Aus Linux-Magazin 12/2021

Im Gespräch mit dem Erfinder des Fuzz Testings, Prof. Barton Miller

© Vitaliy Vodolazskyy / 123RF.com

Ende der 1980er-Jahre stieß Barton Miller zufällig darauf, dass verstümmelte Eingaben Unix-Tools abstürzen ließen. Daraus entwickelte sich eine heute nicht mehr wegzudenkende Testmethodik mit Zufallseingaben, das Fuzz Testing.

Linux-Magazin: Eignen sich einige Applikationen besser als andere für das Fuzz Testing?

Barton Miller: Das ist keine Frage der Eignung. Es geht darum, die Schnittstelle zur Anwendung zu identifizieren und herauszufinden, wie man gegen sie testen kann. Einige sehr einfache Programme beziehen ihre Eingaben zum Beispiel aus einer Datei oder von der Tastatur, der Standardeingabe. In diesem Fall ist es recht trivial, Eingaben für ein solches Programm zu erzeugen.

Andere Programme verwenden die Maus und die Tastatur, was bedeutet, dass die Eingabe über das Fenstersystem erfolgt – typischerweise X Windows bei Unix, Win32 bei Microsoft Windows und Aqua bei MacOS. Bei dieser Art der Eingabe muss das Testprogramm die Fenster und ihre Größe erkennen und dann die passenden Fensterereignisse erzeugen, etwa Mausbewegungen und Tastendrücke. Bei einer Telefonanwendung wiederum basiert die Eingabe auf Berührungen und Gesten, sodass der Tester hier in der Lage sein muss, diese Ereignisse zufällig zu erzeugen.

Barton Miller

Barton Miller ist ein mehrfach ausgezeichneter (Vilas Distinguished Achievement Professorship, Amar & Belinder Sohi Professorship) Professor für Computerwissenschaften an der University of Wisconsin, Madison. Er leitet das Projekt Paradyn Tools, das die Skalierbarkeit von Programmen sowie Technologien zur Analyse und Instrumentierung von Binärprogrammen für den Einsatz in HPC, Systemdesign und Cybersicherheit untersucht. 1988 erfand Miller die Methode der zufälligen Softwaretests (Fuzz Testing), die sich inzwischen zu einer führenden Testdisziplin entwickelt hat.

LM: Oft verwendet man Fuzz Testing für Sicherheitszwecke, um Schwachstellen aufzudecken, die ein Angreifer nutzen könnte, um die Sicherheitsmaßnahmen seines Opfers auszuhebeln. Doch wie wahrscheinlich ist es dabei, dass ein zufällig generierter String einer ausgeklügelten Angriffstechnik entspricht?

BM: Häufig läuft es genau andersherum: Ein Angreifer nutzt Fuzz-Tests, um zu sehen, ob er ein Programm zum Absturz bringen kann. Das bedeutet, dass er versucht, das Programm in einen Zustand zu versetzen, den der Programmierer nicht beabsichtigt hat.

In der Geheimdienstwelt nennt man das “owning the bits” – die Bits besitzen. Es geht darum, Bits in einem Programmzustand zu besitzen, in dem man dazu eigentlich nicht in der Lage sein sollte. Das kann man zum Beispiel nutzen, um einen Puffer überlaufen zu lassen oder eine Zahl negativ zu machen, die immer positiv sein sollte, etwa den Index eines Arrays.

Sobald ein Angreifer (oder ein Analytiker) einen Absturz verursacht, steht fest, dass das Programm nicht alles überprüft, was es überprüfen sollte. Die Aufgabe für den Angreifer besteht nun darin, seine Eingaben so zu gestalten, dass er diese eingeschränkte Prüfung auszunutzen vermag.

LM: Kann man sagen, dass ein Fuzz-Test eher einfache Fehler aufdeckt? Wenn die Anwendung aufgrund eines groben Verstoßes gegen die Erwartungen abstürzt, könnten dann Fehler unentdeckt bleiben, die erst am Ende einer Kette auftreten?

BM: Fuzz-Tests durchlaufen den Zustandsraum des zu testenden Programms nach dem Zufallsprinzip. Rein zufällige Eingaben – unstrukturierte Fuzz-Tests – lösen wahrscheinlich Fehler zu einem frühen Zeitpunkt in der Verarbeitung aus und erreichen keine Stellen tief in der Programmlogik.

Komplexere Logikfehler lassen sich trotzdem finden und werden das manchmal auch. Dazu verleiht der Tester seinen Eingaben Struktur, etwa durch richtig strukturierte Fensterereignisse oder Netzwerkpakete. Diese haben trotz ihres zufälligen Inhalts eine gültige Struktur und ermöglichen so das Testen von tieferen Schichten im Code.

Der Schlüssel zu jedem Testsystem ist die Abdeckung, die besagt, wie viel des Programmcodes tatsächlich getestet wurde. Viele moderne Fuzz-Tester wie AFL, Libfuzz oder Hongfuzz arbeiten abdeckungsgesteuert. Sie verfolgen, welche Codeblöcke das Programm für jede Eingabe ausgeführt hat, und versuchen dann, neue Eingaben zu erzeugen, die andere Teile des Codes testen.

LM: Wie sicher kann man von einem entdeckten Fehler auf eine Klasse von Fehlern schließen, die sich dahinter verbergen könnten?

BM: Sicherlich sollte ein menschlicher Analytiker, wenn er einen bestimmten Fehlertyp findet, an anderer Stelle im Code nach derselben Fehlerklasse suchen. Ich habe aber noch keine gute Möglichkeit gefunden, diese Idee zu automatisieren.

LM: Sollten Fuzz-Tests bei erkannten Fehlern immer mit einer Suche nach der Ursache Hand in Hand gehen, um den genauen Mechanismus aufzudecken, der zu dem Fehler führt?

BM: Das ist eine gute Frage, nicht nur für Fuzz-Tests. Wenn Sie ein fehlerhaftes Verhalten in Ihrem Programm entdecken, haben Sie den Fehler erst dann wirklich gefunden, wenn Sie zum einen die spezifische(n) Codezeile(n) identifizieren können, die den Fehler verursachen, und zum anderen in der Lage sind, zu erklären, warum der Fehler auftrat. Andernfalls können Sie nur raten, wie sich der Fehler beheben lässt. Es mag so aussehen, als sei er verschwunden, aber Sie haben ihn wahrscheinlich nur verschleiert oder verschoben. Kein guter Programmierer gibt sich zufrieden, bevor er die exakte Ursache eines Fehlers ausfindig gemacht hat.

LM: Professor Miller, wir danken für das aufschlussreiche Gespräch.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 2 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben