Skip to main content
Wachter Space ūüöÄ
  1. Posts/

Fuzzing Schutzmaßnahmen

Dieser Blogeintrag ist eine Seminararbeit, die ich im Sommersemester 2020 im Rahmen des Seminars Schwachstellensuche am KIT geschrieben habe. Ich habe das LaLeX einmal durch pandoc gejagt, sodass ich es hier auf meinen Blog schmeißen kann. Möglicherweise leidet die Formatierung darunter.

Das Seminar selbst war wie einen Konferenz gestaltet, inklusive Peer-Reviews von anderen Teilnehmern des Seminars mit HotCRP. Dabei habe ich √ľber das Inhaltliche hinaus noch viel √ľber den Prozess des Peer-Review gelernt.

Abstract #

Fuzzing ist eine Technik zur automatisierten Schwachstellensuche in Software. Im Vergleich zu einem menschlichen Analysten erm√∂glicht Fuzzing kosteng√ľnstige Schwachstellensuche im gro√üen Ma√üstab. Aktuelle Forschung versucht Schutzma√ünahmen zu entwickeln, die Bin√§rprogramme vor Schwachstellensuche durch Fuzzing sch√ľtzen. Damit sollen kritische Anwendungen vor b√∂sartigen Angreifern gesch√ľtzt werden, die Fuzzing anwenden.

Diese Arbeit gibt einen breiten √úberblick √ľber aktuelle Ans√§tze Fuzzing zu erschweren, beschreibt deren Wirkungsweise und Anwendbarkeit. Au√üerdem werden f√ľr viele der Schutzma√ünahmen M√∂glichkeiten zur Entfernung, Umgehung oder Abschw√§chung genannt.

Alternatives Abstract (kein Teil der Seminararbeit) #

Falls man die Idee auf die Idee kommt sich vor Fuzzern ‚Äěsch√ľtzen‚Äú zu wollen, ist der erst Teil der Seminararbeit die perfekte Anleitung daf√ľr. Im zweiten Teil wird dann gezeigt, dass von den Schutzma√ünahmen viel eher zur Kategorie Security-Snakeoil geh√∂rt, die einen Angreifer vielleicht etwas nerven aber sicherlich nicht abhalten k√∂nnen. Trotzdem ist es akademisch spanned sich damit zu besch√§ftigen was eine Worst-Case Eingabe f√ľr einen Fuzzer sein k√∂nnte. In der Praxis w√ľrde ich Fuzzing-Schutzma√ünahmen allerh√∂chstens f√ľr CTF-Challenges empfehlen. Wenn jemand Fuzzing-Schutzma√ünahmen ‚Äěin-the-wild‚Äú findet, w√ľrde ich mich freuen davon zu h√∂ren und mir das Programm mal genauer anzuschauen.

Einleitung

Die Fuzzing zugrunde liegende Idee besteht darin, ein Programm auf einer gro√üen Menge von automatisch generierten Eingaben auszuf√ľhren und sein Verhalten dabei zu beobachten. St√ľrzt das Programm auf einer Eingabe beispielsweise ab oder wird ein Speicherzugriff in einen nicht allozierten Bereich beobachtet, so wurde ein Bug gefunden. Dieser Bug dient dann als Grundlage f√ľr die Suche nach einer ausnutzbaren Schwachstelle. Die erste Implementierung eines Fuzzers stammt bereits aus den fr√ľhen Neunzigerjahren¬†(Miller, Fredriksen, and So 1990; Sutton, Greene, and Amini 2007). Mit seitdem entwickelten neuen Fuzzern, die sich vor allem auch die zunehmende Rechenleistung von heutigen Computern zunutze machen, wurden bereits zahlreiche Schwachstellen gefunden. Alleine ClusterFuzz, eines von mehren Fuzzing-Projekten von Google, hat Stand Februar 2019 mehr als 27000 Bugs gefunden¬†(Arya et al. 2019). Aktuell gibt es Bestrebungen, den Prozess des Fuzzings weiter zu automatisieren¬†(Chang et al. 2017). Gefundene Bugs k√∂nnen automatisiert, bez√ľglich ihres Potenzials als Schwachstelle ausnutzbar zu sein, kategorisiert werden¬†(Tonder, Kotheimer, and Goues 2018). Es gibt au√üerdem erste Ans√§tze, Fuzzing auf eine gro√üe Menge von unbekannten Programmen und Bibliotheken anzuwenden, ohne manuelle Anpassungen oder Konfiguration durch Menschen zu erfordern¬†(Ispoglou et al. 2020).

F√ľr einige kritische Programme gibt es das Bestreben, Schwachstellensuche nur autorisierten Parteien zu erm√∂glichen. Dritten Parteien, die nur √ľber eine Bin√§rversion des Programms verf√ľgen, soll die Schwachstellensuche m√∂glichst erschwert werden. In der Vergangenheit lag der Fokus beim Schutz gegen Schwachstellensuche haupts√§chlich auf Obfuscation-Techniken, die Schutz vor menschlichen Analysten bieten¬†(Behera and Bhaskari 2015). Bisher √ľberpr√ľfte Obfuscation-Techniken bieten keinen umfangreichen Schutz gegen Fuzzing¬†(G√ľler et al. 2019b; Jung et al. 2019b; Banescu et al. 2016). Genau wie Obfuscation machen es Schutzma√ünahmen gegen Fuzzing nicht unm√∂glich, Schwachstellen durch Fuzzing zu finden, sondern sie vergr√∂√üern nur die Kosten und M√ľhen, die ein Angreifer aufwenden muss. Idealerweise so stark, dass andere Techniken der Schwachstellensuche erfolgversprechender werden¬†(Banescu et al. 2016). Es ist zu erwarten, dass in Zukunft neue Ans√§tze publiziert werden, die Fuzzing-Schutzma√ünahmen vorschlagen, und andere, die diese wieder umgehen. Hier sind Analogien zu der Entwicklung von Obfuscation-Techniken oder auch zum Schutz gegen automatisierte Schwachstellensuche im Internet m√∂glich. In keinem der F√§lle werden bestehende Schwachstellen behoben, sondern nur deren Auffinden erschwert.

Das Ziel dieser Seminararbeit ist es, Ans√§tze zu beschreiben, die aktuelle Schutzma√ünahmen gegen Fuzzing umgehen oder abschw√§chen. Hierbei wird in einigen Teilen der Arbeit die Perspektive eines Angreifers eingenommen, der sich mit einem gesch√ľtzten Programm konfrontiert sieht. Dies hat zum Zweck, Fuzzing-Schutzma√ünahmen in einem realistischen Szenario zu betrachten. Es wird ein Angreifer angenommen, der mit m√∂glichst geringem Aufwand viele Schwachstellen finden m√∂chte. Der Angreifer hat lediglich Zugriff auf das mit Fuzzing-Schutzma√ünahmen versehene Bin√§rprogramm. Weiter wird angenommen, dass der Angreifer Kenntnis von den Fuzzing-Schutzma√ünahmen besitzt. Diese Annahme ist aus zwei Gr√ľnden gerechtfertigt. Zum einen, da die zugrundeliegenden Schutzma√ünahmen teilweise zusammen mit Implementierungen ver√∂ffentlicht sind¬†(G√ľler et al. 2019b; Jung et al. 2019b; Edholm and G√∂ransson 2016). Zum anderen da, wie in Kapitel¬†4 beschrieben, Fuzzing-Schutzma√ünahmen zus√§tzliches Potenzial f√ľr Schwachstellen bieten und eigene Implementierungen im Vergleich zu Standard-Open-Source-Implementierungen ein h√∂heres Risiko daf√ľr bergen, dass solche Schwachstellen √ľber l√§ngere Zeit bestehen bleiben.

Kapitel¬†2 gibt einen √úberblick √ľber Kategorien von Fuzzern. Kapitel¬†3 nennt verwandte Arbeiten im Themenfeld der Fuzzing-Schutzma√ünahmen. Kapitel¬†4 beschreibt bestehende Arten von Fuzzing-Schutzma√ünahmen. F√ľr die beschriebenen Schutzma√ünahmen werden in Kapitel¬†5 M√∂glichkeiten beschrieben, diese in Bin√§rprogrammen zu erkennen. Erkannte Schutzma√ünahmen k√∂nnen dann entfernt, umgangen oder, falls das nicht m√∂glich ist, zumindest ber√ľcksichtigt werden.

Hintergrund

Fuzzing ist weit mehr als nur zuf√§llige Eingaben an ein Programm zu geben und zu hoffen, dass es abst√ľrzt. Es gibt verschiedene Arten von Fuzzern, die mit unterschiedlichen Strategien Eingaben erzeugen und deren Auswirkung auf unterschiedliche Arten messen und ber√ľcksichtigen. Um Fuzzing-Schutzma√ünahmen verstehen und bewerten zu k√∂nnen, ist zuerst ein √úberblick √ľber existierende Arten von Fuzzern notwendig.

