Fuzzer: Difference between revisions
(Created page with "Fuzzer sind Programme die ein automatisiertes Testen ermöglichen. Im Gegensatz zu herkömmlicher Testsoftware, werden beim fuzzen zufällige Testcases generiert. In erster Linie…") |
|||
Line 27: | Line 27: | ||
== Konfiguration == |
== Konfiguration == |
||
Beim start von afl-fuzz kann es sein, dass afl auf Einstellungen im System hinweist, die negativen Einfluss auf afl haben und die dementsprechend umgestellt werden sollten. Hiervon nun zwei Beispiele vorgestellt, die bei uns oft aufgetretten sind. |
AFL benötigt eigentlich keinerlei Konfiguration. Beim start von afl-fuzz kann es aber sein, dass afl auf Einstellungen im System hinweist, die negativen Einfluss auf afl haben und die dementsprechend umgestellt werden sollten. Hiervon nun zwei Beispiele vorgestellt, die bei uns oft aufgetretten sind. |
||
[-] Hmm, your system is configured to send core dump notifications to an |
|||
external utility. This will cause issues due to an extended delay |
|||
between the fuzzed binary malfunctioning and this information being |
|||
eventually relayed to the fuzzer via the standard waitpid() API. |
|||
To avoid having crashes misinterpreted as hangs, please log in as root |
|||
and temporarily modify /proc/sys/kernel/core_pattern, like so: |
|||
echo core >/proc/sys/kernel/core_pattern |
|||
[-] PROGRAM ABORT : Pipe at the beginning of 'core_pattern' |
|||
Location : check_crash_handling(), afl-fuzz.c:6926 |
|||
[-] Whoops, your system uses on-demand CPU frequency scaling, adjusted |
[-] Whoops, your system uses on-demand CPU frequency scaling, adjusted |
||
between |
between 781 and 3710 MHz. Unfortunately, the scaling algorithm in the |
||
kernel is imperfect and can miss the short-lived processes spawned by |
kernel is imperfect and can miss the short-lived processes spawned by |
||
afl-fuzz. To keep things moving, run these commands as root: |
afl-fuzz. To keep things moving, run these commands as root: |
||
cd /sys/devices/system/cpu |
cd /sys/devices/system/cpu |
||
echo performance | tee cpu*/cpufreq/scaling_governor |
echo performance | tee cpu*/cpufreq/scaling_governor |
||
You can later go back to the original state by replacing 'performance' with |
You can later go back to the original state by replacing 'performance' with |
||
'ondemand'. If you don't want to change the settings, set |
'ondemand'. If you don't want to change the settings, set AFL_SKIP_CPUFREQ |
||
⚫ | |||
AFL_SKIP_CPUFREQ |
|||
⚫ | |||
[-] PROGRAM ABORT : Suboptimal CPU scaling governor |
[-] PROGRAM ABORT : Suboptimal CPU scaling governor |
||
Location : check_cpu_governor(), afl-fuzz.c:6988 |
Location : check_cpu_governor(), afl-fuzz.c:6988 |
||
Im oberen Beispiel beschwert sich afl das er ungerne im Energiesparmodus ausgeführt werden möchte. Es wird immer erklärt warum man dies nicht haben möchte, wie man die Einstellungen dementsprechend anpasst, beziehungsweise das man mit einer Option (Hier AFL_SKIP_CPUFREQ) diese Meldung umgehen kann. |
|||
Die Fehlermeldungen sind selbsterklärend und können mit den angegebenen Hinweisen leicht behoben werden. Die Einstellungen sind nur temporär und müssen nach einem neustart des Systems wiederholt werden. |
|||
== Testbeispiele == |
== Testbeispiele == |
Revision as of 10:12, 13 October 2015
Fuzzer sind Programme die ein automatisiertes Testen ermöglichen. Im Gegensatz zu herkömmlicher Testsoftware, werden beim fuzzen zufällige Testcases generiert. In erster Linie soll damit getesten werden ob Progamme für nichtspezifizierten Input abstürzen oder hängen bleiben.
Einsatzgebiete
Primär wird Fuzzing zum Suchen von Schwachstellen und Sicherheitslücken benützt. Sicherheitslücken entstehen meist daraus, dass Nutzereingaben nicht hinreichend genau überprüft werden. Beispiele sind z.B. Bufferüberläufe, Formatstingattacken, SQL Injections oder Cross Site Scripting. Durch Fuzzing können Eingaben gefunden werden, die das entsprechende Programm zum absturz bringen. Im Falle von Diensten die über das Netzwerk erreichbar sind, kann dies schon ausreichen um Denial of Service Attacken durchzuführen. In Schwerwiegenderen Fällen kann die Schwachstelle dafür sorgen, dass Fremde Zugriff auf das System erhalten. Eine prominente Lücke, die lange Zeit nicht entdeckt wurde ist Heartbleed. Diese hätte durch Fuzzing entdeckt werden können. https://blog.hboeck.de/archives/868-How-Heartbleed-couldve-been-found.html
AFL (American Fuzzy Lop)
AFL von Michal Zalewski ist ein offener leicht zu bedienender Fuzzer. Es kann unter http://lcamtuf.coredump.cx/afl/ heruntergeladen werden. Für die Benutzung ist fast keine Konfiguration nötig. Es werden lediglich ein Testcase und das zu Testende Programm benötigt. AFL ändert die gegebenen Testcases zufällig ab und testet das Programm auf Abstürze und Ausführgeschwindigkeit.
Installation
In einigen Linux Distributionen ist AFL vorkompiliert enthalten und kann direkt über den jeweiligen Paketmanager heruntergeladen werden. Ist AFL nicht vorhanden, so kann es wie folgt leicht selbst kompiliert werden:
wget http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz tar -xvf afl-latest.tgz cd afl-* make
Mit wget wird die letzte Version von afl runtergeladen und dann mit tar entpackt. Dann wird in den afl-* Ordner gewechselt. Hier kann man nun entscheiden ob man afl richtig installiernen möchte (make install) oder die c-Dateien nur übersetzten möchte (make).
Konfiguration
AFL benötigt eigentlich keinerlei Konfiguration. Beim start von afl-fuzz kann es aber sein, dass afl auf Einstellungen im System hinweist, die negativen Einfluss auf afl haben und die dementsprechend umgestellt werden sollten. Hiervon nun zwei Beispiele vorgestellt, die bei uns oft aufgetretten sind.
[-] Hmm, your system is configured to send core dump notifications to an external utility. This will cause issues due to an extended delay between the fuzzed binary malfunctioning and this information being eventually relayed to the fuzzer via the standard waitpid() API. To avoid having crashes misinterpreted as hangs, please log in as root and temporarily modify /proc/sys/kernel/core_pattern, like so: echo core >/proc/sys/kernel/core_pattern [-] PROGRAM ABORT : Pipe at the beginning of 'core_pattern' Location : check_crash_handling(), afl-fuzz.c:6926
[-] Whoops, your system uses on-demand CPU frequency scaling, adjusted between 781 and 3710 MHz. Unfortunately, the scaling algorithm in the kernel is imperfect and can miss the short-lived processes spawned by afl-fuzz. To keep things moving, run these commands as root: cd /sys/devices/system/cpu echo performance | tee cpu*/cpufreq/scaling_governor You can later go back to the original state by replacing 'performance' with 'ondemand'. If you don't want to change the settings, set AFL_SKIP_CPUFREQ to make afl-fuzz skip this check - but expect some performance drop. [-] PROGRAM ABORT : Suboptimal CPU scaling governor Location : check_cpu_governor(), afl-fuzz.c:6988
Die Fehlermeldungen sind selbsterklärend und können mit den angegebenen Hinweisen leicht behoben werden. Die Einstellungen sind nur temporär und müssen nach einem neustart des Systems wiederholt werden.
Testbeispiele
Beispiel1.c:
#include <stdio.h> #include <string.h> int main (int argc, char **argv) { char test[10]; gets(test); printf("Eingabe: %s\n",test); return 0; }
Beispiel1.c hat ein offensichtliches Problem mit Buffer Overflows. Dies soll der Fuzzer für uns herausfinden. Erstmal übersetzten wir Beispiel1.c mit "gcc -o Beispiel1 Beispiel1.c". Dann setzten wir den Fuzzer auf Beispiel1 an mit: "afl-fuzz -n -i testcases/other/text/ -o out Beispiel1". Mit -n läuft afl als "dumb" fuzzer. Das heißt er hat keine nähere Informationen über die interne Strucktur und den internen Aufbau von Beispiel1 und kann diese somit auch nicht nutzen. Mit -i wird ein Ordner angegeben der die Testcases enthält die als Input für das Programm verwendet werden sollen. In testcases/other/text/ ist nur die hello_world.txt von hello drin steht. Das heißt mit dem Word hello fängt der fuzzer als eingabe an und verändert dies danach auf unterschiedliche weise. Der Ausgabeordner wo die Ergebnisse und anderes gespeichert werden wird mit -o angegeben und muss gegebenenfalls erst erstellt werden. Beispiel1 ist unser Programm was wir fuzzen wollen. Die Eingaben die zu einen Crash oder Hang geführt haben werden im Ausgabeordner unter Crashes oder Hangs gespeichert. Crashes sind mit hoher Warscheinlichkeit richtige Crashes. Bei Hangs muss man durchprüfen ob die Eingaben wirklich zu einen Hang geführt haben, hier gibt es viele False Positives. Also zählen letztendlich nur Crashes. Testen können wir diese mit "cat out/crashes/id:000000* | Beispiel1". Mit "cat out/.cur_input" kann man sich die gerade genutzte Eingabe ansehen.
Beispiel2.c:
#include <stdio.h> #include <stdlib.h> int main (int argc, char **argv) { char buf [128]; fgets(buf,128,stdin); printf(buf); printf("Hello\n"); return 0; }
Beispiel2.c hat ein offensichtliches Problem mit Formatstringangriffen. Dies soll der Fuzzer für uns herausfinden. Erstmal übersetzten wir Beispiel2.c mit "gcc -o Beispiel2 Beispiel2.c". Zusätzlich fügen wir einen weiteren testcase unter testcases/other/text/ hinzu, indem wir eine Datei formatstring.txt erzeugen und dort %s reinschreiben. Um von hello mittels mutation auf irgendetwas mit %s%s%s zu kommen, benötigt der Fuzzer circa eine Stunde. Gibt man aber einen zusätlichen testcase an, der %s enthält, dauert dies nur wenige Minuten. Dann setzten wir den Fuzzer auf Beispiel2 an mit: "afl-fuzz -n -i testcases/other/text/ -o out Beispiel2".
Diese Art des Fuzzens mit -n (dumb Fuzzer) sollte aber inbedingt vermieden werden. Da es intelligentere und damit wesentlich effizientere Arten des Fuzzens gibt. Für die oben gezeigten Minibeispiele reicht es noch aus, aber längere Codebeispiele sollte man damit nicht fuzzen.