Fuzzer: Difference between revisions

From
Jump to navigation Jump to search
(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 1170 and 2603 MHz. Unfortunately, the scaling algorithm in the
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
to make afl-fuzz skip this check - but expect some performance drop.
AFL_SKIP_CPUFREQ
to make afl-fuzz skip this check - but expect some performance drop.
[-] 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.