Die konzeptionell einfachsten Fuzzer sind sogenannte Black-Box-Fuzzer, auch blinde Fuzzer genannt. Diese erzeugen Eingaben gem√§√ü einer Mutationsengine und nehmen Ausgaben oder einen sichtbaren Absturz des Programms als einziges Feedback vom Programm entgegen. Die Mutationsengine ver√§ndert die Eingaben nach bestimmten Mustern. Solche Muster k√∂nnen beispielsweise die √Ąnderung von Zahlen, das Vertauschen von Bytes oder das Einf√ľgen un√ľblicher Zeichen beinhalten. Ein Beispiel hierf√ľr ist der Fuzzer Radamsa¬†(‚ÄúRadamsa‚ÄĚ n.d.). Es gibt auch Fuzzer, welche die Ausgaben zweier Programme bei gleicher Eingabe miteinander vergleichen, um bei einer Abweichung auf einen Bug in einem der beidem Programme schlie√üen zu k√∂nnen, zum Beispiel zum Testen von Numerik-Bibliotheken. Solche Fuzzer sind im Weiteren nicht Gegenstand der Betrachtung. Diese Arbeit ist au√üerdem auf das Fuzzen von lokal ausf√ľhrbaren Programmen fokussiert, wobei die genannten Beispiele auf C-Programmen in einer Linux-Umgebung basieren. Viele der genannten Methoden lassen sich auch in anderen Kontexten und f√ľr andere Sprachen anwenden. Black-Box-Fuzzer ben√∂tigen einen umfangreichen Korpus an Programmeingaben, um daraus zielf√ľhrende neue Eingaben generieren zu k√∂nnen. Typischerweise beinhaltet ein initialer Eingabekorpus eine Mischung aus g√ľltiger und ung√ľltiger Programmeingaben, gem√§√ü der (m√∂glicherweise informellen) Programmspezifikation. Andere Fuzzer arbeiten mit einer Grammatik des Eingabeformats, um Eingaben zu erzeugen. Beide Arten Eingaben zu erzeugen setzen Wissen √ľber das Eingabeformt voraus. Demgegen√ľber stehen White-Box-Fuzzer und Gray-Box-Fuzzer. Diese instrumentieren das Programm auf verschiedene Arten, um die Auswirkungen von Eingaben innerhalb des Programms beobachten zu k√∂nnen. Eine verbreitete Art neue Eingaben zu erzeugen ist, die Programmabdeckung zu messen, die durch eine Eingabe erziehlt wurde. Darauf basierend werden neue Eingaben erzeugt, die neue Teile des Programms abdecken. Abdeckung kann auf verschiedene Arten gemessen werden, zum Beispiel durch abgedeckte Knoten oder abgedeckte Kanten im Kontrollflussgraph des Programms. Dabei muss der Kontrollflussgraph nicht initial vorliegen, sondern kann auch iterativ erstellt und erweitert werden. Fuzzer die Programmabdeckung verwenden, nennt man abdeckungsgesteuert. Eine weitere Art von Fuzzern benutzt symbolische Ausf√ľhrung, um zielgerichteter Zusammenh√§nge zwischen dem internen Verhalten des Programms und der Eingabe herstellen zu k√∂nnen. Hierf√ľr werden, zum Beispiel mithilfe von SMT-L√∂sern, Bedingungen im Kontrollfluss aufgel√∂st. Au√üerdem gibt es Fuzzer, die zuerst eine statische Analyse des Quelltexts durchf√ľhren und basierend darauf gezielt verd√§chtige Stellen des Programms fuzzen¬†(Shastry et al. 2017). Neben diesen verbreiteten Ans√§tzen hat die aktuelle Forschung eine Reihe weiterer Klassen von Fuzzern entwickelt, die verschiedene Herausforderungen der klassischen Fuzzer adressieren. Beispiele hierf√ľr sind redqueen, ein Fuzzer, der Pr√ľfsummen-Vergleiche entfernen kann¬†(Aschermann et al. 2019), T-Fuzz ein Fuzzer, der durch Programmtransformationen irrelevante Programmteile entfernen kann¬†(Peng, Shoshitaishvili, and Payer 2018), IJON, ein durch von Experten eingef√ľgten Annotationen gesteuerter Fuzzer¬†(Aschermann et al. 2020) oder NEUZZ, ein durch maschinelles Lernen gesteuerte Fuzzer¬†(She et al. 2019). Fuzzer k√∂nnen durch verschiedene Beobachtungen auf einen Bug im Programm schlie√üen. Eine Klasse von Bugs sind solche, die zu Programmabst√ľrzen f√ľren. Diese k√∂nnen durch die R√ľckgabe des Programms, Signale oder Zeitlimits (keine Reaktion vom Programm) festgestellt werden. Zus√§tzlich kann im Fuzzing-Prozess Sanitation, zum Beispiel Address-Sanitation, eingesetzt werden, um Bugs zu finden, die nicht unmittelbar in einem Absturz resultieren. Address-Sanitizer detektieren unzul√§ssige Speicherzugriffe, zum Beispiel Puffer√ľberl√§ufe.

Eine weitere Unterscheidung von Fuzzern ist die Form des zu testenden Programms. Da sich diese Arbeit auf lokal ausf√ľhrbare C-Programme bezieht, sind m√∂gliche Formen der Programmquelltext oder ausschlie√ülich das Bin√§rprogramm. Quelltext bietet mehr M√∂glichkeiten f√ľr Fuzzer. Insbesondere Fuzzer, die umfangreiche Instrumentierung vornehmen oder statisch im Quellcode nach interessanten Stellen suchen ben√∂tigen den Programmquelltext. Um Bin√§rprogramme zu fuzzen, wird typischerweise der Prozessor emuliert. Hierf√ľr gibt es beispielsweise QEMU, das zusammen mit dem verbreiteten Fuzzer AFL benutzt werden kann. Bis vor Kurzem war auch Address-Sanitation in Bin√§rprogrammen schwer zu erzielen. Mit RetroWrite gibt es heute jedoch eine automatisierte Methode dazu¬†(Dinesh et al. 2020).

Aktuelle Forschung zu Fuzzing-Schutzmaßnahmen

Ans√§tze, die Fuzzing erschweren, sind nicht neu. Ein Blogartikel von Whitehouse¬†(Whitehouse 2014) aus dem Jahre 2014 beschreibt oberfl√§chlich eine Reihe von Indikatoren, die einem Programm andeuten, dass es gefuzzt wird. F√ľr den Fall, dass ein Fuzzer erkannt wird, schl√§gt der Autor verschiedene Ma√ünahmen vor, die Fuzzer fehlleiten. Dabei werden Ma√ünahmen f√ľr verschiedene Plattformen (Betriebssysteme, Android-Apps, Web-Anwendungen und Bin√§rprogramme) aufgez√§hlt. √Ąhnliche Methoden wurden schon im Jahre 2010 in einer nicht publizierten Arbeit von C. Miller beschrieben¬†(Miller 2010).

Edholm et al.¬†(Edholm and G√∂ransson 2016) beschreiben Ma√ünahmen, die die etablierten Fuzzer AFL und Honggfuzz erkennen und fehlleiten sollen. Dabei sind die beschriebenen Ma√ünahmen auf die spezifischen Implementierungen von AFL und Honggfuzz angepasst und zu gro√üen Teilen nicht f√ľr andere Fuzzer generalisierbar.

Eine Arbeit von G√ľler et al.¬†(G√ľler et al. 2019b) identifiziert Fuzzing-Schutzma√ünahmen, die f√ľr gro√üe Klassen von Fuzzern g√ľltig sind. Dazu werden grundlegende Annahmen identifiziert, die Fuzzer treffen, um erfolgreiche Tests des Programms durchf√ľhren zu k√∂nnen. Die Annahmen sind so generell, dass alle aktuellen Fuzzer auf mindestens einer der Annahmen beruhen, und die Autoren davon ausgehen, dass dies auch f√ľr zuk√ľnftige Fuzzer der Fall sein wird. Um die Schutzma√ünahmen zu evaluieren, die sich nur auf Bin√§rprogramme beziehen, und dabei zuk√ľnftige Verbesserungen von Fuzzern zu ber√ľcksichtigen, werden Fuzzer verwendet, die den Quelltext des Programms ben√∂tigen. Die in¬†(G√ľler et al. 2019b) gefundenen Annahmen sind:

  1. [antifuzz_one] Die von einem Fuzzer erreichte Programmabdeckung steht im Verhältnis zu der getesteten Funktionalität des Programms.

  2. [antifuzz_two]Der Fuzzer kann Abst√ľrze des Zielprogramms erkennen.

  3. [antifuzz_three] Der Fuzzer kann eine gro√üe Anzahl von Ausf√ľhrungen pro Sekunde des Zielprogramms erreichen. (Aktuelle Fuzzer k√∂nnen das Zielprogramm hunderte bis tausende Male pro Sekunde ausf√ľhren.)

  4. [antifuzz_four] Kombinationen von Sprungbedingungen k√∂nnen gel√∂st werden. (Damit Fuzzer symbolische Ausf√ľhrung anwenden k√∂nnen, m√ľssen die Sprungbedingungen, beziehungsweise Kombinationen aus diesen, mit √ľberschaubarem Aufwand, zum Beispiel von SMT-L√∂sern, gel√∂st werden k√∂nnen.)

Auf Basis dieser Annahmen, beschreiben die Autoren Schutzma√ünahmen und implementieren diese. Die Implementierung wird als eine Bibliothek mit dem Namen AntiFuzz bereitgestellt¬†(G√ľler et al. 2019a). AntiFuzz stellt Entwicklern eines zu sch√ľtzenden Programms Funktionen bereit, die an geeigneten Positionen im Programm aufzurufen sind, zum Beispiel bei Gleichheitsvergleichen oder zu Beginn des Programms. Die Implementierung beinhaltet, wie in Kapitel¬†5 n√§her beschrieben, keinen Schutz gegen das Entfernen der Schutzma√ünahmen.

Ein zeitgleich erschienene Arbeit von Jung et al.¬†(Jung et al. 2019b) hat ebenfalls zum Ziel, Schutzma√ünahmen gegen aktuelle Fuzzer zu implementieren. Dabei gehen die Autoren noch einen Schritt weiter, indem sie die Schutzma√ünahmen automatisch beim Kompilierungsvorgang anwenden. Dazu haben sie eine Implementierung mit dem Namen Fuzzification ver√∂ffentlicht¬†(Jung et al. 2019a). Fuzzification ben√∂tigt eine Menge g√ľltiger Programmeingaben sowie eine Menge ung√ľltiger Programmeingaben, um automatisiert Schutzma√ünahmen anwenden zu k√∂nnen.

Arten von Fuzzing-Schutzmaßnahmen

Da noch keine allgemeine Definition f√ľr Fuzzing-Schutzma√ünahmen in der Literatur zu finden ist, wird f√ľr diese Arbeit die formale Definition eines Obfuscators von Barak et al.¬†(Barak et al. 2001) mit den Annahmen √ľber Fuzzer von G√ľler et al.¬†(G√ľler et al. 2019b) kombiniert. Daraus ergeben sich folgende Eigenschaften f√ľr eine Fuzzing-Schutzma√ünahme. (Es k√∂nnen mehrere Fuzzing-Schutzma√ünahmen kombiniert werden, indem sie nacheinander angewendet werden.)

  1. [prop_one] Das gesch√ľtzte Programm muss funktional √§quivalent zum ungesch√ľtzten Programm sein, also gleiche Eingaben m√ľssen in gleichen Ausgaben resultieren.

  2. [prop_two] Das gesch√ľtzte Programm darf, relativ zum ungesch√ľtzten Programm, h√∂chstens polynomiell gr√∂√üer und langsamer sein.

  3. [prop_three] Die Fuzzing-Schutzma√ünahme bricht mindestens eine der √ľber Fuzzer in¬†(G√ľler et al. 2019b) getroffenen Annahmen.

Wobei Fuzzing-Annahme¬†[antifuzz_two] (Eigenschaft¬†[prop_three]) generalisiert werden muss zu: Der Fuzzer kann Fehlverhalten des Zielprogramms erkennen. Diese Generalisierung ist notwendig, da es Fuzzer gibt, die nicht nur Bugs finden, die zu einem Absturz f√ľhren, sondern, beispielsweise durch Address-Sanitation, auch andere Klassen von Bugs. Insbesondere da mittlerweile durch¬†(Dinesh et al. 2020) Address-Sanitation auch automatisch auf Bin√§rprogramme (falls Address Space Layout Randomization verwendet wird) angewendet werden kann, ist diese Generalisierung auch f√ľr das beschriebene Angreifer-Modell relevant. Keine der im Folgenden vorgestellten Schutzma√ünahmen bricht diese generalisierte Annahme.

Die Definition zeigt, dass eine Fuzzing-Schutzma√ünahme nicht gegen jeden Fuzzer erfolgreich sein muss, es muss aber eine grundlegende Annahme einer Klasse von Fuzzern gebrochen werden. Um ein Programm allgemein vor Fuzzing zu sch√ľtzen, ist also eine Kombination von Ma√ünahmen n√∂tig, sodass alle Annahmen gebrochen werden.

Erkennung von Fuzzern

Um Schwachstellensuche durch Fuzzing zu verhindern, kann das Programm versuchen, zu detektieren, ob es gefuzzt wird. Falls ein Fuzzer erkannt wird, k√∂nnen die in Abschnitt¬†4.2 beschriebenen Schutzma√ünahmen aktiviert oder verst√§rkt werden oder das Programm zeigt ein ganz anderes Verhalten, indem es ausschlie√ülich einen trivialen bugfreien Teil des Programms ausf√ľhrt.

Einige Fuzzer nutzen ptrace zur Absturzerkennung oder zur Triage von Bugs¬†(Edholm and G√∂ransson 2016; G√ľler et al. 2019b). Au√üer von Fuzzern wird ptrace direkt von menschlichen Analysten oder von Debuggern verwendet. Programme k√∂nnen detektieren, ob sie mit ptrace beobachtet werden, indem sie versuchen ptrace auf sich selbst aufzurufen. Ein Prozess kann nicht gleichzeitig von mehreren anderen Prozessen mit ptrace beobachtet werden. Wenn das Programm sich also nicht selbst mit ptrace beobachten kann, so wird das Programm gerade analysiert, m√∂glicherweise durch einen Fuzzer.

Ein hinreichendes Kriterium zur Fuzzer-Erkennung ist das Vorhandensein bestimmter Umgebungsvariablen, die typisch f√ľr konkrete Fuzzer sind¬†(Edholm and G√∂ransson 2016; Huet 2017). Dieses Kriterium ist zwar hinreichend, aber nat√ľrlich nicht notwendig, es kann nur bekannte Fuzzer abdecken und durch einfache √Ąnderungen versagt dieses Kriterium. Weitere spezifische Erkennungskriterien, wie die √úberpr√ľfung auf das Vorhandensein bestimmter Dateien, sind vorstellbar.

Fuzzer ben√∂tigen meist ein initiales W√∂rterbuch, um darauf aufbauend neue Eingaben generieren zu k√∂nnen. Eine verbreitete Methode, an dieses initiale W√∂rterbuch zu gelangen, ist es alle Zeichenketten in einem Programm zu extrahieren¬†(Shastry et al. 2017). Dies ist ohne Wissen √ľber das Eingabeformat m√∂glich. Somit k√∂nnen auch Magic-Values gefunden und in das W√∂rterbuch aufgenommen werden. Als Detektionsma√ünahme wird eine Zeichenkette als Honeypot im Programm platziert. Der Honeypot wird als eine f√ľr einen normalen Nutzer sehr unwahrscheinliche Zeichenkette gew√§hlt. Der Fuzzer hingegen wird die extrahierte Zeichenkette verwenden. Bekommt das Programm den Honeypot als Eingabe, so wurde Fuzzing oder eine andere Art der Schwachstellensuche erkannt. Diese Ma√ünahme funktioniert am besten, wenn das Programm √ľber eine M√∂glichkeit verf√ľgt, Daten √ľber mehrere Ausf√ľhrungen hinweg zu speichern, da nicht bei jeder Ausf√ľhrung mit einem Honeypot oder einer einfach zu erkennenden Mutation davon zu rechnen ist. Diese Ma√ünahme ist inspiriert von Juels et al.¬†(Juels and Rivest 2013). Sie haben eine √§hnliche Methode im Kontext von Passworthashes auf Servern vorgeschlagen. Dort werden unter die echten Nutzerpassw√∂rter Hashes von Honeypots, sogenannten Honeywords, gemischt. Wird die Passwortdatenbank gestohlen und invertiert und damit versucht in das System einzudringen, kann der Angriff erkannt werden, sobald der Angreifer die Honeywords als Passw√∂rter ausprobiert. Voris et al.¬†(Voris et al. 2013) beschreiben Honeywords in einem gr√∂√üeren Zusammenhang sowie eine Methode diese zu generieren, sodass sie schwer von anderen Zeichenketten unterscheidbar sind. Ihre Arbeit hat einen Menschen, beispielsweise einen Mitarbeiter im eigenen Unternehmen, als Angreifermodell.

Behindern von Fuzzern

Fuzzer-Erkennung funktioniert nicht zuverl√§ssig gegen viele verschiedene, teils unbekannte, Fuzzer. Ein anderer Ansatz ist deshalb, keine explizite Unterscheidung zwischen normaler Ausf√ľhrung und der Ausf√ľhrung durch einen Fuzzer zu machen. Stattdessen werden die Annahmen √ľber Fuzzer aus (G√ľler et al. 2019b) durch den Aufbau des Programms gebrochen. Dabei soll die normale Programmausf√ľhrung nicht au√üerhalb der Eigenschaften¬†[prop_one] und¬†[prop_two] einer Fuzzing-Schutzma√ünahme beeinflusst werden.

Initialer fork-Aufruf

Fuzzer wie AFL nehmen eine Eingabe als einen Bug ausl√∂send in Betracht, wenn die R√ľckgabe des Programms von null verschieden ist und ein Signal im Zielprogramm beobachtet wurde. Folgende Schutzma√ünahme kann demnach daf√ľr verwendet werden die Absturzerkennung von Fuzzern fehlzuleiten: Bei einem Programm wird initial fork() ausgerufen und das eigentliche Programm als Kind ausgef√ľhrt¬†(Edholm and G√∂ransson 2016). Der Elternprozess wartet dann bis der Kindsprozess beendet wurde. F√ľr den Fall, dass der Kindsprozess von einem Signal beendet wurde, beendet sich der Elternprozess mit R√ľckgabewert¬†0. Somit betrachtet der Fuzzer eine uninteressante H√ľlle statt dem eigentlichen Prozess.

Signale Verbergen

Um Prozessen Fehlverhalten anzuzeigen, sendet das Betriebssystem Signale. Beispiele f√ľr Fehlverhalten sind Schutzverletzungen (segmentation faults), Zugriffe auf physikalisch nicht adressierbare Speicherstellen (Bus-Fehler, englisch bus errors) oder ung√ľltige Instruktionen. In diesen F√§llen sendet das Betriebssystem die Signale SIGSEGV, SIGBUS beziehungsweise SIGILL. Alle diese Fehlerkonditionen sind Resultat eines Bugs im Programm. Programme haben die M√∂glichkeit auf Signale zu reagieren oder sie zu ignorieren. Standardm√§√üig f√ľhren diese in ANSI-C definierten Signale zum Abbruch des Programms. Um Fuzzing zu erschweren, kann nun ein spezieller Signalhandler eingerichtet werden, wie in Listing¬†[hide]. Normalerweise werden Signalhandler f√ľr solch schwerwiegende Fehler dazu verwendet, wichtige Daten zu sichern und im Anschluss das Programm mit einem Fehlercode, EXIT_FAILURE, zu beenden. Stattdessen wird nun das Programm mit dem R√ľckgabewert EXIT_SUCCESS, also 0 beendet, um den Fehler vor dem Fuzzer zu verbergen¬†(Edholm and G√∂ransson 2016). Diese Ma√ünahme erf√ľllt die Definition einer Fuzzing-Schutzma√ünahme, insbesondere wird Annahme¬†[antifuzz_two] gebrochen, die besagt, dass Abst√ľrze detektiert werden k√∂nnen.

void hide(int sig) {
  printf("Everything went well.");
  exit(EXIT_SUCCESS);
}
int main(void) {
  signal(SIGSEGV,hide);
  signal(SIGBUS,hide);
  signal(SIGILL,hide);
  return run_programm();
}

Das dauerhafte Ignorieren oder Blockieren von Signalen, die schwerwiegende Fehler anzeigen, ist keine gute L√∂sung. Zum einen, da des Betriebssystem die M√∂glichkeit hat Prozesse, die sich falsch verhalten und nicht auf andere Signale reagieren, sofort zu beenden. Bei Unix-Betriebssystemen geschieht dies durch das Signal SIGKILL. Prozesse k√∂nnen SIGKILL weder ignorieren noch behandeln, wodurch der Fuzzer den Absturz erkennen kann. Zum anderen ist ersichtlich welche Prozesse welche Signale ignorieren. Unter Linux pro Prozess durch Bitmasken in /proc/$PID/status. Das Ignorieren der oben genannten Signale ist wohl kein legitimer Anwendungsfall und w√§re ein starkes Indiz f√ľr das Vorhandensein von Fuzzing-Schutzma√ünahmen.

Vorget√§uschte Abst√ľrze

Einige Fuzzer instrumentieren das Zielprogramm, indem sie selbst die Signalhandler √ľberschreiben, um Abst√ľrze zu detektieren. In diesen F√§llen hilft die im vorherigen Absatz beschriebene Methode nicht. In¬†(G√ľler et al. 2019b) werden auch Signale verborgen wie im vorherigen Absatz beschrieben, zus√§tzlich wird aber bei jedem Programmstart absichtlich eine Schutzverletzung ausgel√∂st, die der Signalhandler ignorieren soll. Somit ergeben sich zwei F√§lle. √úberschreibt der Fuzzer also Signalhandler, detektiert er bei jeder Programmausf√ľhrung einen Absturz. √úberschreibt der Fuzzer nicht die Signalhandler, so ist die Methode Signale zu verbergen m√∂glich, was in Kombination mit der vorherigen Ma√ünahme, Fuzzer t√§uscht, die basierend auf dem R√ľckgabewert des Programms nach Bugs im Programm suchen.

Schon Whitehouse¬†(Whitehouse 2014) beschreibt eine Methode, um Abst√ľrze vorzut√§uschen. Dort allerdings nicht bei jedem Programmstart, um Fuzzer grunds√§tzlich zu t√§uschen, sondern verstreut √ľber das Programm. An beliebigen Stellen im Programm kann folgendes Muster angewendet werden.

  1. Ein Signalhandler wird eingerichtet, zum Beispiel f√ľr SIGSEGV. Dieser tut nichts, sodass die Programmausf√ľhrung weiter normal fortgesetzt werden kann.

  2. Es wird absichtlich ein Fehler ausgelöst, zum Beispiel eine Schutzverletzung durch Schreiben an Adresse 0x0, was das Signal SIGSEGV auslöst.

  3. Der zuvor eingerichtete Signalhandler wird wieder entfernt.

Dies ist nat√ľrlich kein allgemeiner Schutz gegen Fuzzer. Es tr√§gt aber, durch viele falsch-positive Ergebnisse, dazu bei, die Schwachstellensuche insgesamt zu erschweren ‚Äď unabh√§ngig ob durch einen menschlichen Analysten oder in einem automatisierten Prozess. Annahme¬†[antifuzz_two] wird nur dann gebrochen, wenn der Absturz, wie in (G√ľler et al. 2019b), initial passiert und somit der Fuzzer jede Eingabe als Absturz ansieht und danach zur n√§chsten Eingabe geht.

Einf√ľgen nicht ausnutzbarer Schwachstellen

In (G√ľler et al. 2019b) und (Jung et al. 2019b) wurde angedeutet, aber nicht implementiert, dass auch das Einf√ľgen von typischen Mustern von Schwachstellen in ein Programm, Fuzzer fehlleiten k√∂nnte. In einer Arbeit von Hu et al.¬†(hu, hu, and dolan-gavitt 2018) wird das Werkzeug Chaff Bugs pr√§sentiert, das automatisch Programme durch typischen Muster von Schwachstellen erg√§nzt, dabei aber garantiert, dass diese w√§hrend einer normalen Ausf√ľhrung nicht ausnutzbar sind. Fuzzer finden zun√§chst einmal nur Bugs in einem Programm. Wie bereits beschrieben, haupts√§chlich Programmabst√ľrze. Einige Fuzzer k√∂nnen zus√§tzlich eine Triage eines gefunden Bugs durchf√ľhren, die eine Einsch√§tzung der Ausnutzbarkeit eines Bugs liefert.Angreifer suchen, m√∂glicherweise basierend auf einer automatischen Triage, nach Wegen, den Bug auszunutzen, also einen Exploit zu schreiben. Chaff Bugs kann scheinbare Schwachstellen in ein Programm einf√ľgen, die von Fuzzern gefunden werden und von automatischen Triagewerkzeugen als ausnutzbar klassifiziert werden, aber tats√§chlich beweisbar nicht ausnutzbar sind¬†(hu, hu, and dolan-gavitt 2018). Chaff Bugs wurde in (hu, hu, and dolan-gavitt 2018) mit AFL und dem Triagewerkzeug exloitabe, einem Plugin f√ľr gdb, getestet. Diese Art der Schutzma√ünahme ist nicht nur auf Fuzzer beschr√§nkt, sondern soll jede Art der Schwachstellensuche behindern. Die Anwendung von Chaff Bugs erf√ľllt die Definition einer Fuzzing-Schutzma√ünahme aus zwei Gr√ľnden nicht. Erstens wird keine der Fuzzing-Annahmen gebrochen. Zweitens wird Eigenschaft¬†[prop_one] einer Fuzzing-Schutzma√ünahme nicht erf√ľllt, da, in Abgrenzung zum letzten Abschnitt¬†4.2.3, tats√§chliche Abst√ľrze eingef√ľgt werden. Das Programm ist also nicht mehr funktional √§quivalent zum ungesch√ľtzten Programm.

Die eingef√ľgten Abst√ľrze sind zwar nicht ausnutzbar, es ist aber abh√§ngig von der zu sch√ľtzenden Anwendung, ob diese Ma√ünahme tats√§chlich geeignet ist. Insbesondere darf der Absturz eines Programms selbst noch keine (relevante) Schwachstelle darstellen (DoS-Angriff). Die Autoren von¬†(hu, hu, and dolan-gavitt 2018) argumentieren, dass ihre Schutzma√ünahme f√ľr viele Klassen von Programmen angewendet werden k√∂nne und f√ľhren daf√ľr die heute verbreiteten Microservice-Architekturen, welche f√ľr Ausf√§lle entworfen w√ľrden, als Beispiel an. Tats√§chlich sind viele Microservice-Architekturen so entworfen, dass der Ausfall einer Instanz die Verf√ľgbarkeit des Gesamtsystems nicht beeinflusst. Netflix l√§sst sogar absichtlich immer wieder Microservices abst√ľrzen, um die Ausfallsicherheit ihres Systems in Produktion zu testen¬†(Basiri et al. 2019). Au√üerdem ist die Wahrscheinlichkeit, dass ein normaler Nutzer des Systems versehentlich einen Absturz ausl√∂st sehr gering. Allerdings kann die M√∂glichkeit eine Microservice-Instanz gezielt abst√ľrzen zu lassen durchaus f√ľr die Verf√ľgbarkeit eines Gesamtsystems kritisch werden, wenn der Angriff gleichzeitig auf mehrere Microservice-Instanzen durchgef√ľhrt wird.

In F√§llen, in denen DoS-Angriffe tats√§chlich kein Problem darstellen, kann diese Schutzma√ünahme die Schwachstellensuche stark behindern. √Ąhnlich zu Abschnitt¬†4.2.3 entsteht eine gro√üe Zahl von falsch positiven Ergebnissen, die nur schwer als absichtlich eingebaut zu identifizieren sind. Au√üerdem werden durch diese Ma√ünahme auch Fuzzer fehlgeleitet, die eine statische Programmanalyse durchf√ľhren um, Programmteile zu finden, die typische Muster von Schwachstellen aufweisen (Shastry et al. 2017) und den Fuzzingprozess in diese Teile leiten.

Hashwert-Vergleiche

Durch symbolische oder konkolische Ausf√ľhrung (im Folgenden als symbolische Ausf√ľhrung zusammengefasst) k√∂nnen Fuzzer systematisch die Pfade eines Programms abdecken. Daf√ľr wird der Einfluss von Eingaben auf das Ergebnis von Sprungbedingungen analysiert. Obwohl symbolische Ausf√ľhrung mittlerweile auch kompliziertere Bedingungen aufl√∂sen kann und Fuzzer in Kombination mit anderen Methoden gute Ergebnisse erzielen¬†(Stephens et al. 2016; Yun et al. 2018), gibt es Grenzen der symbolischen Ausf√ľhrung. Insbesondere Pr√ľfsummen, welche in vielen Dateiformaten zu finden sind, stellen ein Hindernis dar. Fuzzing solcher Dateiformate ben√∂tigt in der Praxis das manuelle oder automatische Entfernen von Pr√ľfsummen u.√§.¬†(Liu et al. 2018), Kenntnisse √ľber das Eingabeformat oder optimistische Annahmen √ľber das Verhalten des Programms¬†(Peng, Shoshitaishvili, and Payer 2018; Aschermann et al. 2019). Dieses Hindernis kann f√ľr Fuzzing-Schutzma√ünahmen ausgenutzt werden, indem alle Vergleiche auf Gleichheit durch Hashwert-Vergleiche ersetzt werden. Dies ist ein wirksamer Schutz gegen symbolische Ausf√ľhrung, da ein erfolgreiches Aufl√∂sen eines Vergleichs (ohne Vorwissen √ľber den Klartext) gleichbedeutend mit dem Brechen der Kollisionsresistenz-Eigenschaft der verwendeten Hashfunktion ist. Dies hat nat√ľrlich einige Limitationen. Hashwert-Vergleiche lassen sich nur bei Vergleichen auf Gleichheit anwenden, sind also f√ľr viele Eingabeformate und deren Interpretationsroutinen nicht anwendbar, da sich dort oftmals Vergleiche mit regul√§ren Ausdr√ľcken oder Vergleiche innerhalb einer Ordungsrelation finden. Das Verwenden von Hashfunktionen induziert einen h√∂heren Berechnungsaufwand, auch da nicht alle Prozessoren Hardware-Unterst√ľtzung f√ľr Hashwertberechungen haben. Die Entwickler des zu sch√ľtzenden Programms verlassen sich, durch Anwenden dieser Ma√ünahme, auf die Einwegeigenschaft der verwendeten Hashfunktion und verletzten Eigenschaft¬†[prop_one] der Definition von Fuzzing-Schutzma√ünahme, da die Programme nicht mehr √§quivalent sind. Unsichere Hashfunktionen wie md5 und SHA-1¬†(Leurent and Peyrin 2020; Stevens 2013), sind als Fuzzing-Schutzma√ünahme in diesem Sinne ungeeignet. Barak et al.¬†(Barak et al. 2001) definieren eine abgeschw√§chte approximative Form von Eigenschaft¬†[prop_one], bei der die Eigenschaft nur mit hoher Wahrscheinlichkeit halten muss. Diese ist bei sicheren Hashfunkionen erf√ľllt. Trotzdem ist es auch dort sinnvoll die Hashwertberechungen zu salzen, da die Zeichenketten in realen Programmen nicht als gleichverteilt anzunehmen sind. Angreifer mit vorberechneten Hashwerten, f√ľr g√§ngige Zeichenketten in Programmen k√∂nnen sonst deutlich schneller Urbilder f√ľr diese finden. Salzen bedeutet: F√ľr jede Zeichenkette einen zuf√§lligen Wert mit in die Hashfunktion zu geben und diesen dann neben der Zeichenkette zu speichern. Somit muss der Angreifer auch f√ľr g√§ngige Zeichenketten viele Hashwerte berechnen. Keiner der aktuellen Ans√§tze salzt die Hashwerte.

Angreifer k√∂nnten bei Verwendung einer unsicheren Hashfunktion gegebenenfalls ein unterschiedliches Verhalten des gesch√ľtzten Programms im Vergleich mit dem ungesch√ľtzten Programm ausl√∂sen, was schwerwiegende Auswirkungen haben k√∂nnte. In¬†(G√ľler et al. 2019b) wird diesem Problem dadurch begegnet, dass die Hashwert-Vergleiche durch die Entwickler selektiv angewendet werden. Somit kann der Berechnungsmehraufwand gering gehalten werden. Au√üerdem wird SHA-512, eine als sicher angenommene Hashfunktion, verwendet. In¬†(Jung et al. 2019b) hingegen werden die Vergleiche automatisch ersetzt. Um hier den Berechnungsmehraufwand gering zu halten, wird auf eine starke Hashfunktion verzichtet und stattdessen CRC32 eingesetzt¬†(Jung et al. 2019a, 2019b). CRC32 ist ein Algorithmus, um effizient Pr√ľfsummen berechnen zu k√∂nnen, weist aber keine Kollisionsresistenz auf. Es k√∂nnen trivial Kollisionen zu einem gegebenen Wert gefunden werden k√∂nnen, beispielsweise durch Vertauschen von 4-Byte-Gruppen, so haben die Zeichenketten "BBBBAAAA" und "AAAABBBB" den gleichen Hashwert. Hier ist also Eigenschaft¬†[prop_one] nicht erf√ľllt.

//original code: if (value == 12345)
if (CRC_LOOP(value) == OUTPUT_CRC) {...}

Auch als Pr√ľfsumme verwendet, stellt CRC nicht f√ľr alle Fuzzer mit symbolischer Ausf√ľhrung ein Hindernis dar.
Sharma et al.¬†(Sharma et al. 2020) zeigen f√ľr die CRC32-Implementierung von (Jung et al. 2019b), dass diese mit symbolischer Ausf√ľhrung effizient gel√∂st werden kann. Das zeigt, dass auch Eigenschaft¬†[prop_three] nicht erf√ľllt ist.

Fuzzification hat zudem Schwächen, Vergleiche im Quelltext zu identifizieren und zu ersetzen. Einfache Vergleiche, zum Beispiel solche, bei denen die strcmp-Funktion nicht unmittelbar in einem if steht (siehe Listing [bad_one]), werden nicht ersetzt.

/* Wird ersetzt: */
if(strcmp(strA, "hello")) {...}
/* Wird nicht ersetzt */
int c = strcmp(strA, "hello");
if(c) {...}

Zudem ist es m√∂glich, dass Fuzzification invaliden C-Code generiert, falls an an einer Stelle eine Variable mit dem Namen ‚Äěnewvar_1‚Äú verwendet wird. Es kann sogar dazu kommen, dass der Code syntaktisch korrekt bleibt, aber funktional ver√§ndert wird. Falls wie in Listing¬†[bad_two] ein Vergleich in einer festen Zeichenkette steht, so wird die Zeichenkette ver√§ndert.

strcpy(strA, "if(strcmp(strB,strA))");

Es ist also m√∂glich, dass durch eine bessere Implementierung zu deutlicheren Ergebnissen in der Auswertung der AntiHybrid-Technik gef√ľhrt h√§tte. Zusammen mit der Abh√§ngigkeit von guten Testf√§llen ist Fuzzification insgesamt nicht breit als Fuzzing-Schutzma√ünahme anwendbar. Die Evaluation in (Jung et al. 2019b) mit AFL-QEMU zeigt auch, dass Fuzzification nicht gegen jedes der getesteten Programme die Anzahl der gefundenen Pfade reduzieren konnte. In Abbildung¬†1 ist zu sehen, dass Fuzzification (alle Schutzma√ünahmen aktiviert) bei libpng erfolgreich ist (gefundene Pfade um ca. 77% reduziert), bei libjpeg hingegen nicht (gefundene Pfade um ca. 11% reduziert). Eine von Wang et al.¬†(Wang et al. 2020) durchgef√ľhrte Evaluation von Fuzzification unter gleichen Bedingungen, misst au√üerdem deutlich abweichende Werte f√ľr objdump. (Jung et al. 2019b) misst eine Reduktion der Pfade um ca. 80%, (Wang et al. 2020) hingegen eine Reduktion um nur 7,6%.

Ausschnitt der Evaluation von Fuzzification. Auf Basis von (Jung et al. 2019b), Abbildung 9.

Das Einf√ľgen von Hashwert-Vergleichen sch√ľtzt nicht nur gegen symbolische Ausf√ľhrung, sondern hat auch den Nebeneffekt, eine bestimmte Art der Programmtransformation zu verhindern. Da Fuzzer Programmabdeckung als Metrik verwenden, teilen sie Bedingungen in mehrere Teile, sodass die Bedingungen schrittweise erf√ľllt werden k√∂nnen, statt diese direkt erf√ľllen zu m√ľssen. Eine g√§ngige Transformation ist, falls das m√∂glich ist, das Aufteilen von Zeichenkettenvergleichen wie in Listing¬†[transformation] dargestellt¬†(Autor 2016).

/* originaler Code */
if(strcmp(x,"vln")) {...}
/* transformierter Code */
if(strlen(x) == 3)
if(x[0] == 'v')
    if(x[1] == 'l')
        if(x[2] == 'n') {...}

Somit ergibt jeder gefundene l√§ngere Pr√§fix einer Zeichenkette mehr Abdeckung und hilft Fuzzern, auf die Annahme¬†[antifuzz_one] aus¬†(G√ľler et al. 2019b) zutrifft. Da Hashwert-Vergleiche nicht in der dargestellten Weise aufteilbar sind, muss der Fuzzer nun direkt eine g√ľltige Eingabe f√ľr einen Vergleich erraten.

Eine Alternative zu Hashfunktionen, bei der nicht das Problem der Kollisionen besteht, ist es Verschl√ľsselung zu verwenden. (G√ľler et al. 2019b) nutzt hierf√ľr die symmetrische Verschl√ľsselung AES. Der Schl√ľssel muss jedoch mit im Programm enthalten sein. Obfuscation-Techniken k√∂nnen beim Verstecken des Schl√ľssels helfen.

Einf√ľgen vieler Pfade

Au√üer Hashwert-Vergleichen gibt es noch weitere Methoden, die nicht oder nur sehr schwer durch symbolische Ausf√ľhrung aufzul√∂sen sind. Von Banescu et al.¬†(Banescu et al. 2016) werden daf√ľr Code-Obfuscation-Techniken mit aktuellen Werkzeugen zur symbolischen Ausf√ľhrung evaluiert und basierend darauf neue wirksamere Methoden vorgeschlagen. Als Fuzzing-Schutzma√ünahme ist das Unterteilen von Eingaben in mehrere logisch √§quivalente Pfade am geeignetsten. Ein Elementarblock, der von mindestens einer Eingabe abh√§ngt, wird anhand der Eingabe in (maximale Kardinalit√§t der Wertemenge) viele Pfade unterteilt. Jeder der Pfade enth√§lt √§quivalenten, aber durch bestehende Obfuscation-Techniken unterschiedlich formulierten Code. Diese Obfuscation der Pfade ist notwendig, damit der Compiler diesen Code nicht entfernt oder es f√ľr Angreifer trivial wird diese Schutzma√ünahme zu erkennen und zu entfernen. Die Gr√∂√üe des Programms w√§chst dadurch asymptotisch linear, w√§hrend die Analyse durch symbolische Ausf√ľhrung asymptotisch exponentiellen Mehraufwand bedeutet, sobald diese Ma√ünahme in nicht trivialen Programmen mit Schleifen und Bedingungen angewendet wird¬†(Banescu et al. 2016). Damit existiert eine Schutzma√ünahme gegen symbolische Ausf√ľhrung, die die vorausgesetzten Eigenschaften f√ľr eine Fuzzing-Schutzma√ünahme erf√ľllt. Diese Art von Schutzma√ünahme bricht nicht nur Annahme¬†[antifuzz_four], auf der Fuzzer mit symbolischer Ausf√ľhrung beruhen, sondern auch Annahme¬†[antifuzz_one], da nun getestete Funktionalit√§t nicht mehr (oder deutlich weniger) im Verh√§ltnis zur erreichten Abdeckung ist.

Es ist anzumerken, dass sowohl das Einf√ľhren von Hashwert-Vergleichen, wie auch die hier beschriebene Schutzma√ünahme nicht bei allen Programmen gleich gut funktioniert. Hashwert-Vergleiche ben√∂tigen, wie oben beschrieben, Vergleiche auf Gleichheit und diese Schutzma√ünahme profitiert deutlich von vielen Elementarbl√∂cken in Schleifen¬†(Banescu et al. 2016).

G√ľler et al.¬†(G√ľler et al. 2019b) und Jung et al.¬†(Jung et al. 2019b) erh√∂hen auch die Pfade im Programm (englisch branch explosion) als Schutzma√ünahme, allerdings duplizieren sie daf√ľr nicht im Programm vorhandene Funktionalit√§t, sondern f√ľgen funktionslose neue Elementarbl√∂cke und Pfade ein. Es werden pseudozuf√§llig zur Kompilierungszeit Bedingungen generiert, die zu unterschiedlichen Elementarbl√∂cken f√ľhren. Jedes Byte der Eingabe ist in mehreren Bedingungen involviert. Damit kann der Fuzzer keine Zusammenh√§nge mehr zwischen Eingabe und beobachteter Abdeckung herstellen, da kleine Unterschiede in den Eingaben zu deutlich abweichendem Verhalten f√ľhrt. Konkret wird dadurch die Datenstruktur, die diesen Zusammenhang speichert, bei AFL eine Bitmap, √ľberschwemmt. Einige der generierten Bedingungen sind einfach zu erf√ľllen, sodass ein abdeckungsgesteuerter Fuzzer schnell Eingaben generiert, die ihn in den funktionslosen Teil des Programmes fehlleiten. Andere Bedingungen lassen sich schwerer erf√ľllen, sodass der Fuzzer lange Zeit im funktionslosen Teil des Programms verbringt, wenn er versucht diese zu l√∂sen.

Durch dieses Vergr√∂√üern des Kontrollflussgraphen entsteht Mehraufwand, das Bin√§rprogramm wird gr√∂√üer und die Laufzeit wird l√§nger. In¬†(Jung et al. 2019b) wird angegeben, dass das Einf√ľgen von hunderttausend Pfaden, was die standardm√§√üig von AFL verwendete Bitmap zu 90% f√ľllt, in ihrer Implementierung das Bin√§rprogramm um 4,6MB vergr√∂√üert. Die Anwendung von¬†(G√ľler et al. 2019b) vergr√∂√üert das Bin√§rprogramm nach den Angaben der Autoren um circa 25MB. Ich selbst konnte auch bei Anwendung aller Schutzma√ünahmen in der auf GitHub ver√∂ffentlichten Implementierung¬†(G√ľler et al. 2019a) eine maximale Vergr√∂√üerung von 6,8MB messen. Der Laufzeitmehraufwand war weder bei¬†(Jung et al. 2019b), noch bei¬†(G√ľler et al. 2019b) messbar. W√§hrend die Vergr√∂√üerung des Bin√§rprogramms in vielen Umgebungen, wie Servern oder Heimcomputern, kein Problem darstellten sollte, gibt es Umgebungen, wie IoT-Ger√§te mit wenig Speicher, f√ľr die m√∂glicherweise die Anzahl der eingef√ľgten Pfade individuell konfiguriert werden muss. Eigenschaft¬†[prop_two] einer Fuzzing-Schutzma√ünahme ist, wegen des nur konstanten Mehraufwands erf√ľllt. In eigenen Tests war es mit manchen Fuzzern auf einem System mit 8GB Arbeitsspeicher nicht m√∂glich das mit (G√ľler et al. 2019b) gesch√ľtzte Programm zu instrumentieren. Zum Beispiel wurden AFL-QEMU und IJON (Um den Fuzzer durch eine Annotation zu einer echten Codestelle zu leiten.) erfolglos getestet. Wird ein mit¬†(G√ľler et al. 2019b) gesch√ľtztes Programm f√ľr 3 Stunden mit AFL (LLVM-fast-Instrumentierung auf 2 3.6GHz Kernen parallel) gefuzzt, ist die Bitmap bereits zu 26% gef√ľllt.

Verz√∂gerungen f√ľr seltene Pfade

Fuzzer ben√∂tigen viele Programmausf√ľhrungen, um Bugs zu finden (Annahme¬†[antifuzz_three]). Dies gilt weniger f√ľr White-Box-Fuzzer, die bei jeder Programmausf√ľhrungen umfangreiche Analysen durchf√ľhren. Die Methoden in (G√ľler et al. 2019b) und (Jung et al. 2019b) brechen diese Annahme durch das Einf√ľgen von Verz√∂gerungen im Programm. Verz√∂gerungen verlangsamen sowohl Fuzzing, wie auch normale Ausf√ľhrung. W√§hrend eine Verz√∂gerung von beispielsweise 100ms vielen Nutzern nicht auffallen w√ľrde, so wird dadurch der Fuzzingprozess deutlich gebremst, da Annahme¬†[antifuzz_three] von hunderten bis tausenden Ausf√ľhrungen pro Sekunde ausgeht. In vielen F√§llen ist eine solche Verz√∂gerung auch f√ľr die normale Benutzung eines Programms inakzeptabel. Die Methode in¬†(G√ľler et al. 2019b) beruht deshalb darauf, dass die Verz√∂gerungen von den Entwicklern des Programms an unkritischen Stellen eingef√ľgt werden, beispielsweise bei ung√ľltigen Eingaben. Fuzzer werden in der Regel deutlich mehr ung√ľltige Eingaben erzeugen als normale Nutzer. Bei dieser Art von Schutzma√ünahme h√§ngt es von der Position der Verz√∂gerungen ab, ob Eigenschaft¬†[prop_two] erf√ľllt ist. Die Methode in (Jung et al. 2019b) ben√∂tigt Testf√§lle f√ľr das Programm, um von normaler Ausf√ľhrung selten besuchte Pfade zu finden. Auf gefunden seltenen Pfaden wird dann eine Verz√∂gerung eingef√ľgt. Dieser Ansatz verl√§sst sich auf eine gute Abdeckung durch die Testf√§lle der Entwickler. Ist in Testf√§llen ein Programmpfad nicht enthalten, der von einer Nutzergruppe aber h√§ufig verwendet wird, erleben diese Nutzer eine Verlangsamung des Programms. Das Erstellen von Verz√∂gerungen funktioniert iterativ.

  1. Es werden selten besuchte Pfade auf Basis der Testfälle identifiziert.

  2. [speediter] Es werden probabilistisch Verz√∂gerungen auf seltenen Pfaden eingef√ľgt.

  3. Die Testf√§lle werden auf dem gesch√ľtzten Programm ausgef√ľhrt und die Verlangsamung insgesamt gemessen.

  4. Ist die gemessene Verlangsamung nicht innerhalb eines vorgegeben Zeitbudgets, wird Schritt¬†[speediter] mit weniger/k√ľrzeren Verz√∂gerungen ausgef√ľhrt.

