Fuzzer

From
Revision as of 14:48, 12 October 2015 by Schall (talk | contribs) (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…")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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

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.

  [-] Whoops, your system uses on-demand CPU frequency scaling, adjusted
   between 1170 and 2603 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

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.


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.