-
Die Erfindung betrifft computer-implementierte Verfahren zum Fuzzing einer Zielsoftware, ein entsprechendes Computerprogramm sowie ein entsprechendes Fuzzing-System.
-
Stand der Technik
-
In
DE 10 2021 207248 wird ein Verfahren zum systematischen Multi-Prozess-Interface-Fuzzing beschrieben.
DE 10 2019 211037 offenbart ein Verfahren zur effizienten Kombination von dynamischen und statischen Analysen von Systemen.
-
In „NEUZZ: Efficient Fuzzing with Neural Program Smoothing“, D. She, K. Pei, D. Epstein, J. Yang, B. Ray und S. Jana, 2019 IEEE Symposium on Security and Privacy (SP), 2019, Seiten 803-817, doi: 10.1109/SP.2019.00052 verbessern die Autoren vorhandene Fuzzing-Techniken, indem maschinelles Lernen (ML) aufgenommen wird. Wie sie gezeigt haben, ist ihr gradientengesteuertes, als NEUZZ bezeichnetes Fuzzing-Verfahren besonders erfolgreich, wenn komplexe Eingabeformate erkannt werden müssen. Die Lösung dieser hochdimensionalen strukturierten Optimierungsprobleme stellt weiterhin ein offenes Problem dar, aber NEUZZ scheint besser zu sein als Fuzzer nach dem Stand der Technik.
-
NEUZZ beruht auf folgender Idee: Ein neuronales Netz wird dahingehend trainiert, dass es als eine glatte Annäherung des ursprünglichen Programms im Hinblick auf die Codeabdeckung dient, die dann verwendet werden kann, um Programmeingaben vorzuschlagen, die verschiedene Bereiche des Codes erreichen. NEUZZ repräsentiert die verschiedenen Pfadabdeckungen jeder einzelnen Programmeingabe des Zielprogramms als binäre Vektoren. Elemente in Abdeckungsvektoren, die beständig null sind, repräsentieren Code-Zweige, die nie erreicht werden, was durch Fuzzing erkannt werden soll. Das durch NEUZZ trainierte neuronale Netz stellt eine glatte Approximation des Zielprogramms im Hinblick auf die Codeabdeckung dar. Dieses Modell wird verwendet, um ein Optimierungsproblem zu lösen, das Eingaben erzeugt, welche in der Lage sind, nicht abgedeckte Zweige zu erreichen.
-
Offenbarung der Erfindung
-
Offenbart wird ein computer-implementiertes Verfahren zum Fuzzing einer auf einem Computer ausgeführten Zielsoftware, wobei das Verfahren die folgenden Schritte umfasst:
- - eine Zielsoftware (ein Computerprogramm) wird unter Verwendung erster Eingabedaten ausgeführt,
- - Speicherkontextinformationen einer Ausführung des Zielprogramms werden erfasst,
- - ein Modell des maschinellen Lernens wird unter Verwendung der ersten Eingabedaten und der Speicherkontextinformationen als Modelleingabe trainiert,
- - eine Fuzzing-Eingabe wird auf der Grundlage einer Ausgabe des Modells des maschinellen Lernens erzeugt,
- - das Zielprogramm wird unter Verwendung der Fuzzing-Eingabe getestet.
-
Die entsprechenden Verfahren verwenden einen Speicherkontext, um ein durch maschinelles Lernen gesteuertes Fuzzing in Richtung Testeffektivität (mehr Fehler finden) und Effizienz (Verwendung der Testzeit) zu unterstützen. Speicherkontextinformationen bereichern das durch maschinelles Lernen unterstützte Fuzzing, um mit weniger Versuchen bessere Eingaben zu generieren, insbesondere für zustandsbehaftete, langsame oder eingebettete Software.
-
In bevorzugten Ausführungsformen wird das Modell des maschinellen Lernens unter Verwendung eines überwachten Trainings trainiert. Das Modell des maschinellen Lernens kann zum Beispiel als ein neuronales Netz oder unter Verwendung von Stützvektormaschinen realisiert werden. Das Modell des maschinellen Lernens kann auf der Grundlage der Fuzzing-Eingabe und der Speicherkontextinformationen des Tests des Zielprogramms, das die Fuzzing-Eingabe verwendet, neu trainiert werden.
-
Das hier vorgeschlagene Verfahren befasst sich mit den Nachteilen des einfachen abdeckungsgesteuerten Fuzzings sowie mit den Nachteilen der vorstehend vorgestellten NEUZZ-Methode.
-
Nachteile des einfachen abdeckungsgesteuerten Fuzzings:
- - Fuzzing beruht auf einer schnellen Ausführung der Ziel-Binärdatei und kompensiert die Unkenntnis des Ziels durch das Ausprobieren einer Unmenge verschiedener Eingaben. Jedoch ist für langsame Ziele eine intelligentere Erzeugung von Eingaben erforderlich.
- - Für Ziele, die zustandsbehaftet sind, wird einfaches Fuzzing ineffizient. Wenn der Fuzzer keine Kenntnis über den jetzigen Zustand des Ziels aufweist, können sogar identische Eingaben verschiedene Verhaltensweisen auslösen. Das Ziel verhält sich für den Fuzzer nicht deterministisch.
-
Nachteile von NEUZZ:
- - NEUZZ beruht auf einer Kantenabdeckung, um sein Modell zu trainieren und den Fuzzing-Prozess zu verbessern. Dies funktioniert nicht für zustandsbehaftete Software, da Kantenpfade für eine zustandsbehaftete Software unendlich oder ununterscheidbar für verschiedene Zustände sein können.
- - Während NEUZZ versucht, unterschiedliche Verhaltensweisen bezüglich der Kantenabdeckung auszulösen, löst der vorliegende Vorschlag unterschiedliche Verhaltensweisen auf der Grundlage von Speicherzugriffen aus. Dadurch wird der Zustand der Software intrinsisch, durch Beobachten aller Speicherzugriffe während der Ausführung gelernt.
- - Da NEUZZ mit AFL zusammenarbeitet, weist es die gleichen Nachteile auf, wenn es um eingebettete Software geht. Die Zielsoftware ist z.B. nur auf einer x86-Architektur fuzzingfähig. Ein Portieren eingebetteter Software in einen fuzztestbaren Zustand stellt weiterhin ein offenes Problem dar. Der vorliegende Ansatz kann mit Speicherschnappschüssen oder Differenzen von Speicherschnappschüssen arbeiten, die problemlos von eingebetteten Vorrichtungen erlangt werden können.
-
In bevorzugten Ausführungsformen wird die Fuzzing-Eingabe auf der Grundlage der Ausgabe des Algorithmus für maschinelles Lernen durch einen Optimierungsalgorithmus generiert, um spezifische Speicherzustände oder Speicherzugriffe des Zielprogramms zu erlangen. Die Speicherkontextinformationen können mindestens eines von einer Speicherzustandsinformation, einer Speicherzugriffsinformation, einer Information über Speicheroperationen während der Ausführung des Programms, einem Schnappschuss des gesamten Speichers nach der Verarbeitung von Daten oder einer Sequenz von Speicherschnappschüssen umfassen.
-
Ausführungsformen der Erfindung werden unter Bezugnahme auf die aufgenommenen Zeichnungen beschrieben:
- 1 zeigt schematisch den Beispielaufbau eines Fuzz-Testsystems.
- 2 zeigt schematisch ein Beispielablaufdiagramm, das einer bevorzugten Ausführungsform der vorgeschlagenen Fuzzing-Verfahren entspricht.
-
Beschreibung der Ausführungsformen
-
Diese Erfindungsoffenbarung betrifft ein Fuzz-Testverfahren und -system, die maschinelles Lernen verwenden, um Speicherkontextinformationen in der Generierung von Eingabedaten für ein Fuzzing einer Zielsoftware aufzunehmen.
-
Ein Fuzzing oder Fuzz-Testing stellt eine automatisierte Softwaretesttechnik dar, die ein Bereitstellen ungültiger, unerwarteter oder zufälliger Daten als Eingaben in ein Zielcomputerprogramm und ein Überwachen seiner Reaktion, z.B. ob die Software abstürzt oder die eingebauten Code-Assertions fehlschlagen, umfasst.
-
Die Programme, die Eingaben automatisch generieren, werden als Fuzzer oder Fuzz-Engines bezeichnet. Sie werden im Allgemeinen entwickelt, um jede zu testende Software generisch zu testen. Sie weisen typischerweise die Fähigkeiten auf, Code zu instrumentieren, Testfälle zu generieren und zu testende Programme auszuführen. Zu weit verbreiteten Beispielen gehören afl und libfuzzer.
-
Das Softwareprogramm oder die Softwarefunktion, das/die mithilfe von Fuzzing getestet werden soll, wird Fuzz-Ziel genannt. Ein Hauptmerkmal eines Fuzz-Ziels sollte sein, dass es potenziell nicht vertrauenswürdige Eingaben verbraucht, die durch den Fuzzer während des Fuzzing-Prozesses erzeugt werden. Häufig erfordern Fuzz-Ziele strukturierte Eingaben, die z.B. in einem Dateiformat spezifiziert sind. Daher sollte die durch den Fuzzer erzeugte Eingabe auf eine Weise erzeugt werden, dass sie durch den Parser akzeptiert wird, jedoch weiterhin Randfälle testet oder zu einem überraschenden Verhalten des Ziels führt.
-
Die kombinierte Version eines Fuzzers und eines Fuzz-Ziels wird als Fuzz-Test bezeichnet. Ein Fuzz-Ziel kann dann instrumentierter Code mit einem Fuzzer sein, der an seinen Eingängen angebracht ist. Ein Fuzz-Test ist ausführbar. Der Fuzzer kann außerdem mehrere laufende Fuzz-Tests (typischerweise hunderte oder tausende pro Sekunde), jeder mit einer durch den Fuzzer generierten, leicht anderen Eingabe, starten, beobachten und anhalten.
-
Eine konkrete Eingabe und eine Testausführung eines Fuzz-Tests werden als Testfall bezeichnet. In der Regel werden aus Gründen der Reproduzierbarkeit interessante Durchläufe (das Finden neuer Codepfade oder Abstürze) gespeichert. Auf diese Weise kann ein spezifischer Testfall mit seiner entsprechenden Eingabe auch auf einem Fuzz-Ziel ausgeführt werden, das nicht mit einem Fuzzer verbunden ist, d.h. in seiner Release-Version.
-
Es bestehen verschiedene Optionen, ein effizientes Fuzzing zu realisieren:
- - Befehle können in ein Programm eingegeben werden, um ein Feedback von der Ausführung zu erzeugen (statische Instrumentierung). Dies kann durch den Compiler realisiert werden und kann zum Beispiel die während der Ausführung erreichten Code-Blöcke beschreiben.
- - Die Ausführung eines Programms kann während der Laufzeit gesteuert werden, um ein Feedback von der Ausführung zu generieren (dynamische Instrumentierung). Es wird meist durch Betriebssystemfunktionalitäten oder durch Verwenden von Emulatoren realisiert.
- - Codeabdeckungsinformationen können als Feedback während des Fuzzings verwendet werden, um zu detektieren, ob eine Eingabe die Ausführung von neuen Code-Pfaden/-Blöcken verursacht hat (abdeckungsgesteuertes Fuzzing).
- - Neue Eingaben können erzeugt werden, indem ein Satz bekannter Eingaben (Korpus) verwendet wird und Mutationen auf sie zufällig angewendet werden (mutationsbasiertes Fuzzing).
- - Neue Eingaben können zum Beispiel unter Verwendung von Eingabemodellen oder Eingabegrammatiken von Grund auf neu erstellt werden (generationsbasiertes Fuzzing)
-
Fuzzer nach dem Stand der Technik, wie z.B. AFL, Honggfuzz oder Libfuzzer, stellen mutationsbasiertes, abdeckungsgesteuertes Fuzzing zum Testen von Software bereit. Dabei wird in jeder Runde eine Seed-Eingabe aus dem Eingabekorpus ausgewählt, zufällig mutiert und an das Zielprogramm gesendet. Wenn die neu generierte Eingabe ein zuvor nicht beobachtetes Verhalten auslöst (wie z.B. neue ausgeführte Codepfade), wird sie zum Eingabekorpus hinzugefügt. Auf diese Weise kann der Eingaberaum eines Programms ohne oder mit wenig Wissen über das Eingabeformat erkundet werden.
-
1 zeigt schematisch den Beispielaufbau eines Fuzz-Testsystems, wobei das Fuzzing-System mit einem Algorithmus (Modell) des maschinellen Lernens erweitert ist, und dadurch verbessert ist, dass es zusätzlich einen Speicherkontext empfängt.
-
Speicherkontextinformationen können zum Beispiel Folgende sein:
- • eine Auflistung aller Speicheroperationen während der Ausführung des Programms (Speicheradresse, Größe, Lesen oder Schreiben),
- • ein Schnappschuss des gesamten Speichers nach der Verarbeitung von Daten (bevorzugt für Vorrichtungen mit einem kleinen internen RAM),
- • eine Sequenz von Speicherschnappschüssen bezüglich einer Serie von Eingaben (Eingabesequenz).
-
Während eine Auflistung von Speicheroperationen für typische Benutzeranwendungen abgerufen werden kann, ist der Schnappschussmechanismus für eingebettete Geräte mit einer kleinen Größe eines internen Speichers gedacht, bei denen der Schnappschuss durch eine Debugging-Verbindung abgerufen werden kann. Für bevorzugte Ausführungsformen kann es irrelevant sein, wie die Speicherkontextdaten abgerufen und repräsentiert werden, solange das Modell des maschinellen Lernens daraus ein Verhalten ableiten kann.
-
Ein typischer Fuzzing-Aufbau, der Seeds 11, einen Fuzzer 12 und ein Zielprogramm 13 umfasst, ist um eine Komponente 14 des maschinellen Lernens erweitert.
-
Die Seeds 11 werden ausgewählt und als ausgewählte Seeds an den Fuzzer 12 übertragen (112). Der Fuzzer 12 wählt eine Testeingabe aus. Die ausgewählte Testeingabe wird als Eingabe an die Komponente 14 des maschinellen Lernens übertragen (124) und als Eingabe an das Zielprogramm 13 übertragen (123).
-
Die Komponente 14 des maschinellen Lernens umfasst ein Modell oder einen Algorithmus des maschinellen Lernens, das/der einen Aspekt des Zielprogramms imitiert oder beschreibt. Der betrachtete Aspekt, insbesondere Speicherkontextinformationen 15, wird als leitendes Feedback in der Fuzzing-Schleife verwendet. Das Modell des maschinellen Lernens 14 sagt Speicherkontextinformationen 15 voraus und gibt diese aus (145).
-
In der nächsten Iteration der Fuzzing-Schleife werden das Feedback 151 des maschinellen Lernens und das Ausführungsfeedback 131 zum Generieren weiterer Seeds 11 verwendet.
-
In einer bevorzugten Ausführungsform beruht die Leitungsstrategie auf Speicherzugriffsinformationen für das Ziel. Der Algorithmus des maschinellen Lernens wird pro Zielprogramm mit der Endzielsetzung trainiert, ihn zum Generieren neuer erfolgsversprechender Programmeingaben zu verwenden, die im Fuzzing-Prozess untersucht werden sollen.
-
Eine Ausführungsform des entsprechenden Fuzzing-Verfahrens umfasst drei Schritte:
-
1. Datensammlung für ein Modelltraining (fakultativ)
-
Dieser Schritt zielt darauf ab, Daten über das Zielprogramm zu sammeln, die zum Trainieren eines Modells des maschinellen Lernens verwendet werden können. Programmeingaben werden in das Zielprogramm eingegeben und seine Speicherzugriffe oder -zustände werden für jede Eingabe beobachtet und aufgezeichnet.
Dieser Schritt ist optional, weil die Benutzer möglicherweise bereits verfügbare Daten haben.
-
2. Modelltraining
-
Ein Modell des maschinellen Lernens wird in einem überwachten Aufbau auf der Grundlage der gesammelten Daten trainiert: (a) Paare entsprechender Programmeingaben und (b) der Programmantwort auf die Eingabe im Hinblick auf einen Speicherzugriff oder -zustände. Eine beliebige Art eines Modells des maschinellen Lernens, die Gradientenverfahren unterstützt und für überwachte Aufgaben funktioniert, kann verwendet werden, z.B. neuronale Netze oder Stützvektormaschinen.
-
Das Modell verwendet als Eingabe das gleiche Format wie das Zielprogramm. Auf dieser Grundlage wird das Modell trainiert, um die Speicherzugriffe vorherzusagen, die das Zielprogramm für jede gegebene Eingabe vornehmen würde. Nachdem es trainiert wurde, ist das Modell des maschinellen Lernens in der Lage, Speicherzugriffe für eine Zielprogrammeingabe vorherzusagen, ohne dass das Programm ausgeführt werden muss. In diesem Sinne wirkt das Modell als ein Orakel für Speicherzugriffe des Zielprogramms.
-
3. Programmeingabegenerierung
-
Die Generierung interessanter Eingaben für den Fuzzing-Prozess verwendet das trainierte Modell und versucht die Frage zu beantworten: Wie eine gegebene Programmeingabe geändert werden sollte, so dass sich ihre vorhergesagten Speicherzugriffe auf eine bestimmte Weise ändern? In der Praxis wird diese Frage beantwortet, indem ein Optimierungsproblem gelöst wird. Das im vorherigen Schritt trainierte Orakel ist für die Lösung des Optimierungsproblems wesentlich, da es differenzierbare Approximation des Zielprogramms repräsentiert, das selbst nicht differenzierbar ist. Eine große Auswahl von Optimierungsalgorithmen kann verwendet werden, um eine modifizierte Version der Eingabe zu berechnen, die bestimmte, für das Fuzzing interessante Speicherzustände oder -zugriffe erzeugt. Diese umfassen stochastisches Gradientenabstiegsverfahren, AdaGrad [Duchi et al., Adaptive Subgradient Methods for Online Learning and Stochastic Optimization, Conference on Learning Theory, 2010], RMSProp [Hinton, G., Unveröffentlicht:
- http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf, Zugriff am 8. November 2021] und ihr neueres Gegenstück Adam [Kingma, D. P. & Ba, J., Adam: A Method for Stochastic Optimization. International Conference for Learning Representations, 2015], und sind nicht auf diese beschränkt. In der Praxis schneidet Adam in der Regel am besten ab, da es Momente erster und zweiter Ordnung wirksam einsetzt.
-
Die drei vorherigen Schritte können einmal oder mehrmals durchgeführt werden, wobei das Modell von Grund auf neu trainiert wird, wenn mehr Daten für das Training verfügbar werden. Alternativ kann ein Online-Lernansatz implementiert werden, bei dem das Modell des maschinellen Lernens mit dem Feedback von Eingaben, die es generiert hat und die das vorhergesagte Speicherzustandsziel nicht erreicht haben, verfeinert wird. Dieser letztere Ansatz ermöglicht es, jegliche blinden Flecken, die das Modell des maschinellen Lernens möglicherweise aufweist, explizit zu berücksichtigen und zu korrigieren.
-
2 zeigt schematisch ein Beispielablaufdiagramm, das einer bevorzugten Ausführungsform der vorgeschlagenen Fuzzing-Verfahren entspricht.
-
In diesem Beispiel ist das trainierte Modell ein neuronales Netz und das Optimierungsverfahren, das zum Generieren verbesserter Programmeingaben verwendet wird, ist ein Standard-Gradientenabstiegsverfahren. Das neuronale Netz wird in diesem Beispiel periodisch neu trainiert, um vom letzten durch den Fuzzer erzeugten Feedback zu profitieren.
-
In einem ersten Schritt 21 werden Trainingsdaten erzeugt, die für den Algorithmus des maschinellen Lernens verwendet werden sollen, indem das Zielprogramm 212 mit allen verfügbaren Testeingaben 211 ausgeführt wird, während die gewünschten Speicherkontextinformationen 213 aufgezeichnet werden.
-
In einem zweiten Schritt 22 wird ein in diesem Beispiel als Modell des maschinellen Lernens gewähltes neuronales Netz 221 unter Verwendung der Eingabe 211 sowie der entsprechenden Speicherkontextinformation 213 als Eingaben trainiert.
-
In einem dritten Schritt 23 werden eine Ausgabe des neuronalen Netzes 221 sowie seine Eingaben für eine Generierung 231 mutierter Eingaben 232 für weiteres Fuzzing verwendet.
-
Für die Generierung 231 mutierter Eingaben 232 werden Speicherzugriffe aus den Speicherkontextinformationen 213 ausgewählt. Für jene Speicherzugriffe werden Gradienten bezüglich der Eingabe 211 berechnet. Unter Verwendung jener Berechnungen werden Positionen mit den steilsten Gradienten ausgewählt. Für jene ausgewählten Positionen werden Mutationen angewendet, wodurch ein Satz mutierter Eingaben 232 generiert wird.
-
Da in diesem Beispiel das Training des Algorithmus des maschinellen Lernens ein periodisches erneutes Training umfasst, wird der Satz mutierter Eingaben 231 in Schritt 21 als Eingabe 211 wieder verwendet, die zum Testen des Zielprogramms 212 und Generieren weiterer Trainingsdaten 211 und 213 verwendet wird.
-
Dieses Verfahren ermöglicht es, neue Testeingaben zu generieren, die auf der Grundlage des Speicherverhaltens vorheriger Testeingaben eine hohe Wahrscheinlichkeit des Auslösens eines unterschiedlichen Speicherverhaltens aufweisen. Dies ist besonders nützlich, wenn anderes Verhaltensfeedback, wie z. B. Codeabdeckung, aus dem Ziel, besonders für eingebettete Software oder zustandsbehaftete Software, nicht abgerufen werden kann. Zum Beispiel stellt ein Generieren einer Codeabdeckung von einem eingebetteten System einen offenen Forschungsbereich dar, während ein Speicherschnappschuss über eine Debugging-Verbindung vorgenommen werden kann.
-
ZITATE ENTHALTEN IN DER BESCHREIBUNG
-
Diese Liste der vom Anmelder aufgeführten Dokumente wurde automatisiert erzeugt und ist ausschließlich zur besseren Information des Lesers aufgenommen. Die Liste ist nicht Bestandteil der deutschen Patent- bzw. Gebrauchsmusteranmeldung. Das DPMA übernimmt keinerlei Haftung für etwaige Fehler oder Auslassungen.
-
Zitierte Patentliteratur
-
- DE 102021207248 [0002]
- DE 102019211037 [0002]