Fuzzing bezeichnet das systematische Testen von Software mit zufälligen oder gezielt manipulierten Eingabedaten, um unerwartetes Verhalten wie Abstürze oder Sicherheitslücken aufzudecken. Klassisches Fuzzing arbeitet ohne Vorwissen über das System. Beim Fuzzing nach Maß fließen Kenntnisse über Eingabeformate und Protokolle ein, sodass syntaktisch gültige, aber inhaltlich grenzwertige Testdaten in Millionenzahl automatisch erzeugt werden können.
Das Wichtigste in Kürze
- Fuzzing ohne Formatwissen scheitert an Validierungen: Eine zufällig erzeugte IBAN-Nummer trifft die Prüfsumme nur in etwa einem von 8.000 Fällen, was den Fuzzer tagelang beschäftigt, ohne je in die eigentliche Programmlogik vorzudringen.
- Gezieltes Fuzzing nach Maß kombiniert bekannte Syntaxregeln mit kontrollierten Zufallsvariationen, sodass nur einzelne Felder wie der Überweisungsbetrag unsicher bleiben, während der Rest gültig und verarbeitbar bleibt.
- Jedes Programm, das externe Daten verarbeitet, muss mit ungültigen, negativen und mathematisch grenzwertigen Eingaben wie NaN oder negativen Beträgen klarkommen, weil sich solche Werte viral durch nachgelagerte Systeme fortpflanzen können.
- LLMs eignen sich nicht als primäre Testdatengeneratoren, weil sie aus bestehenden Mustern lernen und damit genau jene unbekannten Grenzfälle verfehlen, die Fehler erst aufdecken.
- Die offizielle Testsuite für die E-Rechnung (X-Rechnung) umfasst nur wenige Dutzend Fälle bei 150 Datenfeldern, was automatisierte Testgenerierung zur Pflicht macht, nicht zur Option.
Was ist Fuzzing?
Fuzzing bezeichnet das systematische Traktieren eines Programms mit ungültigen, unerwarteten oder rein zufälligen Eingaben, um zu sehen, wie es darauf reagiert. Stürzt es ab? Hängt es sich auf? Lässt es sich aus dem Takt bringen?
Den Begriff prägte der amerikanische Professor Bart Miller Ende der 80er Jahre. Miller arbeitete von zu Hause über eine einfache Telefonleitung und ein Modem an seinem Großrechner. Bei den in Wisconsin häufigen Gewittern störten elektrische Entladungen die Verbindung, und die Bits und Bytes kamen verändert beim Großrechner an.
Ihm fiel auf, dass viele Programme mit solchen verstümmelten Eingaben überhaupt nicht klarkamen. Daraus machte er eine Programmieraufgabe für seine Studenten: zufällige, sinnlos zusammengewürfelte Eingaben erzeugen und damit gängige Programme der Zeit testen. Das Ergebnis war ernüchternd. Ein Großteil der UNIX-Programme jener Zeit liess sich auf diese Weise aus dem Takt bringen.
Die wissenschaftliche Veröffentlichung scheiterte zunächst an den Gutachtern. Ihr Argument: Warum sollte jemals jemand solche sinnlosen Eingaben an ein Programm schicken? Ende der 80er kannte Miller jeden Nutzer seines Großrechners persönlich. Erst mit dem Internet und anonymen Benutzern wurde klar, wie real die Gefahr ist.
Warum jedes Programm gegen böse Eingaben gesichert sein muss
Jedes Programm, das Daten von extern verarbeitet, darf sich nicht darauf verlassen, dass diese Daten wohlgeformt sind. Das ist die zentrale Konsequenz aus dem Fuzzing-Gedanken.
Ein Angreifer kann aus der Ferne mit zufälligen Daten in ein System hineinstochern. Reagiert das System irgendwann nicht mehr, liegt dort möglicherweise eine Lücke, die sich gezielt erweitern lässt, bis das System manipulierbar wird. Aus diesem Grund gehört Fuzzing heute zum Pflichtprogramm für jede Software, die Daten von dritter Seite verarbeitet.
Das Thema bewegt sich damit an der Schnittstelle von Security und Robustheit. Es geht nicht nur um Sicherheitslücken, sondern auch darum, dass ein System unter unerwarteten Eingaben stabil bleibt.
Wie eine einzelne Eingabe ein System sprengen kann
Schon kleine Manipulationen an validen Daten können erhebliche Wirkung entfalten. Das Beispiel einer Banküberweisung macht das greifbar.
Eine normale Überweisung lautet: von Andreas an Richie, ein Euro. In 99,9 Prozent der Fälle passiert genau das. Interessant wird es bei gezielten Änderungen:
- Negative Werte: Eine Überweisung über minus einen Euro. Hat irgendwo ein Skript vergessen, dass Beträge negativ sein könnten, entsteht ein Loch.
- Unendlich: Ein Betrag von unendlich vielen Euro. Schlägt das durch, ist auch die Bank in Schwierigkeiten.
- Not a Number (NaN): Ein Gleitkomma-Sonderwert. Alles, was mit NaN verrechnet wird, wird selbst zu NaN. Eine einzige akzeptierte NaN-Überweisung könnte die Tagessumme, die Bilanz und den Aktienkurs infizieren.
- Pufferüberlauf: Eine E-Mail-Adresse mit 100.000 Zeichen statt der üblichen 256. Läuft der Zielpuffer über, lassen sich angehängte Zeichen nutzen, um kritische Daten zu überschreiben.
- Befehls-Einschleusung: Statt eines Namens steht in dem Feld ein eingeschmuggeltes Kommando, das am anderen Ende die Datenbank löscht.
Banken sind gegen solche Angriffe gesichert. Die Frage ist, ob das auch für jedes FinTech und jeden Praktikanten-Code gilt. Fuzzing fängt mit Zufallsdaten an und stochert mal hier, mal da, bis das System eine Schwäche zeigt.
Jedes Programm, das Daten von extern verarbeitet, kann sich nicht darauf verlassen, dass die Daten von draußen wohlgeformt sind. Es muss mit fehlerhaften, zufälligen und bösartigen Daten klarkommen.
Andreas Zeller
Fuzzing ist Automatisierung über Stunden, nicht über Minuten
Fuzzing läuft nicht von Hand, sondern automatisiert über lange Zeiträume. Ein Fuzzer läuft typischerweise 24 Stunden, oft Tage, manchmal Wochen, und erzeugt dabei hunderttausende bis Millionen Versuche.
Der Vorteil des reinen Zufalls: Der Fuzzer braucht kein Vorwissen und hat keinen Bias. Er probiert eine Eingabe nach der anderen aus und findet auch Fehler jenseits der bekannten Angriffskataloge. Genau deshalb ist die Trefferchance gut, auch wenn ein Lauf lange dauert.
Ein klassischer Anfängerfehler dabei ist fehlende Protokollierung. Wer eine Woche Zufallsdaten verschickt und beim Absturz nicht mehr weiß, welche Eingabe ihn ausgelöst hat, steht mit leeren Händen da. Aufzeichnen ist Pflicht.
Ebenso wichtig ist eine geschützte Umgebung. Eingeschleuste Befehle können beliebiges Verhalten auslösen, bis hin zum Löschen des eigenen Dateisystems oder genau jener Datenbank, in der die Testdaten liegen. Niemals auf einem Produktivsystem fuzzen.
Warum Zeitbomben besonders schwer zu finden sind
Nicht jeder Fehler zeigt sich sofort. Ein bösartiges Datum kann zu einem frühen Zeitpunkt eingeschleust werden und sich erst viele Interaktionen später manifestieren. Diese Entkopplung von Ursache und Wirkung nennt sich Zeitbombe.
Solche Fehler sind in der Fehlersuche besonders schwierig, weil zwischen Auslöser und sichtbarem Effekt ein großer Abstand liegt. Für einen Angreifer ist das ein perfides Werkzeug: Er schleust das Datum ein und wartet, bis es Wochen später Schaden anrichtet.
Deshalb zeichnet gutes Fuzzing nicht nur die letzte Interaktion auf, sondern die gesamte Folge. Hat man einmal eine reproduzierbare Fehlerfolge, gibt es automatische Verfahren, die sie reduzieren. Aus tausend Interaktionen filtern sie die zwei oder drei heraus, die tatsächlich fehlerrelevant sind.
Warum reiner Zufall an strukturierten Formaten scheitert
Reine Zufallsdaten kommen bei komplexen Eingabeformaten nicht weit. Eine Bank verwirft willkürliche Bytes sofort, weil eine Überweisung eine strenge Struktur hat: ein wohlgeformtes Dokument, Prüfsummen, gültige Felder.
Die IBAN zeigt das Problem in Zahlen. Die zwei Prüfziffern nach der Länderkennung treffen Zufallsdaten nur in etwa einem von 100 Fällen. Die Länderkennung aus zwei Buchstaben trifft etwa in einem von 676 Fällen. Zusammen landet man bei rund einem Treffer pro mehrere tausend Versuche, allein für eine gültige IBAN.
Und eine Überweisung braucht zwei gültige Kontonummern, deine und meine. Das multipliziert sich auf rund 64 Millionen Kombinationen. Ein Fuzzer verbringt damit einen ganzen Tag, nur um überhaupt ein paar valide IBANs zu erzeugen. So dringt er nie zur eigentlichen Logik vor, etwa zur Prüfung des Betragsfeldes.
Der Kern: Datenpakete sind bewusst robust gegen einfache Störungen gebaut. Genau die Mechanismen, die eine Überweisung über eine gewitterstörige Leitung schützen, blockieren auch den naiven Fuzzer.
Fuzzing nach Maß verheiratet Zufall mit Wissen über das System
Fuzzing nach Maß kombiniert die Zufälligkeit des Fuzzings mit herkömmlichen Testmethoden, die Wissen über das System voraussetzen. Statt alles zufällig zu erzeugen, bekommt der Fuzzer die Regeln des Eingabeformats beigebracht.
Sage dem Generator, wie eine IBAN aufgebaut ist: zwei Buchstaben, zwei Prüfziffern, dann die Kontonummer. Ab sofort erzeugt er nur noch Daten, die diesem Muster folgen. Die Wahrscheinlichkeit syntaktisch gültiger Eingaben steigt schlagartig.
Der entscheidende Schritt ist, syntaktisch gültige Daten zu erzeugen, die trotzdem inhaltlichen Unsinn enthalten. Vergleichbar mit einem grammatikalisch korrekten deutschen Satz, der inhaltlich keinen Sinn ergibt. Das Datenpaket muss erst akzeptiert werden, damit ein manipulierter Wert wie minus ein Euro überhaupt in der tieferen Verarbeitung ankommt.
So entsteht gezielte Steuerung. Du baust die Überweisung regelkonform auf, mit Sender, Empfänger, Kontonummern und Betrag, und nimmst dann an ein oder zwei Stellen alle Checks heraus. Beim Betrag etwa jagst du beliebige Werte durch. Das Ergebnis: in einer Minute eine Million Überweisungen, die fast alle stimmen, und ein deutlich effizienterer Test als mit reinem Zufall.
Warum Security und Software-Test unterschiedlich fuzzen
Security und klassischer Software-Test verfolgen mit Fuzzing verschiedene Ziele, und das prägt die Methode.
In der Security will man oft kein Wissen über das angegriffene System voraussetzen. Wer mit Insider-Wissen eindringt, dessen Leistung zählt weniger. Deshalb hält sich die Security an die klassische Methode: alles zufällig hineinhauen, so wenig Vorwissen wie möglich.
Beim Testen der eigenen Software ist die Lage umgekehrt. Du kennst das System und willst es robust machen. Also nutzt du dein Wissen über das Format und über mögliche Schwachstellen aktiv. Wenn die IBAN-Prüfung sicher funktioniert, ignorierst du sie und richtest den Fuzzer auf eine frische, gerade geänderte Stelle.
Genau hier hilft Fuzzing nach Maß. Bestehende Testfälle sind auf bekannte Probleme geeicht und finden neue selten. Ein Generator, der spezifisch auf ein neues Feature zielt, legt den Finger schnell auf die Wunde.
Komplexe Datenformate sind ohne Generierung nicht mehr testbar
Die Komplexität moderner Datenformate übersteigt das, was sich von Hand testen lässt. Die elektronische Rechnung im Format X-Rechnung ist seit diesem Jahr Pflicht und ein gutes Beispiel.
Die X-Rechnung kennt rund 150 verschiedene Datenfelder, darunter Konstruktionen wie Umsätze außerhalb der EU. Die offizielle Testsuite umfasst dagegen nur einige Dutzend Testfälle. Mit so wenigen, handgeschriebenen Rechnungen lassen sich 150 Felder mit ihren Extremwerten und negativen Werten unmöglich abdecken.
Solche Mengen tippt niemand mehr von Hand ein. Ohne automatisierte Generierung von Testdaten ist eine so umfangreiche Prüfung nicht machbar.
Hinzu kommt der unsichere Kanal. Elektronische Rechnungen kommen per E-Mail, und jeder kann behaupten, jemand anderes zu sein. Wo früher ein Mensch das Papier las und nur begrenzte Varianten möglich waren, treffen jetzt frische, kaum gereifte Implementierungen auf ein offenes Tor.
Die offenen Herausforderungen: Coverage, Orakel und LLMs
Fuzzing löst nicht alles. Drei Probleme bleiben hartnäckig.
Abdeckung: Viele Sonderfälle stecken nicht im Datenformat, sondern in der Verarbeitung. Dass ein Empfänger auf einer Sperrliste steht, lässt sich aus den Eingabedaten nicht ableiten, dafür gibt es kein Feld. Ein guter Fuzzer erkennt, welche Verzweigungen im Programmlauf noch nicht genommen wurden, und konzentriert sich darauf. Auch gute Fuzzer schaffen jedoch nur einen Teil aller Verzweigungen.
Das Orakel-Problem: Hat das System das Richtige getan? Gängige Fuzzer prüfen nur auf generische Fehler wie Absturz oder Aufhängen. Eine Fehlermeldung ignorieren viele, weil Security-Leute den unkontrollierten Absturz suchen. Als Tester willst du dagegen prüfen, ob eine Fehlermeldung angemessen ist und ob das fachlich Richtige passiert. Dafür gute Prüfungen zu bauen, bleibt schwierig.
Grenzen der LLMs: Machine Learning lernt aus bestehenden Daten und erzeugt Ähnliches. Das funktioniert für Bewerbungen, Code und Bilder, die andere schon gemacht haben. Bei Testdaten will man oft genau das Gegenteil. Bittet man ein LLM, aus 100 vorhandenen Überweisungen 100 weitere zu erzeugen, sehen die neuen aus wie die alten. Dann könnte man gleich die Trainingsdaten zum Testen nehmen.
Für einzelne Datenfelder, etwa das Generieren gültiger IBANs, sind LLMs durchaus brauchbar. Für die kreative Aufgabe aber, etwas zu erzeugen, das so noch nicht getestet wurde, sind sie denkbar schlecht geeignet. Genau hier bleibt der kreative Tester gefragt, der Fehler findet, bevor ein externer Angreifer darauf stösst.


