Trying some server side javascript injection in mongodb, I wondered if it would be possible to pop a shell.
Unfortunately, this command is only effective in mongo client :
But let’s dig a little bit.
So you can run the « run » function directly by calling nativeHelper.apply(run_,["uname","-a"]);
In server side, the result show us that nativeHelper.apply method exists !
So what’s run_ ?
An associative array, can we use it in server side ?
The server crashed \o/ !
Let’s check the source code :
./src/mongo/scripting/engine_spidermonkey.cpp
nativeHelper is a crazy feature in spidermonkey missused by mongodb:
the NativeFunction func come from x javascript object and then is called without any check !!!
Challenge now is to make a reliable exploit bypassing NX and ASLR (on x86 32bits for the moment).
To achieve this let’s debug it !
The func NativeFunction take 2 arguments : the first one is the arguments array from javascript call inBSONObj format.
The second one is a number from y.
In gdb if we look at eax when the crash occurs [eax]=pointer on our BSONObj
So we need gadgets to pivot in the [[eax]]+>0xb
This one will dereference eax and then call [eax+0x1c] that we control.
So we can put a second gadget to xchg esp, eax at our arguments+0×11
This gadget must also increment esp to point in our buffer and not in BSONObj structure.
Here is a little problem : arguments is UTF-8 encoded so we have to find gadgets with bytes inferior to 0x7f.
0×08457158 respects it :
So the ret will fall in arguments+0×01, that’s okay for us, we can put another gadget here.
We need to increment the stack pointer to escape the second gadget at arguments+0×11
Here we go ! Our stack is controlled, but the UTF-8 limitation is really bad, themmap64@plt is at address
0x816f768 so we can’t use it inarguments. Let’s pivot again.
As we are in javascript environment the same techniques used in browser could be effective !
Sorry but we will heapspray !
The first one with NOP+SHELLCODE and we will mmap it RWX.
The second one with our RETCHAIN+ROPCHAIN that call mmap without UTF-8 limitation.
0×20202020 => RETCHAIN+ROPCHAIN
So we need a gadget to put it in eax then xchg esp, eax again.
then 0×08457158, the same as above will pivot the stack.
Here we go again ! Our stack is controlled without any contraints !
The next part is simple as mmap64 is directly callable via plt.
Return to mmap64@plt : 0x816f768 and stack look like that
Here is the total exploit :
This feature/vulnerability was reported 3 weeks ago to 10gen developers, no patch was commit but the default javascript engine was changed in last version so there is no more nativeHelper.apply function.
A metasploit module is comming soon…