mardi 20 janvier 2015

Let's have (not) fun with afl

And that's a part two for an extreme exploitation of my previous bug found with afl. It was a crash in cabextract.

And it's a double fail.

1/ First fail
This crash is just a null pointer dereference. There is a lot of documentation in internet for it, and in that case, that's just not interesting at all. In order to be exploitable, you have to map an executable page at offset 0 and trigger the crash.

Here is a nice doc talking about null deref. Here is another blogspot explaining how to exploit null deref in linux kernel (now it's protected).

Short story short: "In the realm of userland applications, exploiting them usually requires being able to somehow control the target's allocations until you get page zero mapped, and this can be very hard."

2/ Second fail
This bug is known and corrected! You can see a nice explanation in debian bugtracker.

So,  nothing to do here, and moving for next target!

Mitsurugi

mercredi 14 janvier 2015

Let's have some fun with afl

1/ Let's play

Let's play with the fuzzer afl. I'll write some blogposts about my research with afl. This can be seen as a diary of a fuzzer :-)

2/ At first, choose your target

I think that afl has been pretty much used on usual unix binaries (compressor, file format, and so on), so I did a
$ ls /usr/bin

and choose one of them in order to fuzz. afl is great at fuzzing programs which take a file as argument and don't produce too much output. There is a lot of them which can be fuzzed.

That's easy, just grab the sources of the binary you want to fuzz, recompile it using afl-gcc (or afl-g++), and roll!
Sometimes, it's better to desactivate checksum computations: fuzzing goes faster, fuzzing goes farther (doesn't stop for a bad checksum) and in case of a crash, you can easily recalculate the checksum and see if crash is still here.

After fuzzing a lot of software, I managed to reach two crashes:

That's enough for a good start. Those two crashes will be investigated.

I don't look at hangs: my computer do a lot of things (loadavg > 1 most of the time), and afl has an aggressive value of 50ms for saying that program has stopped. So, there is a lot of false positive. And I'm mostly interested in crashes anyway.

3/ Keep focused

Afl comes with an handy helper call Peruvian were rabbit. Just feed afl-fuzz with some known files causing a crash and it will make some variation around it in order to see if some new crashes appears.

$ cd ..
$ mkdir crashes crashes/findings crashes/testcases
$ cp fuzzy/findings/crashes/id\:000001* crashes/testcases/case1
$ cp fuzzy/findings/crashes/id\:000002* crashes/testcases/case2
$ cd crashes
$ afl-gcc -C -i testcases/ -o findings/ unnamed -t @@

And unsurprisingly, number of crashes grow very fast:

I have now 255 files causing crashes.

What's really interesting in my case is that the unmodified program (the one doing checksum) segfaults too :-) It writes a message "bad checksum", but segfault like a boss:

mitsurugi@mitsu:~/fuzz$ ./unnamed-no-cksum -t case1
Segmentation fault
mitsurugi@mitsu:~/fuzz$ ./unnamed-ori -t case1
    failed (checksum error)
Segmentation fault
mitsurugi@mitsu:~/fuzz$


mitsurugi@mitsu:~/fuzz$ ./unnamed-no-cksum -t case1
Segmentation fault

mitsurugi@mitsu:~/fuzz$ dmesg | tail -1
[784784.901989] unnamed-no-cksum[29344]: segfault at 0 ip   (null) sp bf89d38c error 14 in unnamed-no-cksum[8048000+57000]
And it seems promising, because it crash on a bad EIP value (and not a losy read or write in forbidden location). My senseï said:

"If you manage to control EIP, you'll soon manage to control the world"

4/ Let's investigate

I have a good lead, the next step is to force EIP to a choosen value (0x41414141 for example) instead of 0x00000000.

The crash appears here:
=> 0x804daf0:    call   DWORD PTR [eax+0x40]
   0x804daf3:    cmp    eax,0x3
   0x804daf6:    je     0x804db54


And the memory layout around eax is:
gdb$ x/12dwx $eax + 0x30
0x80618b0:   0x0804a580    0x0804a560    0x00000000    0x0000eaea
0x80618c0:   0x00000000    0x00000000    0x080601e8    0x08060080
0x80618d0:   0x00000000    0x080618dc    0x080618dc    0x00000000
gdb$


unfortunately, I don't have 0xeaea followed by some 0x00 in source file. So I think I'll have to dig really further.

I also have 255 files, I choose 10 of them, all of them crash with EIP=0x00000000. It's time to industrialize the checkings.

That's all for today :-)
Mitsurugi

mardi 6 janvier 2015

Is fuzzing obsolete? No, afl rocks!

1/ Intro

Is fuzzing obsolete? I've read an interesting presentation given at NosuchCon about analyzing execution of binaries.

One slide was saying that fuzzing is over:

So, let's try it with afl, or american fuzzy lop. As everybody knows, american fuzzy lop is a rabbit, but few knows that it's a really powerful fuzzer made by lcamtuf.

Afl can instrumentate the code in order to follow some path, instead of relying on chance only.

2/ Dumb mode, before afl

If I rely with chance only, with an initial buffer "good", and with 1000 try/seconds, I will have to wait (2^32/1000/3600/24) = 49 days to trigger a crash. That's not really efficient.

3/ AFL powerful execution mode

In order to use afl, you have to recompile your binaries with afl-gcc (wrapper around gcc). It's easy: download afl, compile it, then add in your path the build directories like:

export PATH=$PATH:/home/mitsurugi/fuzz/afl-0.88b/
export AFL_PATH=/home/mitsurugi/fuzz/afl-0.88b/

(protip: your PATH should be set before afl, i.e. PATH=afl-dir/:$PATH won't work)

and rocks:

Now the code is instrumented, we just have to launch afl-fuzz:

And in less than an hour (!!!) afl trigger the crash:

That's incredible. Dumb fuzz was expecting 49 days.

4/ conclusion

So, I think that we can say that fuzzing is not over yet :-) Let's start afl everywhere in every progs!

I've currently trigger a crash in a common unix utility, but it's not exploitable (working on it, but it's hard, I can write some 0 in a not really arbitrary location :-( ).

What I miss so much is the same fuzzer for networking utility. Kind of :
printf 'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n' > tescases/request
afl-fuzz -i testcases/ -o findings httpd @@