Die von (Jung et al. 2019b) eingef√ľgten Verz√∂gerungen sind keine reinen Aufrufe der sleep-Funktion, sondern sehen aus wie normaler Programmcode. Es wird CSmith¬†(Yang et al. 2011) verwendet, um Programmcode zu generieren, der beispielsweise globale Variablen ver√§ndert oder arithmetische Operationen ausf√ľhrt, um zu verhindern, dass die Schutzma√ünahme leicht zu erkennen und zu entfernen ist. In den f√ľr diese Arbeit mit (G√ľler et al. 2019b) durchgef√ľhrten Tests hat AFL-QEMU bei einem einfachen Programm¬†(G√ľler et al. 2019a) (√§hnlich zu dem transformierten Programm in Listing¬†[transformation], wobei in {...} der Absturz ausgel√∂st wird) auch nach 3 Stunden (gleiche Bedingungen wie oben) keinen Absturz finden k√∂nnen. AFL-QEMU zeigt bei verlangsamten Programmen eine Warnmeldung an und vermutet eine Fehlkonfiguration des Fuzzers. Im ungesch√ľtzten Programm kann innerhalb von unter einer Minute ein Absturz gefunden werden.

Automatisches Einf√ľgen von Verz√∂gerungen wie in (Jung et al. 2019b) ist zwar aus Entwicklersicht einfacher, sollte aber mit Vorsicht verwendet werden. Ein Angreifer k√∂nnte aus der Verteilung der Verz√∂gerungen im Programm auf die Testfallabdeckung der Entwickler schlie√üen und dann an Stellen mit wenig Testfallabdeckung auf Schwachstellensuche gehen. Beim Entwerfen zuk√ľnftiger Fuzzing-Schutzma√ünahmen dieser Art muss darauf geachtet werden, nichts √ľber die Testfallabdeckung zu verraten. Au√üerdem ist diese Schutzma√ünahme nicht f√ľr alle Anwendungen geeignet. Es gibt beispielsweise Anwendungen, f√ľr die (fast) jede Eingabe eine g√ľltige Eingabe ist. Die Annahme, dass normale Nutzer h√§ufiger g√ľltig Eingaben verwenden als Fuzzer, trifft dann nat√ľrlich nicht mehr zu. Bei Anwendungen, f√ľr die DoS-Angriffe eine Gefahr darstellen, ist zu beachten, dass Angreifer absichtlich ung√ľltige Eingabe senden k√∂nnen, um somit die Anwendung zu √ľberlasten.

Hashkollisionen f√ľr AFL

Viele heutige Fuzzer basieren auf AFL und nutzten somit auch die gleiche Datenstruktur wie AFL, eine Bitmap, standardm√§√üig 64KB gro√ü. In dieser wird die erreichte Programmabdeckung gespeichert. Jedem Elementarblock wird bei der Instrumentierung des Programms eine Zahl z zugewiesen. Wird beim Fuzzing ein Elementarblock zn abgedeckt, so wird die Information zusammen mit der Informationen √ľber den letzten Elementarblock za an der Stelle zn‚ÄÖ‚äē‚ÄÖza der Bitmap gespeichert. Hat AFL den Quelltext des Programms zur Verf√ľgung, so kann afl-gcc jeweils eine gute Zufallszahl f√ľr z w√§hlen. Liegt nur das Bin√§rprogramm vor, so ist das, aufgrund der geringeren M√∂glichkeiten der Instrumentierung, nicht einfach m√∂glich. AFL-QEMU nutzt deshalb einen einfachen Hash aus den Adressen der Elementarbl√∂cke. Die Nummern der Elementarbl√∂cke sind also immer gleich. Kang Li¬†(Kang Li 2018) stellt auf der Black Hat USA 2018 eine M√∂glichkeit vor, durch Einf√ľgen von funktionslosen neuen Bl√∂cken Hashkollisionen f√ľr echte Pfade zu erzeugen. AFL kann dann f√ľr viele Eingaben nicht mehr entscheiden, ob sie zu neuer Abdeckung gef√ľhrt haben. Diese Schutzma√ünahme ist allerdings auf AFL-QEMU beschr√§nkt.

Bugs in Fuzzern

Eine weitere, in (Jung et al. 2019b) erw√§hnte M√∂glichkeit, den Fuzzing-Prozess zu behindern, ist das absichtliche Ausl√∂sen von Bugs in Fuzzern selbst. Es gibt Bugs in Fuzzern, die von einem Programm dazu genutzt werden k√∂nnen den Fuzzer abst√ľrzen zu lassen. Beispielsweise ist (Bruening 2014) ein seit 2014 bekannter Absturz in einem von vielen Fuzzern verwendeten Werkzeug zur Programmtransformation. Nat√ľrlich ist diese Art der Schutzma√ünahme auf wenige bestimmte Versionen von Fuzzern beschr√§nkt, f√ľr die Bugs bekannt sind.

Umgehen von Fuzzing-Schutzmaßnahmen

Fuzzing-Schutzma√ünahmen haben das Ziel die Schwachstellensuche durch Fuzzing so schwer wie m√∂glich zu gestalten, sodass ein Angreifer entweder seine Ressourcen verschwendet oder aufgibt, da keine Bugs gefunden wurden. In diesem Kapitel soll die Perspektive eines Angreifers eingenommen werden, der Fuzzing verwenden m√∂chte, um Schwachstellen zu finden. Zuerst muss erkannt werden, dass ein Programm Fuzzing-Schutzma√ünahmen einsetzt, um zu verhindern, dass Ressourcen verschwendet werden. Dann m√ľssen die Arten der Schutzma√ünahmen identifiziert werden, um schlie√ülich die Schutzma√ünahmen zu entfernen oder eine alternative Fuzzing-Technik anzuwenden, die von den Fuzzing-Schutzma√ünahmen nicht betroffen ist.

Erkennen von Fuzzing-Schutzmaßnahmen

Es sind verschiedene Ans√§tze denkbar, um Fuzzing-Schutzma√ünahmen zu erkennen. Nicht alle davon sind sichere Kriterien, sondern oftmals eher Indizien. Die nachfolgend beschriebenen Ans√§tze k√∂nnen kombiniert werden, um aussagekr√§ftige Ergebnisse zu erreichen. Es ist sogar denkbar, die Ans√§tze zur Merkmalsextraktion f√ľr eine Klassifikation durch maschinelles Lernen zu verwenden.

Nutzt ein Programm Fuzzer-Erkennung, dann ist es m√∂glich, das Verhalten des Programms in verschiedenen Umgebungen zu vergleichen. Verh√§lt sich das Programm in einer normalen Umgebung, zum Beispiel einer neu aufgesetzten virtuellen Maschine, anders als in einer Umgebung in der alles auf einen Fuzzer hindeutet, zum Beispiel Umgebungsvariablen von AFL, dann verwendet das Programm Fuzzer-Erkennung. Auch Honeywords als Schutzma√ünahme k√∂nnen erkannt werden, indem dem Programm zuerst extrahierte Zeichenketten als Eingaben gegeben werden und es dann mit einem neu gestarteten Programm verglichen wird. Hier sind nicht nur funktionale Eigenschaften des Programms zu vergleichen, sondern auch nicht-funktionale Eigenschaften, um Verz√∂gerungen zu erkennen. Es ist auch m√∂glich einen Fuzzer zu konstruieren, der die R√ľckgaben des gefuzzten Programms mit den R√ľckgaben des gleichen ungefuzzten Programms vergleicht. Dieser Vergleich kann auch asynchron stichprobenartig geschehen, um den Fuzzing-Prozess durch teure Aufrufe an eine virtuelle Maschine oder einen Container nicht zu verlangsamen.

Um Fuzzing-Schutzma√ünahmen zu erkennen, kann das Verhalten des Programms w√§hrend einer normalen Ausf√ľhrung oder w√§hrend des Fuzzing-Prozesses betrachtet werden. F√ľr einen initialen fork-Aufruf, um Signale zu verbergen oder um Abst√ľrze vorzut√§uschen sind eine Reihe von typischen Systemaufrufe n√∂tig, die mit strace beobachtet werden k√∂nnen. Listing¬†[straceout] zeigt die Systemaufrufe, wenn AntiFuzz einen Absturz vort√§uscht. Auch der Schutz gegen eine Beobachtung durch ptrace, kann durch einen entsprechenden Systemaufruf mit strace erkannt werden. Bei einem strace eines mit (G√ľler et al. 2019b) gesch√ľtzten Programms ist ein vorget√§uschter Absturz klar zu erkennen.

rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
getpid()                             = 15967
gettid()                             = 15967
tgkill(15967, 15967, SIGABRT)            = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
---SIGABRT {si_signo=SIGABRT,si_code=SI_TKILL,si_pid=15967,si_uid=1000}---

Mustererkennung mit strace und ltrace (das ptrace verwendet) ist nicht hinreichend zur Erkennung eines initialen fork-Aufrufs oder dem Verbergen von Signalen als Fuzzing-Schutzma√ünahme, auch ungesch√ľtzte Programme k√∂nnen √§hnliche Muster aufweisen. Zur weiteren Untersuchung kann das Programm ausgef√ľhrt und diesem, beziehungsweise seinem Kindsprozess, verschiedene Signale gesendet werden. Beendet sich das Programm, bei einem der in Abschnitt¬†4.2.2 beschriebenen Signale, mit R√ľckgabewert¬†0, so ist von einer Fuzzing-Schutzma√ünahme auszugehen.

Absichtlich eingef√ľgte nicht ausnutzbare Schwachstellen sind dagegen deutlich schwerer zu erkennen. Hier k√∂nnen statistische Analysen √ľber die Anzahl und Art der durch Fuzzing gefundenen Bugs zusammen mit automatischen Triageergbnissen der gefunden Bugs einen Anhaltspunkt geben. Statische Analyse des Programms k√∂nnte bei Kenntnis der Art der eingef√ľgten Bugs weitere Anhaltspunkte liefern.

Um Hashwert-Vergleiche zu erkennen, k√∂nnen entweder Zeichenketten exportiert und auf die H√§ufigkeit von bekannten Hashfunktionen beziehungsweise Entropie analysiert werden. Es k√∂nnen auch dynamische Methoden zur Erkennung von Hashfunktionen verwendet werden. Hier muss beim Sch√ľtzen des Programms abgewogen werden zwischen Sicherheit der Hashfunktion oder Verschl√ľsselung und deren Detektierbarkeit, da sicherere Verfahren aufw√§ndiger zu implementieren sind und eine Reihe typischer arithmetischer Operationen verwenden. Wegen der einfachen M√∂glichkeit, Hashfunktionen und Verschl√ľsselung zu erkennen, ist es im Bereich der Schadsoftware-Obfuscation verbreitet, auf kryptographisch starke Verfahren zu verzichten¬†(Wressnegger, Boldewin, and Rieck 2013).

