Sicherheitslücken finden mit WinAFL
Beim Sicherheitsupdate für Microsoft Windows vom November 2016 (MS16-130, CVE-2016-7212) wurde eine kritische Sicherheitslücke behoben, welche ich gemeldet hatte (siehe Danksagung von Microsoft).
In diesem Artikel möchte ich das Vorgehen und das Tool vorstellen, mit dem die Sicherheitslücke gefunden werden konnte.
Fuzzing und AFL
Wie aus meinem früheren Artikel ersichtlich ist, bin ich ein grosser Fuzzing Enthusiast und konnte diese Sicherheitslücke von Microsoft Windows sowie auch andere Sicherheitsrelevante Softwarefehler bei anderen Firmen (CVE-2011-2989, Mozilla Advisory 2016-53) mit dieser Strategie finden.
Fuzzing ist eine alte und bewährte Strategie, Software auf Fehler zu überprüfen. Dabei werden massenhaft Eingabedaten erzeugt und manipuliert, um dann schlussendlich zu überprüfen, wie sich die Software verhält. Es gibt viele Fuzzingtools und Frameworks (siehe Peach Fuzzer, Sulley, Radamsa), welche verschieden Techniken verwenden, Fehler in der Software zu finden.
Ein Beispiel für eine Fuzzingtechnik ist, dass das Fuzzingtool relativ „dumm“ ist und die Eingabedaten einfach nur mittels „Bit flipping“ manipuliert werden, um diese als Eingabedaten für die zu testende Software zu verwenden (siehe Fuzz testing techniques).
Seit 2014 hat sich das Fuzzingtool American fuzzy loop (kurz AFL) vor allem im Open-Source Bereich durchgesetzt und zahlreiche Sicherheitslücken und Softwarefehler gefunden. Das Besondere an diesem Tool ist, dass durch Instrumentierung von der zu testenden Software die Codepfade beobachtet werden, die durch die Eingabedaten genutzt werden. AFL verwendet dann diese Informationen, um selber weitere Eingabedaten zu erzeugen, welche verschiedene Codepfade abdecken. Wie dieses Experiment zeigt, konnte mit dieser Technik aus einer simplen Datei mit dem Inhalt „hello“, mit der Zeit gültige Bilddaten erzeugt werden.
WinAFL
Das Fuzzingtool AFL ist nur für Linux und Unix Betriebssysteme ausgelegt. Glücklicherweise erschien Mitte diesen Jahres WinAFL, das ein Fork von AFL und für das Windows Betriebssystem ausgelegt ist.
WinAFL verwendet, im Unterschied zu AFL, einen etwas anderen Ansatz für die Instrumentalisierung. Bei AFL wird die Instrumentalisierung statisch beim kompilieren zum Programmcode hinzugefügt. Bei WinAFL wird die Instrumentalisierung dynamisch mittels DynamoRIO erreicht und kann auch bei Software verwendet werden, bei denen nur die ausführbare Binärdatei verfügbar ist (also wenn kein Programmcode vorhanden ist).
WinAFL in Action
Der Programmcode für WinAFL sowie die vorkompilierte Versionen von WinAFL in 32- und 64 Bit sind komplett auf github verfügbar.
Nach dem Klonen vom WinAFL Repository und der Installation von DynamoRIO, kann es auch schon gleich losgehen mit dem Fuzzing.
Eine Bespielapplikation ist auch dabei, welche hier für die Demonstration verwendet wird.
Der Programmcode von der Bespielapplikation (test.exe) ist ziemlich einfach und soll die Basis-Funktion von WinAFL aufzeigen:
wenn in einem Textfile das Wort „test“ enthalten ist, soll ein Programmabsturz verursacht werden, der dann erkannt werden soll.
Für diese Demo verwende ich die 32Bit Version.
Das Testprogramm (test.exe) und das Fuzzingtool (afl-fuzz.exe) sind im Ordner Bin32 zu finden.
Bevor aber angefangen werden kann, muss die Funktion, die das WinAFL Fuzzingtool aufrufen soll, als Konsolen-Parameter in Form von einem Offset (target_offset) mitgegeben werden, den man am besten mit dem WinDbg Tool von Microsoft herausfinden kann.
Nachdem WinDbg gestartet wurde, kann die Bespielapplikation (test.exe) mit dem WinDbg Tool geöffnet werden:
In diesem Beispiel möchten wir einfach die „main“ – Methode mittels WinAFL überprüfen.
Dazu muss folgender WinDbg – Befehl eingegeben werden:
x test!main
Der Offset kann ermittelt werden, indem der Wert von B (Anfangsadresse von test.exe) vom Hex-Wert von A (Adresse von main-funktion) abgezogen wird:
target_offset = A – B = 0x01241010 – 0x01240000 = 0x1010
Achtung! Dieser Offset kann auf einem anderem Computersystem unterschiedlich sein und muss daher individuell ermittelt werden.
Als nächstes stellen wir sicher, dass die Beispielapplikation fehlerfrei ausgeführt werden kann.
Dazu erstellen wir ein Textfile mit einem beliebigen Inhalt und rufen test.exe mit diesem Textfile als zusätzlichem Parameter auf:
Um einen Crash bei der Beispielapplikation zu verursachen muss als Input das Wort „test“ im Textfile vorhanden sein. Dazu ändern wir den vorherigen Inhalt von „noser“ auf „test“ und führen die Beispielapplikation erneut auf:
Wie man sieht konnten wir den Crash erfolgreich auslösen.
Als nächsten Schritt kann nun überprüft werden, ob mit DynamoRIO die Instrumentalisierung und der ermittelte target_offset funktionieren.
Dazu ändern wir unsere Textdatei wieder so um, dass die Beispielapplikation nicht abstürzt („test“ auf „noser“) und rufen unsere Beispielabblikation wie folgt auf:
c:\DynamoRIO-Windows-6.2.0-2\bin32\drrun.exe -c winafl.dll -debug -target_module test.exe -target_offset 0x1010 -fuzz_iterations 5 -nargs 2 — test.exe test.txt
Nachdem auch das geklappt hat sind wir nun bereit unsere Bespielapplikation mit dem WinAFL Fuzzingtool zu testen.
Dazu muss unsere Beispielapplikation wie folgt aufgerufen werden:
C:\winafl\bin32>afl-fuzz.exe -i in -o out -D c:\DynamoRIO-Windows-6.2.0-2\bin32 -t 20000 —
-coverage_module test.exe -fuzz_iterations 1000 -target_module test.exe -target_offset 0x1010 -nargs 2 — test.exe @@
Nach einigen Durchläufen wird WinAFL verschiede Programmpfade finden und sogar der Crash konnte relativ schnell gefunden werden.
Wenn wir das File anschauen im out/crashes Ordner, dann werden wir ein File mit dem Inhalt „test“ finden, welches die Ursache vom Crash ist:
Fazit
Mit WinAFL konnten schon erfolgreich sicherheistrelevante Software-Fehler gefunden werden. Darum kann der Einsatz von WinAFL, um Software auf Softwarefehler zu untersuchen, durchaus eine Variante sein.
Ein Beispiel, wie so eine Teststrategie aussehen könnte, ist bei SQLite zu finden, welche Fuzz Testing mit AFL standartmässig in ihrer Teststrategie integriert haben. Dies könnte sicher auch für Software auf Windows Systemen mit WinAFL adaptiert werden.
Happy Fuzzing!