Det finns en mängd fuzzers i naturen, däribland Peach och syzkaller. Så varför AFL?
Användningsfallet. Detta är den viktigaste punkten att ta hänsyn till. Mitt användningsfall var att fuzza ett program som tar emot indata från en fil. Det är viktigt att notera att AFL inte har möjlighet att fuzza över nätverk.
Det är enkelt att installera.
AFL:s användargränssnitt innehåller massor av information, bland annat realtidsstatistik över fuzzingprocessen.
Installation av AFL
Installation av AFL är enkelt och jag har gjort det enklare för dig genom att skriva ett enkelt (men grovt) skalskript som installerar det åt dig! Kör skriptet med dina användarrättigheter och det kommer att installera alla beroenden, AFL och relaterade verktyg. Skalskriptet finns här: https://github.com/nikhilh-20/enpm691_project/blob/master/install_afl.sh
Välj programmet att fuzza
I det här inlägget kommer vi bara att titta på fuzzning av de program som vi har källkoden till. Detta beror på att AFL instrumenterar källkoden för att övervaka exekvering, fel och andra saker som rör prestanda. Det är också möjligt att direkt fuzza en körbar fil men det är experimentellt och ligger utanför det här inlägget (tips: det kräver QEMU).
Välj ett valfritt system med öppen källkod från GitHub för fuzzing. Ju mer välkänt ditt val är, desto mindre antal sårbarheter kommer det sannolikt att ha. Andra letar också efter buggar! En enkel metod som jag använder för att hitta sårbar kod är att använda GitHub Search. Så här gör jag:
Sök efter en sårbar funktion, säg strcpy.
Resultaten kommer att vara i miljontals. Gå till kategorin commits i resultaten. Det är där du hittar de repositories där strcpy användes (eller kanske togs bort). Dessa repositories är en bra utgångspunkt för att börja fuzza.
Instrumentering av applikationen
Av integritetsskäl kan jag inte avslöja det repository som jag använder.
Klona git-förrådet.
nikhilh@ubuntu:~$ git clone https://github.com/vuln; cd vuln
Sätt en miljövariabel, AFL_HARDEN=1. Detta aktiverar vissa kodhärdningsalternativ i AFL under kompileringen, vilket gör det lättare att upptäcka minneskorruptionsfel.
nikhilh@ubuntu:~/vuln$ export AFL_HARDEN=1
Inställ vissa kompilatorflaggor, så att programmet kompileras på ett sätt som gör det lätt för oss att hitta (och utnyttja) sårbarheter. Helst skulle vi använda miljövariabler för att ställa in det vi behöver, men det finns en hel del anpassningsmöjligheter. så vi redigerar Makefile direkt.
Säkerställ att kompilatorn som används är afl-gcc eller afl-clang istället för gcc respektive clang. Detta gör det möjligt för AFL att instrumentera källkoden.
Lägg till kompilatorflaggor:
-fno-stack-protector stänger av stackprotektorn, vilket gör det möjligt för oss att utnyttja buffertöverflöden.
-m32 behövs bara om du använder en 32-bitarsmaskin, annars nej.
När du är klar med dessa ändringar är det dags att kompilera programmet. Kör make. När du gör det MÅSTE du se uttalanden som dessa i loggen:
Instrumented 123 locations (32-bit, hardened-mode, ratio 100%).
Om du inte ser sådana uttalanden betyder det att AFL inte har aktiverat applikationens kod för fuzzing. Med andra ord har den inte instrumenterat källkoden framgångsrikt.
Testprov
AFL är en evolutionär typ av fuzzer. Det innebär att den, liksom generationsbaserade fuzzerare, också kräver inledande testdata för att förstå vilken typ av data som målprogrammet förväntar sig. När man riktar in sig på system med öppen källkod är detta lätt att hitta. Titta bara i deras testkatalog så hittar du alla testdata du behöver.
nikhilh@ubuntu:~/vuln$ mkdir afl_in afl_out
nikhilh@ubuntu:~/vuln$ cp test/* afl_in/
Fuzzing Begins
Nu när vi har våra testprover är vi redo att fuzza!
Oh, vänta… vi måste också ändra var applikationens kraschmeddelanden går till. By default, when an application crashes, the core dump (basically, the contents of RAM are stored in a file to help in debugging) notification is sent to the system’s core handler. We don’t want this. Why? By the time this notification reaches AFL, it’ll be classified as a timeout rather than a crash.
nikhilh@ubuntu:~/vuln$ sudo su
password for nikhilh:
root@ubuntu:/home/nikhilh/vuln# echo core > /proc/sys/kernel/core_pattern
root@ubuntu:/home/nikhilh/vuln# exit
NOW, we are ready to fuzz!
nikhilh@ubuntu:~/vuln$ afl-fuzz -i afl_in -o afl_out -S slaveX — ./vuln @@
Command line flags used:
-i — This marks the test input directory. Det är här vi lagrade de ursprungliga testdata.
-o- Detta är katalogen där AFL skriver användbar information om krascher, hängningar etc.
-S – Detta är slavläget. I princip kommer AFL att slumpmässigt modifiera inmatningen vilket orsakar icke-deterministisk fuzzing.
-M-alternativet är Master-läget som är deterministisk fuzzing, vilket i princip innebär att varje bit av inmatningen modifieras på något sätt. (Detta är långsamt! … Uppenbarligen.)
@@ – Detta är den position där testfilen för indata kommer att vara. AFL ersätter detta för dig automatiskt. Om din körbara fil tar inmatning från STDIN behövs inte detta.
Fuzzing Results
Det här kommer att ta lite tid att visa. Det händer ofta att folk fuzzar i mer än 24 timmar (och kanske slutar med ingenting). I mitt fall tror jag att applikationen var lite för sårbar, så jag hade 516 unika krascher inom en timme. Det betyder dock inte att det finns 516 sårbarheter!
Du kan avsluta fuzzing-sessionen med en Ctrl-C.
Analysis Phase
Now that we have results, we need to analyze them to see which ones are exploitable. To this end, we will use one of AFL’s utilities called afl-collect. This will have been installed through the installation script as well.
nikhilh@ubuntu:~/afl-utils$ afl-collect -d crashes.db -e gdb_script -r -rr ~/vuln/afl_out/slaveX ./output_dir — ~/vuln/vuln
To understand what each command line flag does, refer to its help section.
nikhilh@ubuntu:~/afl-utils$ afl-collect — help
If you see lines such as these in the output, celebrate! You’ve found something interesting to try and exploit.
*** GDB+EXPLOITABLE SCRIPT OUTPUT ***
…
…
slaveX:id:000000,sig:11,src:000000,op:havoc,rep:2……………:EXPLOITABLE
…
slaveX:id:000046,sig:11,src:000004,op:havoc,rep:4……………:EXPLOITABLE
…
AFL visar dig vilken indata som fick programmet att krascha. I det här fallet orsakade filen: id:000046,sig:11,src:000004,op:havoc,rep:4 ett StackBufferOverflow i programmet. Sådana filer kan hittas under ../afl_out-slaveX/crashes/
Done!
Det var allt för en snabbstart i fuzzing! Processen är verkligen enkel och mycket bekväm eftersom allt är automatiserat. Nästa steg skulle vara att analysera varför inmatningen orsakade ett buffertöverflöde och söka efter ett sätt att utnyttja det. Kom ihåg att inte alla sårbarheter kan leda till en exploatering.