Entfernen von Fuzzing-Schutzmaßnahmen

Letztlich kann jede der Schutzmaßnahmen durch manuelle statische Analyse entfernt werden. Da das aber mit hohem menschlichen Aufwand verbunden ist, werden im Folgenden nur Methoden präsentiert, die Schutzmaßnahmen mit vergleichsweise geringem Aufwand entfernen oder umgehen.

Die ptrace-Erkennung kann vergleichsweise einfach get√§uscht werden. In der LD_PRELOAD-Umgebungsvariable k√∂nnen eigene geteilte Bibliotheken angegeben werden, die dann vom Programm verwendet werden. Gibt man dort eine eigene Implementierung der ptrace-Funktion an, die immer 0 zur√ľckgibt, so funktioniert die ptrace-Erkennung von (Edholm and G√∂ransson 2016) und von (G√ľler et al. 2019b) nicht mehr. Wie bei allen in dieser Arbeit beschriebenen Schutzma√ünahmen kann eine lange Kette von Gegenma√ünahmen gegen Gegenma√ünahmen beschrieben werden ‚Äď ein Wettr√ľsten, das den Aufwand auf beiden Seiten erh√∂ht. Komplexere ptrace-Erkennungen w√ľrden hier ein komplexeres Vorgehen erfordern. Der weitere Teil des Kapitels geht daher von der in Kapitel¬†4 beschriebenen Form der Schutzma√ünahmen aus.

Initiale fork-Aufrufe k√∂nnen durch statische Analyse einfach gefunden werden. Hier gibt es mehrere M√∂glichkeiten das Programm trotzdem erfolgreich zu fuzzen. Es kann das Bin√§rprogramm gepatcht werden. Statt dem fork-Aufruf wird dann die echte main-Methode aufgerufen. Das Warten auf den Prozess wird mit NOPs √ľberschrieben. Damit kann die Schutzma√ünahme, wie in¬†(Edholm and G√∂ransson 2016) in Listing¬†6 beschrieben, entfernt werden. Der Fuzzer kann statt den Elternprozess, alternativ dessen Kindsprozess beobachten, dazu ist allerdings eine Anpassung des Fuzzers selbst notwendig.

Eine weitere √Ąnderung des Fuzzers kann darin bestehen, die Systemaufrufe des Programms zu beobachten. Wird ein Muster wie in Listing¬†[straceout] beobachtet, so ignoriert der Fuzzer den dadurch ausgel√∂sten Absturz und f√ľhrt den Fuzzingprozess fort.

Benutzt ein Programm Honeywords als Fuzzer-Erkennung, kann das zwar erkannt, aber nicht trivial entfernt werden. Honeywords werden so gew√§hlt, dass sie schwer von anderen Zeichenketten in einem Programm unterscheidbar sind¬†(Voris et al. 2013). Ein anderer Ansatz ist es, die Stelle zu finden, an der das Programm sich √ľber mehrere Ausf√ľhrungen merkt, dass Fuzzing erkannt wurde. Wenn die Implementierung der Schutzma√ünahme bekannt ist, ist das einfach m√∂glich. Wird allerdings eine unbekannte Implementierung verwendet, ist das je nach Umgebung sehr aufw√§ndig, da nur ein einzelnes Bit gespeichert werden muss und es daf√ľr viele unterschiedliche M√∂glichkeiten gibt.

Auch Hashwert-Vergleiche durch starke Hashfunktionen sind einfach zu erkennen aber schwer zu entfernen. Wurden die Hashwerte zusammen mit den anderen Zeichenketten extrahiert, kann versucht werden die vorliegenden Hashwerte zu erraten. Daf√ľr k√∂nnen Wissen √ľber das Eingabeformat und die nicht gehashten Zeichenketten des Programms als W√∂rterbuch dienen. Liegt eine Menge von Testdaten vor, k√∂nnen diese verwendet werden, um dynamisch den Kontrollfluss nachzuvollziehen. Dieser Ansatz ist allerdings sehr aufw√§ndig und verbraucht viele Ressourcen des Angreifers.

F√ľr diese Arbeit wurde statische Analyse mit dem Dekompilierer Ghidra ausgef√ľhrt. Damit ist es in unter zehn Minuten m√∂glich die Schutzma√ünahmen im Programm zu finden und dann mit einem Hex-edior zu entfernen. F√ľr die Analyse wird das in der AntiFuzz-Software¬†(G√ľler et al. 2019a) mitgelieferte Testprogramm verwendet. Es ist, auch wenn alle Schutzma√ünahmen aktiviert sind, ausreichend die init-Funktion durch NOPs zu ersetzten, um mit AFL-QEMU den Absturz im Programm zu finden. Wie auch beim ungesch√ľtzten Programm, wird der Absturz dann in unter einer Minute gefunden. Auch in einem Bin√§rprogramm, in dem die Symbole entfernt wurden, ist das einfach m√∂glich. Da der Quellcode von AntiFuzz √∂ffentlich ist, k√∂nnen die Header-Dateien in Ghidra importiert werden. Somit ist auch in einem kompliziertem Programm das Auffinden und Entfernen der init-Funktion m√∂glich. In¬†(G√ľler et al. 2019b) wird explizit gemacht, dass in AntiFuzz keine Schutzma√ünahmen gegen das Entfernen der Schutzma√ünahmen eingebaut sind und zus√§tzlich Obfuscation-Techniken eingesetzt werden sollen. Damit ist der Schutz gegen Fuzzing mit AntiFuzz immer nur so schwer zu entfernen wie die verwendete Obfuscation.

In einem Paper aus 2020 stellen Wang et al.¬†(Wang et al. 2020) einen Fuzzer TortoiseFuzz mit einer neuartigen Priorisierung von Eingaben vor. Fuzzer wie AFL sind rein abdeckungsgesteuert und deshalb sehr anf√§llig f√ľr die Schutzma√ünahme des Einf√ľgens vieler Pfade. Um die Abdeckung zu maximieren, verbringt AFL viel Zeit damit, die funktionslosen Pfade (eingef√ľgt durch (G√ľler et al. 2019b) oder (Jung et al. 2019b)) zu testen. Wang et al.¬†schlagen deshalb vor, Eingaben anhand mehrerer Faktoren zu priorisieren. Faktoren der Priorisierung enthalten:

  • Eingaben die zu Funktionen f√ľhren, welche daf√ľr bekannt sind bei falscher Benutzung Fehler zu verursachen. Beispiele sind memcpy, memset, malloc, free, etc.

  • Eingaben die zu Schleifenbedingungen f√ľhren, da Schleifenbedingungen beispielsweise Off-By-One-Fehler enthalten k√∂nnen. Aktuelle Fuzzing-Schutzma√ünahmen beinhalten weder diese Funktionen noch Schleifen.

Da die genannten Funktionen wegen der teilweise verwendeten Systemaufrufe aufw√§ndig sind, k√∂nnen auch die Elementarbl√∂cke nicht um diese erg√§nzt werden, ohne das Programm sehr zu verlangsamen. F√ľr TortoiseFuzz existiert auch eine Version f√ľr Bin√§rprogramme. Wang et al.¬†evaluieren TortoiseFuzz gegen Fuzzification und messen dabei, dass die Programmabdeckung nur um 25% verglichen mit dem ungesch√ľtzten Bin√§rprogramm reduziert wird, statt einer 90% Abnahme bei AFL. Leider ist der Quellcode von TortoiseFuzz zum Zeitpunkt der Einreichung noch nicht ver√∂ffentlicht worden.

Fazit

In dieser Arbeit wurde ein √úberblick √ľber Schutzma√ünahmen gegen Fuzzer zu geben. Keine der Methoden zur Fuzzer-Erkennung sind erfolgreich darin, gro√üe Klassen von Fuzzern zu erkennen. Schutzma√ünahmen, bei welchen kein Unterschied zwischen normaler Ausf√ľhrung und der Ausf√ľhrung durch einen Fuzzer besteht, sind breiter anwendbar. Diese Schutzma√ünahmen wurden theoretisch in ihrer Anwendbarkeit und Wirksamkeit bewertet. Dabei wurde, mittels einer formalen Definition von Fuzzing-Schutzma√ünahme gezeigt, dass nicht jede Schutzma√ünahme in jedem Kontext einsetzbar ist und einige Schutzma√ünahmen grunds√§tzliche, von einer Schutzma√ünahme erwartete Eigenschaften nicht erf√ľllen. Die Evaluationen anderer Forschungsarbeiten, sowie stichprobenartige Tests in dieser Arbeit zeigen, dass die betrachteten Methoden in Kombination wirksam Fuzzing verhindern, falls die Angreifer nicht von den Fuzzing-Schutzma√ünahmen wissen und das Programm eine typische Struktur hat. Mit TortoiseFuzz gibt es einen Fuzzer, der weit weniger anf√§llig gegen Fuzzing-Schutzma√ünahmen ist, als bisherige Fuzzer. Leider konnte aufgrund begrenzter Ressourcen keine umfangreichere Evaluation der Ma√ünahmen vorgenommen werden. Weiter zeigt diese Arbeit, dass momentane Schutzma√ünahmen gegen Fuzzing einfach zu erkennen sind. Angreifer, die von der Existenz einer Ma√ünahme wissen, k√∂nnen √ľberpr√ľfen, ob ein Programm diese verwendet, statt ihre Ressourcen auf ein gesch√ľtztes Programm zu verschwenden. Einzig f√ľr die in dieser Arbeit als Fuzzer-Erkennung vorgeschlagenen Honeywords kann keine zufriedenstellende Erkennung angegeben werden. Das Entfernen von Schutzma√ünahmen ist unterschiedlich schwierig. Versuche die Absturzerkennung des Fuzzers zu t√§uschen sind einfach zu entfernen, w√§hrend Verz√∂gerungen und das Einf√ľgen vieler Pfade gr√∂√üere Herausforderungen darstellen. Au√üerdem wurde festgestellt, dass einige Schutzma√ünahmen unerw√ľnschte Nebenwirkungen, wie die M√∂glichkeit von DoS-Angriffen oder der Vergr√∂√üerung der Menge der g√ľltiger Eingaben, mit sich bringen. Neben der grunds√§tzlichen √úberlegung, ob man die Schwachstellensuche f√ľr andere erschweren will, ist das eine weitere Abw√§gung, die f√ľr jeden Anwendungsfall individuell getroffen werden muss.

In zuk√ľnftiger Forschung k√∂nnen Fuzzing-Schutzma√ünahmen in Programmen dazu verwendet werden, Fuzzer zu evaluieren, da gesch√ľtzte Programme eine Art schlechtesten Fall f√ľr aktuelle Fuzzer darstellen. Fuzzer, die es schaffen trotz Fuzzing-Schutzma√ünahmen gut zu funktionieren, k√∂nnten m√∂glicherweise auch in ungesch√ľtzten Programmen mehr Bugs finden.

Ich m√∂chte Jun.-Prof. Dr. Christian Wressnegger f√ľr das Anbieten dieses interessanten Seminars und die hervorragende Betreuung insbesondere w√§hrend der Einschr√§nkungen durch die Corona-Pandemie besonders danken. Au√üerdem m√∂chte ich den anonymen Reviewern f√ľr ihr konstruktives, detailliertes und umfangreiches Feedback danken.

