天天看点

mongodb – SSJI to RCE

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…