Ich veröffentliche finale Version dieser Serminararbeit unter CC-BY-SA-Lizenz. Siehe: https://creativecommons.org/licenses/by-sa/3.0/de/

Arya, Abhishek, Oliver Chang, Martin Barbella, and Jonathan Metzman. 2019. ‚ÄúOpen Sourcing Clusterfuzz.‚ÄĚ February 2019. https://github.com/mirrorer/afl/blob/master/docs/env_variables.txt.

Aschermann, Cornelius, Sergej Schumilo, Ali Abbasi, and Thorsten Holz. 2020. ‚ÄúIJON: Exploring Deep State Spaces via Fuzzing.‚ÄĚ In 2020 Ieee Symposium on Security and Privacy (Sp), 1:893‚Äď908. IEEE Computer Society.

Aschermann, Cornelius, Sergej Schumilo, Tim Blazytko, Robert Gawlik, and Thorsten Holz. 2019. ‚ÄúREDQUEEN: Fuzzing with Input-to-State Correspondence.‚ÄĚ In Symposium on Network and Distributed System Security (Ndss).

Autor, Unbekannter. 2016. ‚ÄúCircumventing Fuzzing Roadblocks with Compiler Transformations.‚ÄĚ August 2016. https://lafintel.wordpress.com/.

Banescu, Sebastian, Christian Collberg, Vijay Ganesh, Zack Newsham, and Alexander Pretschner. 2016. ‚ÄúCode Obfuscation Against Symbolic Execution Attacks.‚ÄĚ In Proceedings of the 32nd Annual Conference on Computer Security Applications, 189‚Äď200.

Barak, Boaz, Oded Goldreich, Rusell Impagliazzo, Steven Rudich, Amit Sahai, Salil Vadhan, and Ke Yang. 2001. ‚ÄúOn the (Im) Possibility of Obfuscating Programs.‚ÄĚ In Annual International Cryptology Conference, 1‚Äď18. Springer.

Basiri, Ali, Lorin Hochstein, Nora Jones, and Haley Tucker. 2019. ‚ÄúAutomating Chaos Experiments in Production.‚ÄĚ In 2019 Ieee/Acm 41st International Conference on Software Engineering: Software Engineering in Practice (Icse-Seip), 31‚Äď40.

Behera, Chandan Kumar, and Lalitha Bhaskari. 2015. ‚ÄúDifferent Obfuscation Techniques for Code Protection.‚ÄĚ Procedia Computer Science 70: 757‚Äď63.

Bruening, Derek. 2014. ‚ÄúSelf-Interpretation Due to ... on an Already-Caught Early Thread.‚ÄĚ November 2014. https://github.com/DynamoRIO/dynamorio/issues/1443.

Chang, Oliver, Abhishek Arya, Kostya Serebryany, and Josh Armour. 2017. ‚ÄúOSS-Fuzz: Five Months Later, and Rewarding Projects.‚ÄĚ May 2017. https://security.googleblog.com/2017/05/oss-fuzz-five-months-later-and.html.

Dinesh, Sushuant, Nathan Burow, Dongyan Xu, and Mathias Payer. 2020. ‚ÄúRetroWrite: Statically Instrumenting Cots Binaries for Fuzzing and Sanitization.‚ÄĚ In 2020 Ieee Symposium on Security and Privacy (Sp), 128‚Äď42. IEEE Computer Society.

Edholm, Emil, and David G√∂ransson. 2016. ‚ÄúEscaping the Fuzz-Evaluating Fuzzing Techniques and Fooling Them with Anti-Fuzzing.‚ÄĚ Master‚Äôs thesis.

G√ľler, Emre, Cornelius Aschermann, Ali Abbasi, and Thorsten Holz. 2019a. ‚ÄúAntifuzz.‚ÄĚ https://github.com/RUB-SysSec/antifuzz.

‚ÄĒ‚ÄĒ‚ÄĒ. 2019b. ‚ÄúAntiFuzz: Impeding Fuzzing Audits of Binary Executables.‚ÄĚ In 28th USENIX Security Symposium (USENIX Security 19), 1931‚Äď47. USENIX Association.

hu, zhenghao, yu hu, and brendan dolan-gavitt. 2018. ‚ÄúChaff Bugs: Deterring Attackers by Making Software Buggier.‚ÄĚ Arxiv Preprint Arxiv:1808.00659.

Huet, Thomas. 2017. ‚ÄúAFL Environmental Variables.‚ÄĚ November 2017. https://github.com/mirrorer/afl/blob/master/docs/env_variables.txt.

Ispoglou, Kyriakos, Daniel Austin, Vishwath Mohan, and Mathias Payer. 2020. ‚ÄúFuzzGen: Automatic Fuzzer Generation.‚ÄĚ In 29th USENIX Security Symposium (USENIX Security 20). USENIX Association.

Juels, Ari, and Ronald Rivest. 2013. ‚ÄúHoneywords: Making Password-Cracking Detectable.‚ÄĚ In Proceedings of the 2013 Acm Sigsac Conference on Computer & Communications Security, 145‚Äď60. CCS ‚Äô13. Association for Computing Machinery.

Jung, Jinho, Hong Hu, David Solodukhin, Daniel Pagan, Kyu Hyung Lee, and Taesoo Kim. 2019a. ‚ÄúFuzzification.‚ÄĚ https://github.com/sslab-gatech/fuzzification.

‚ÄĒ‚ÄĒ‚ÄĒ. 2019b. ‚ÄúFuzzification: Anti-Fuzzing Techniques.‚ÄĚ In 28th USENIX Security Symposium (USENIX Security 19), 1913‚Äď30. USENIX Association.

Kang Li. 2018. ‚ÄúAFL‚Äôs Blindspot and How to Resist Afl Fuzzing for Arbitrary Elf Binaries.‚ÄĚ Black Hat USA. August 2018. https://i.blackhat.com/us-18/Wed-August-8/us-18-Li-AFLs-Blindspot-And-How-To-Resist-AFL-Fuzzing-For-Arbitrary-ELF-Binaries.pdf.

Leurent, Ga√ętan, and Thomas Peyrin. 2020. ‚ÄúSHA-1 Is a Shambles - First Chosen-Prefix Collision on Sha-1 and Application to the Pgp Web of Trust.‚ÄĚ Cryptology ePrint Archive, Report 2020/014.

Liu, Xiaolong, Qiang Wei, Qingxian Wang, Zheng Zhao, and Zhongxu Yin. 2018. ‚ÄúCAFA: A Checksum-Aware Fuzzing Assistant Tool for Coverage Improvement.‚ÄĚ Security and Communication Networks 2018.

Miller, Barton, Louis Fredriksen, and Bryan So. 1990. ‚ÄúAn Empirical Study of the Reliability of UNIX Utilities.‚ÄĚ Communications of the ACM 33 (12): 32‚Äď44.

Miller, Charlie. 2010. ‚ÄúAnti-Fuzzing.‚ÄĚ Unpublished. https://www.scribd.com/document/316851783/anti-fuzzing-pdf.

Peng, Hui, Yan Shoshitaishvili, and Mathias Payer. 2018. ‚ÄúT-Fuzz: Fuzzing by Program Transformation.‚ÄĚ In 2018 Ieee Symposium on Security and Privacy (Sp), 697‚Äď710. IEEE.

‚ÄúRadamsa.‚ÄĚ n.d. Accessed July 4, 2020. https://gitlab.com/akihe/radamsa.

Sharma, Vaibhav, Navid Emamdoost, Seonmo Kim, and Stephen McCamant. 2020. ‚ÄúIt Doesn‚Äôt Have to Be so Hard: Efficient Symbolic Reasoning for Crcs.‚ÄĚ

Shastry, Bhargava, Markus Leutner, Tobias Fiebig, Kashyap Thimmaraju, Fabian Yamaguchi, Konrad Rieck, Stefan Schmid, Jean-Pierre Seifert, and Anja Feldmann. 2017. ‚ÄúStatic Program Analysis as a Fuzzing Aid.‚ÄĚ In International Symposium on Research in Attacks, Intrusions, and Defenses, 26‚Äď47. Springer.

She, Dongdong, Kexin Pei, Dave Epstein, Junfeng Yang, Baishakhi Ray, and Suman Jana. 2019. ‚ÄúNEUZZ: Efficient Fuzzing with Neural Program Smoothing.‚ÄĚ In 2019 Ieee Symposium on Security and Privacy (Sp), 803‚Äď17. IEEE.

Stephens, Nick, John Grosen, Christopher Salls, Andrew Dutcher, Ruoyu Wang, Jacopo Corbetta, Yan Shoshitaishvili, Christopher Kruegel, and Giovanni Vigna. 2016. ‚ÄúDriller: Augmenting Fuzzing Through Selective Symbolic Execution.‚ÄĚ In NDSS, 16:1‚Äď16. 2016.

Stevens, Marc. 2013. ‚ÄúNew Collision Attacks on Sha-1 Based on Optimal Joint Local-Collision Analysis.‚ÄĚ In Annual International Conference on the Theory and Applications of Cryptographic Techniques, 245‚Äď61. Springer.

Sutton, Michael, Adam Greene, and Pedram Amini. 2007. ‚ÄúFuzzing: Brute Force Vulnerability Discovery,‚ÄĚ January.

Tonder, Rijnard van, John Kotheimer, and Claire Le Goues. 2018. ‚ÄúSemantic Crash Bucketing.‚ÄĚ In Proceedings of the 33rd ACM/IEEE International Conference on Automated Software Engineering - ASE 2018. ACM Press.

Voris, Jonathan, Jill Jermyn, Angelos Keromytis, and Salvatore Stolfo. 2013. ‚ÄúBait and Snitch: Defending Computer Systems with Decoys.‚ÄĚ

Wang, Yanhao, Xiangkun Jia, Yuwei Liu, Kyle Zeng, Tiffany Bao, Dinghao Wu, and Purui Su. 2020. ‚ÄúNot All Coverage Measurements Are Equal: Fuzzing by Coverage Accounting for Input Prioritization.‚ÄĚ In.

Whitehouse, Ollie. 2014. ‚ÄúIntroduction to Anti-Fuzzing: A Defence in Depth Aid.‚ÄĚ January 2014. https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2014/january/introduction-to-anti-fuzzing-a-defence-in-depth-aid/.

Wressnegger, Christian, Frank Boldewin, and Konrad Rieck. 2013. ‚ÄúDeobfuscating Embedded Malware Using Probable-Plaintext Attacks.‚ÄĚ In International Workshop on Recent Advances in Intrusion Detection, 164‚Äď83. Springer.

Yang, Xuejun, Yang Chen, Eric Eide, and John Regehr. 2011. ‚ÄúFinding and Understanding Bugs in c Compilers.‚ÄĚ In Proceedings of the 32nd Acm Sigplan Conference on Programming Language Design and Implementation, 283‚Äď94.

Yun, Insu, Sangho Lee, Meng Xu, Yeongjin Jang, and Taesoo Kim. 2018. ‚ÄúQSYM : A Practical Concolic Execution Engine Tailored for Hybrid Fuzzing.‚ÄĚ In 27th USENIX Security Symposium (USENIX Security 18), 745‚Äď61. USENIX Association.