@AndreasZeller
Software-Tests automatisch erzeugen:
Frische Ansätze für Forschung, Praxis und Lehre
Andreas Zeller
CISPA Helmholtz-Zentrum für Informationssicherheit
www.fuzzingbook.org
@AndreasZeller
I ❤ SEUH
I ❤ TAV
─┐	CISPA	|	Center	for	IT-Security,	Privacy	and	Accountability	└─
─┐	CISPA	|	Center	for	IT-Security,	Privacy	and	Accountability	└─
Wissenschaftliche Exzellenz in Grundlagenforschung
50.000.000 €/Jahr • 500–900 Forscher
Fuzzing

Testen mit zufälligen Eingaben
[;x1-GPZ+wcckc];,N9J+?#6^6e?]9lu2_%'4GX"0VUB[E/r
~fApu6b8<{%siq8Zh.6{V,hr?;{Ti.r3PIxMMMv6{xS^+'Hq!AxB"YXRS@!
Kd6;wtAMefFWM(`|J_<1~o}z3K(CCzRH JIIvHz>_*.>JrlU32~eGP?
lR=bF3+;y$3lodQ<B89!5"W2fK*vE7v{')KC-i,c{<[~m!]o;{.'}Gj(X}
EtYetrpbY@aGZ1{P!AZU7x#4(Rtn!q4nCwqol^y6}0|
Ko=*JK~;zMKV=9Nai:wxu{J&UV#HaU)*BiC<),`+t*gka<W=Z.
%T5WGHZpI30D<Pq>&]BS6R&j?#tP7iaV}-}`?[_[Z^LBMPG-
FKj'xwuZ1=Q`^`5,$N$Q@[!CuRzJ2D|vBy!^zkhdf3C5PAkR?V hn|
3='i2Qx]D$qs4O`1@fevnG'211Vf3piU37@55apzIyl"'f,
$ee,J4Gw:cgNKLie3nx9(`efSlg6#[K"@WjhZ}r[Scun&sBCS,T[/
vY'pduwgzDlVNy7'rnzxNwI)(ynBa>%|b`;`9fG]P_0hdG~$@6
3]KAeEnQ7lU)3Pn,0)G/6N-wyzj/MTd#A;r
Fuzzing

Testen mit zufälligen Eingaben
Barton P. Miller
Fuzzer
Fuzzing

Zufällige Eingaben für Programmme
UNIX-
Werkzeuge
“ab’d&gfdfggg” 25%–33%grep • sh • sed …
@AndreasZeller
Demo
@AndreasZeller
• Annahme: Ich möchte einen Parser testen,
der komplexe Eingaben verarbeitet
• Um am Parser vorbeizukommen, braucht
man syntaktisch gültige Eingaben
Grammatik-basiertes Fuzzing
Parser
LangFuzz (2012)
• Fuzzer für JavaScript und andere
Sprachen
• Nutzt Grammatiken, um
Eingaben zu erzeugen
• Nutzt die Grammatik, um
existierende Eingaben zu
verarbeiten
<start> ::= <expr>
<expr> ::= <expr> + <term> | <expr> - <term> | <term>
<term> ::= <term> * <factor> | <term> / <factor> | <factor>
<factor> ::= +<factor> | -<factor> | (<expr>) |
<integer> | <integer>.<integer>
<integer> ::= <integer><digit> | <digit>
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
Eine Grammatik
• Grammatik für arithmetische Ausdrücke:









• <start> expandiert zu <expr>; <expr> zu <term>,
<term> zu <expr> + <term>, usw.
Fuzzing mit Grammatiken
<start> ::= <expr>
<expr> ::= <expr> + <term> | <expr> - <term> | <term>
<term> ::= <term> * <factor> | <term> / <factor> | <factor>
<factor> ::= +<factor> | -<factor> | (<expr>) |
<integer> | <integer>.<integer>
<integer> ::= <integer><digit> | <digit>
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<start>
<start> ::= <expr>
<expr> ::= <expr> + <term> | <expr> - <term> | <term>
<term> ::= <term> * <factor> | <term> / <factor> | <factor>
<factor> ::= +<factor> | -<factor> | (<expr>) |
<integer> | <integer>.<integer>
<integer> ::= <integer><digit> | <digit>
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<expr>
Fuzzing mit Grammatiken
<start> ::= <expr>
<expr> ::= <expr> + <term> | <expr> - <term> | <term>
<term> ::= <term> * <factor> | <term> / <factor> | <factor>
<factor> ::= +<factor> | -<factor> | (<expr>) |
<integer> | <integer>.<integer>
<integer> ::= <integer><digit> | <digit>
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<expr> + <term>
Fuzzing mit Grammatiken
<start> ::= <expr>
<expr> ::= <expr> + <term> | <expr> - <term> | <term>
<term> ::= <term> * <factor> | <term> / <factor> | <factor>
<factor> ::= +<factor> | -<factor> | (<expr>) |
<integer> | <integer>.<integer>
<integer> ::= <integer><digit> | <digit>
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<expr> + <factor>
Fuzzing mit Grammatiken
<start> ::= <expr>
<expr> ::= <expr> + <term> | <expr> - <term> | <term>
<term> ::= <term> * <factor> | <term> / <factor> | <factor>
<factor> ::= +<factor> | -<factor> | (<expr>) |
<integer> | <integer>.<integer>
<integer> ::= <integer><digit> | <digit>
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<term> + <factor>
Fuzzing mit Grammatiken
<start> ::= <expr>
<expr> ::= <expr> + <term> | <expr> - <term> | <term>
<term> ::= <term> * <factor> | <term> / <factor> | <factor>
<factor> ::= +<factor> | -<factor> | (<expr>) |
<integer> | <integer>.<integer>
<integer> ::= <integer><digit> | <digit>
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
2 + <integer>
Fuzzing mit Grammatiken
<start> ::= <expr>
<expr> ::= <expr> + <term> | <expr> - <term> | <term>
<term> ::= <term> * <factor> | <term> / <factor> | <factor>
<factor> ::= +<factor> | -<factor> | (<expr>) |
<integer> | <integer>.<integer>
<integer> ::= <integer><digit> | <digit>
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
2 + 2
Fuzzing mit Grammatiken
JavaScript-Grammatik
If Statement
IfStatementfull ⇒
   if ParenthesizedExpression Statementfull
|  if ParenthesizedExpression StatementnoShortIf else Statementfull
IfStatementnoShortIf ⇒ if ParenthesizedExpression StatementnoShortIf else StatementnoShortIf
Switch Statement
SwitchStatement ⇒
   switch ParenthesizedExpression { }
|  switch ParenthesizedExpression { CaseGroups LastCaseGroup }
CaseGroups ⇒
   «empty»
|  CaseGroups CaseGroup
CaseGroup ⇒ CaseGuards BlockStatementsPrefix
@AndreasZeller
JavaScript

Parser
JavaScript-Fuzzing
hase III
est case into
ter, check for
and assertions
1 var haystack = "foo";
2 var re text = "^foo";
3 haystack += "x";
4 re text += "(x)";
5 var re = new RegExp(re text);
6 re. test(haystack);
7 RegExp.input = Number();
8 print(RegExp.$1);
Figure 2: Test case generated by LangFuzz, crashing the
JavaScript interpreter when executing Line 8. The static
access of RegExp is deprecated but valid. Reported asHoller, Herzig, Zeller: "Fuzzing with Code Fragments", USENIX 2012
30 Chromium + Mozilla Security Rewards

53,000 US$ als Bug-Prämien
C. Holler
Grammatiken schreiben
If Statement
IfStatementfull ⇒
   if ParenthesizedExpression Statementfull
|  if ParenthesizedExpression StatementnoShortIf else Statementfull
IfStatementnoShortIf ⇒ if ParenthesizedExpression StatementnoShortIf else StatementnoShortIf
Switch Statement
SwitchStatement ⇒
   switch ParenthesizedExpression { }
|  switch ParenthesizedExpression { CaseGroups LastCaseGroup }
CaseGroups ⇒
   «empty»
|  CaseGroups CaseGroup
CaseGroup ⇒ CaseGuards BlockStatementsPrefix
@AndreasZeller
Grammatiken lernen
• Jedes Verhalten eines Programmms kann durch dessen
Eingabe hervorgerufen werden
• Wir sehen die Eingabe als eine Folge von Zeichen
(Buchstaben, Interaktionen, Ereignisse…)
• Eine Sprache beschreibt die erlaubten Zeichenfolgen
• Wir möchten die Eingabesprache eines Programmms lernen
@AndreasZeller
http:// @user:pass www.google.com:80 path/
Grammatiken lernen
http:// @user:pass www.google.com:80 path/
Programm
@AndreasZeller
http:// @user:pass www.google.com:80 path/
Grammatiken lernen
http
:// @user:pass www.google.com:80 path/
– Protokoll
@AndreasZeller
http:// @user:pass www.google.com:80 path/
Grammatiken lernen
http
:// @user:pass
www.google.com
:80 path/
– Protokoll
– Hostname
@AndreasZeller
http:// @user:pass www.google.com:80 path/
Grammatiken lernen
http
:// @user:pass
www.google.com
:
80
path/
– Protokoll
– Hostname
– Port
@AndreasZeller
http:// @user:pass www.google.com:80 path/
Grammatiken lernen
http
:// @
user
:
pass
www.google.com
:
80
path/
– Protokoll
– Hostname
– Port
– Anmeldedaten
@AndreasZeller
http:// @user:pass www.google.com:80 path/
Grammatiken lernen
http
:// @
user
:
pass
www.google.com
:
80
path
/
– Protokoll
– Hostname
– Port
– Anmeldedaten
– Seite
@AndreasZeller
Grammatiken lernen
http
:// @
user
:
pass
www.google.com
:
80
path
/
– Protokoll
– Hostname
– Port
– Anmeldedaten
– Seite
– Trenner
http:// @user:pass www.google.com:80 path/
@AndreasZeller
Grammatiken lernen
http
:// @
user
:
pass
www.google.com
:
80
path
/
– Protokoll
– Hostname
– Port
– Anmeldedaten
– Seite
– Trenner
http:// @user:pass www.google.com:80 path/
}
werden in
unterschiedlichen
Funktionen
verarbeitet
werden in
verschiedenen
Variablen
gespeichert
@AndreasZeller
Eingaben verfolgen
Wir verfolgen Eingaben durch den Programmlauf:
1. Dynamisches Tainting versieht jedes Zeichen
der Eingabe mit einem Etikett, das mit jeder
Berechnung weitergereicht wird
2. Eingaben wiedererkennen prüft Zeichenketten
im Speicher, ob sie Teil der Eingabe sind
@AndreasZeller
Grammatiken lernen
• Wir beginnen mit der (trivialen) Grammatik

<start> ::= Eingabe
<start> ::= http://user:pass@www.google.com:80/path#ref
@AndreasZeller
Grammatiken lernen
fragment = 'ref'
url = '/path'
path = '/path'
scheme = 'http'
netloc = 'user:pass@www.google.com:80'
<start> ::= http://user:pass@www.google.com:80/path#ref
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
@AndreasZeller
<start> ::= http://<netloc>/path#ref

<netloc> ::= user:pass@www.google.com:80
Grammatiken lernen
fragment = 'ref'
url = '/path'
path = '/path'
scheme = 'http'
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
@AndreasZeller
Grammatiken lernen
fragment = 'ref'
url = '/path'
path = '/path'
<start> ::= <scheme>://<netloc>/path#ref

<netloc> ::= user:pass@www.google.com:80

<scheme> ::= http
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
@AndreasZeller
<start> ::= <scheme>://<netloc><path>#ref

<netloc> ::= user:pass@www.google.com:80

<scheme> ::= http

<path> ::= /path
fragment = 'ref'
url = '/path'
Grammatiken lernen
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
@AndreasZeller
Grammatiken lernen
url = '/path'
<start> ::= <scheme>://<netloc><path>#<fragment>

<netloc> ::= user:pass@www.google.com:80

<scheme> ::= http

<path> ::= /path
<fragment> ::= ref
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
@AndreasZeller
Grammatiken lernen
<start> ::= <scheme>://<netloc><path>#<fragment>

<netloc> ::= user:pass@www.google.com:80

<scheme> ::= http

<path> ::= <url>
<fragment> ::= ref
<url> ::= /path
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
@AndreasZeller
Demo
@AndreasZeller
AUTOGRAM
AUTOGRAM ist ein Grammatik-Lerner für Java-Programme
Durch systematische Experimente lernt AUTOGRAM
• Wiederholungen
• Optionale Teile
• Häufige Elemente (Zahlen, Bezeichner…)
Höschele, Zeller: "Mining Input Grammars from Dynamic Taints", ASE 2016
@AndreasZeller
URLs
URL ::= PROTOCOL '://' AUTHORITY PATH ['?' QUERY] ['#' REF]
AUTHORITY ::= [USERINFO '@'] HOST [':' PORT]
PROTOCOL ::= 'http' | 'ftp'
USERINFO ::= /[a-z]+:[a-z]+/
HOST ::= /[a-z.]+/
Port ::= '80'
PATH ::= //[a-z0-9./]*/
QUERY ::= 'foo=bar&lorem=ipsum'
REF ::= /[a-z]+/
http://user:password@www.google.com:80/command?foo=bar&lorem=ipsum#fragment
http://www.guardian.co.uk/sPorts/worldcup#results
ftp://bob:12345@ftp.example.com/oss/debian7.iso
@AndreasZeller
INI-Dateien
INI ::= LINE+
LINE ::= SECTION_LINE 'r'

| OPTION_LINE ['r']
SECTION_LINE ::= '[' KEY ']'
OPTION_LINE ::= KEY ' = ' VALUE
KEY ::= /[a-zA-Z]*/
VALUE ::= /[a-zA-Z0-9/]/
[Application]
Version = 0.5
WorkingDir = /tmp/mydir/
[User]
User = Bob
Password = 12345
@AndreasZeller
JSON-Daten
JSON ::= VALUE

VALUE ::= JSONOBJECT | ARRAY | STRINGVALUE |
TRUE | FALSE | NULL | NUMBER
TRUE ::= ’true’
FALSE ::= ’false’
NULL ::= ’null’
NUMBER ::= [’-’] /[0-9]+/
STRINGVALUE ::= ’"’ INTERNALSTRING ’"’
INTERNALSTRING ::= /[a-zA-Z0-9 ]+/
ARRAY ::= ’[’
[VALUE [’,’ VALUE]+]
’]’
JSONOBJECT ::= ’{’
[STRINGVALUE ’:’ VALUE
[’,’ STRINGVALUE ’:’ VALUE]

+]

'}'
{
"v": true,
"x": 25,
"y": -36,
…
}
@AndreasZeller
Lernen ohne Beispiele
Tests Grammatik
Test-Generator
für Parser
Programm
Mathis et al.: "Parser-Directed Fuzzing", PLDI 2019
@AndreasZeller
Lernen ohne Beispiele
xyzzy ✘
– prüft auf Ziffer
– prüft auf "true"/"false"
– prüft auf '"'
– prüft auf '['
– prüft auf '{'
Test-Generator Programm
@AndreasZeller
Lernen ohne Beispiele
0 ✔
Test-Generator Programm
@AndreasZeller
Lernen ohne Beispiele
– prüft auf Ziffer
– prüft auf "true"/"false"
– prüft auf '"'
– prüft auf '['
– prüft auf '{'
0 ✔
Test-Generator Programm
@AndreasZeller
Lernen ohne Beispiele
– prüft auf Ziffer
– prüft auf "true"/"false"
– prüft auf '"'
– prüft auf '['
– prüft auf '{'
0 ✔
Test-Generator Programm
@AndreasZeller
Lernen ohne Beispiele
true ✔
Test-Generator Programm
@AndreasZeller
Lernen ohne Beispiele
false ✔
Test-Generator Programm
@AndreasZeller
Lernen ohne Beispiele
– prüft auf Ziffer
– prüft auf "true"/"false"
– prüft auf '"'
– prüft auf '['
– prüft auf '{'
false ✔
Test-Generator Programm
@AndreasZeller
Lernen ohne Beispiele
– prüft auf Ziffer
– prüft auf "true"/"false"
– prüft auf '"'
– prüft auf '['
– prüft auf '{'
false ✔
Test-Generator Programm
@AndreasZeller
Lernen ohne Beispiele
" ✘
– prüft auf '"'
– prüft auf ''
– prüft auf character
Test-Generator Programm
@AndreasZeller
Lernen ohne Beispiele
"" ✔
Test-Generator Programm
@AndreasZeller
JSON lernen
JSON ::= VALUE

VALUE ::= JSONOBJECT | ARRAY | STRINGVALUE |
TRUE | FALSE | NULL | NUMBER
TRUE ::= ’true’
FALSE ::= ’false’
NULL ::= ’null’
NUMBER ::= [’-’] /[0-9]+/
STRINGVALUE ::= ’"’ INTERNALSTRING ’"’
INTERNALSTRING ::= /[a-zA-Z0-9 ]+/
ARRAY ::= ’[’
[VALUE [’,’ VALUE]+]
’]’
JSONOBJECT ::= ’{’
[STRINGVALUE ’:’ VALUE
[’,’ STRINGVALUE ’:’ VALUE]

+]

'}'
Test-Generator
@AndreasZeller
Fuzzing ohne Beispiele
PYGMALION Prototyp für Python-Programme
Program
Under Test
Parser-Directed
Test Generator
ComparisonsTests Dynamic Taints
Grammar
Learner
Test Inputs
Inputs +
Equivalence Classes
Grammar
Fuzzer
Gopinath, Mathis, Höschele, Kampmann, Zeller: "Sample-Free Learning of Input Grammars", ArXiV 2018
Perfekte Abdeckung, beispiellose Effizienz
@AndreasZeller
Fuzzing ohne Beispiele
PYGMALION Prototyp für Python-Programme
Program
Under Test
Parser-Directed
Test Generator
ComparisonsTests Dynamic Taints
Grammar
Learner
Test Inputs
Inputs +
Equivalence Classes
Grammar
Fuzzer
Gopinath, Mathis, Höschele, Kampmann, Zeller: "Sample-Free Learning of Input Grammars"
Perfekte Abdeckung, beispiellose Effizienz
@AndreasZeller
Erzeugte Tests im Vergleich
[false ,[{ "o":{ , "$dYPrlj@?BR":
397  [+ ]"S|+|4GzCW(C":-94}} ],
[false,null]]
............................
nullÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
AFL
KLEE
Pygmalion
Niedrige Abdeckung, wenige gültige Eingaben
Gute Abdeckung, aber flache Eingaben
Gute Abdeckung, tiefe Strukturen, Kontrolle
Dateiformate
@AndreasZeller
@AndreasZeller
Eine Quelle für Alles
HTML
Fuzzing: Breaking Things
with Random Inputs
A Chapter of “Generating Software Tests”
Author:
Andreas Zeller,
Rahul Gopinath,
Marcel Böhme,
Gordon Fraser, and
Christian Holler
February 20, 2019
PDF
Code
+ Folien
+ EPUB
+ LaTeX
+ Word
+ TXT …Notebook
@AndreasZeller
Beständige

Software
1. Nutze ein Repository
2. Jeder kann bauen
3. Nutze Tests
4. Sei offen für Erweiterungen
5. Nutze BeispieleNotebook
@AndreasZeller
Software-Tests automatisch erzeugen:
Frische Ansätze für Forschung, Praxis und Lehre
Andreas Zeller
CISPA Helmholtz-Zentrum für Informationssicherheit
www.fuzzingbook.org @AndreasZeller
Fuzzing

Testen mit zufälligen Eingaben
[;x1-GPZ+wcckc];,N9J+?#6^6e?]9lu2_%'4GX"0VUB[E/r
~fApu6b8<{%siq8Zh.6{V,hr?;{Ti.r3PIxMMMv6{xS^+'Hq!AxB"YXRS@!
Kd6;wtAMefFWM(`|J_<1~o}z3K(CCzRH JIIvHz>_*.>JrlU32~eGP?
lR=bF3+;y$3lodQ<B89!5"W2fK*vE7v{')KC-i,c{<[~m!]o;{.'}Gj(X}
EtYetrpbY@aGZ1{P!AZU7x#4(Rtn!q4nCwqol^y6}0|
Ko=*JK~;zMKV=9Nai:wxu{J&UV#HaU)*BiC<),`+t*gka<W=Z.
%T5WGHZpI30D<Pq>&]BS6R&j?#tP7iaV}-}`?[_[Z^LBMPG-
FKj'xwuZ1=Q`^`5,$N$Q@[!CuRzJ2D|vBy!^zkhdf3C5PAkR?V hn|
3='i2Qx]D$qs4O`1@fevnG'211Vf3piU37@55apzIyl"'f,
$ee,J4Gw:cgNKLie3nx9(`efSlg6#[K"@WjhZ}r[Scun&sBCS,T[/
vY'pduwgzDlVNy7'rnzxNwI)(ynBa>%|b`;`9fG]P_0hdG~$@6
3]KAeEnQ7lU)3Pn,0)G/6N-wyzj/MTd#A;r
@AndreasZeller
Grammatiken lernen
http
:// @
user
:
pass
www.google.com
:
80
path
/
– Protokoll
– Hostname
– Port
– Anmeldedaten
– Seite
– Trenner
http:// @user:pass www.google.com:80 path/
}
werden in
unterschiedlichen
Funktionen
verarbeitet
werden in
verschiedenen
Variablen
gespeichert
@AndreasZeller
Fuzzing ohne Beispiele
PYGMALION Prototyp für Python-Programme
Program
Under Test
Parser-Directed
Test Generator
ComparisonsTests Dynamic Taints
Grammar
Learner
Test Inputs
Inputs +
Equivalence Classes
Grammar
Fuzzer
Gopinath, Mathis, Höschele, Kampmann, Zeller: "Sample-Free Learning of Input Grammars"
Perfekte Abdeckung, beispiellose Effizienz
@AndreasZeller
Erzeugte Tests im Vergleich
[false ,[{ "o":{ , "$dYPrlj@?BR":
397  [+ ]"S|+|4GzCW(C":-94}} ],
[false,null]]
............................
nullÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
AFL
KLEE
Pygmalion
Niedrige Abdeckung, wenige gültige Eingaben
Gute Abdeckung, aber flache Eingaben
Gute Abdeckung, tiefe Strukturen, Kontrolle

Software-Tests automatisch erzeugen: Frische Ansätze für Forschung, Praxis und Lehre (Keynote TAV + SEUH 2019)

  • 1.
    @AndreasZeller Software-Tests automatisch erzeugen: FrischeAnsätze für Forschung, Praxis und Lehre Andreas Zeller CISPA Helmholtz-Zentrum für Informationssicherheit www.fuzzingbook.org
  • 2.
  • 3.
  • 4.
  • 5.
    Fuzzing
 Testen mit zufälligenEingaben [;x1-GPZ+wcckc];,N9J+?#6^6e?]9lu2_%'4GX"0VUB[E/r ~fApu6b8<{%siq8Zh.6{V,hr?;{Ti.r3PIxMMMv6{xS^+'Hq!AxB"YXRS@! Kd6;wtAMefFWM(`|J_<1~o}z3K(CCzRH JIIvHz>_*.>JrlU32~eGP? lR=bF3+;y$3lodQ<B89!5"W2fK*vE7v{')KC-i,c{<[~m!]o;{.'}Gj(X} EtYetrpbY@aGZ1{P!AZU7x#4(Rtn!q4nCwqol^y6}0| Ko=*JK~;zMKV=9Nai:wxu{J&UV#HaU)*BiC<),`+t*gka<W=Z. %T5WGHZpI30D<Pq>&]BS6R&j?#tP7iaV}-}`?[_[Z^LBMPG- FKj'xwuZ1=Q`^`5,$N$Q@[!CuRzJ2D|vBy!^zkhdf3C5PAkR?V hn| 3='i2Qx]D$qs4O`1@fevnG'211Vf3piU37@55apzIyl"'f, $ee,J4Gw:cgNKLie3nx9(`efSlg6#[K"@WjhZ}r[Scun&sBCS,T[/ vY'pduwgzDlVNy7'rnzxNwI)(ynBa>%|b`;`9fG]P_0hdG~$@6 3]KAeEnQ7lU)3Pn,0)G/6N-wyzj/MTd#A;r
  • 6.
    Fuzzing
 Testen mit zufälligenEingaben Barton P. Miller
  • 7.
    Fuzzer Fuzzing
 Zufällige Eingaben fürProgrammme UNIX- Werkzeuge “ab’d&gfdfggg” 25%–33%grep • sh • sed …
  • 8.
  • 9.
    @AndreasZeller • Annahme: Ichmöchte einen Parser testen, der komplexe Eingaben verarbeitet • Um am Parser vorbeizukommen, braucht man syntaktisch gültige Eingaben Grammatik-basiertes Fuzzing Parser
  • 10.
    LangFuzz (2012) • Fuzzerfür JavaScript und andere Sprachen • Nutzt Grammatiken, um Eingaben zu erzeugen • Nutzt die Grammatik, um existierende Eingaben zu verarbeiten
  • 11.
    <start> ::= <expr> <expr>::= <expr> + <term> | <expr> - <term> | <term> <term> ::= <term> * <factor> | <term> / <factor> | <factor> <factor> ::= +<factor> | -<factor> | (<expr>) | <integer> | <integer>.<integer> <integer> ::= <integer><digit> | <digit> <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 Eine Grammatik • Grammatik für arithmetische Ausdrücke:
 
 
 
 
 • <start> expandiert zu <expr>; <expr> zu <term>, <term> zu <expr> + <term>, usw.
  • 12.
    Fuzzing mit Grammatiken <start>::= <expr> <expr> ::= <expr> + <term> | <expr> - <term> | <term> <term> ::= <term> * <factor> | <term> / <factor> | <factor> <factor> ::= +<factor> | -<factor> | (<expr>) | <integer> | <integer>.<integer> <integer> ::= <integer><digit> | <digit> <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 <start>
  • 13.
    <start> ::= <expr> <expr>::= <expr> + <term> | <expr> - <term> | <term> <term> ::= <term> * <factor> | <term> / <factor> | <factor> <factor> ::= +<factor> | -<factor> | (<expr>) | <integer> | <integer>.<integer> <integer> ::= <integer><digit> | <digit> <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 <expr> Fuzzing mit Grammatiken
  • 14.
    <start> ::= <expr> <expr>::= <expr> + <term> | <expr> - <term> | <term> <term> ::= <term> * <factor> | <term> / <factor> | <factor> <factor> ::= +<factor> | -<factor> | (<expr>) | <integer> | <integer>.<integer> <integer> ::= <integer><digit> | <digit> <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 <expr> + <term> Fuzzing mit Grammatiken
  • 15.
    <start> ::= <expr> <expr>::= <expr> + <term> | <expr> - <term> | <term> <term> ::= <term> * <factor> | <term> / <factor> | <factor> <factor> ::= +<factor> | -<factor> | (<expr>) | <integer> | <integer>.<integer> <integer> ::= <integer><digit> | <digit> <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 <expr> + <factor> Fuzzing mit Grammatiken
  • 16.
    <start> ::= <expr> <expr>::= <expr> + <term> | <expr> - <term> | <term> <term> ::= <term> * <factor> | <term> / <factor> | <factor> <factor> ::= +<factor> | -<factor> | (<expr>) | <integer> | <integer>.<integer> <integer> ::= <integer><digit> | <digit> <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 <term> + <factor> Fuzzing mit Grammatiken
  • 17.
    <start> ::= <expr> <expr>::= <expr> + <term> | <expr> - <term> | <term> <term> ::= <term> * <factor> | <term> / <factor> | <factor> <factor> ::= +<factor> | -<factor> | (<expr>) | <integer> | <integer>.<integer> <integer> ::= <integer><digit> | <digit> <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 2 + <integer> Fuzzing mit Grammatiken
  • 18.
    <start> ::= <expr> <expr>::= <expr> + <term> | <expr> - <term> | <term> <term> ::= <term> * <factor> | <term> / <factor> | <factor> <factor> ::= +<factor> | -<factor> | (<expr>) | <integer> | <integer>.<integer> <integer> ::= <integer><digit> | <digit> <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 2 + 2 Fuzzing mit Grammatiken
  • 19.
  • 20.
    @AndreasZeller JavaScript
 Parser JavaScript-Fuzzing hase III est caseinto ter, check for and assertions 1 var haystack = "foo"; 2 var re text = "^foo"; 3 haystack += "x"; 4 re text += "(x)"; 5 var re = new RegExp(re text); 6 re. test(haystack); 7 RegExp.input = Number(); 8 print(RegExp.$1); Figure 2: Test case generated by LangFuzz, crashing the JavaScript interpreter when executing Line 8. The static access of RegExp is deprecated but valid. Reported asHoller, Herzig, Zeller: "Fuzzing with Code Fragments", USENIX 2012 30 Chromium + Mozilla Security Rewards
 53,000 US$ als Bug-Prämien C. Holler
  • 21.
    Grammatiken schreiben If Statement IfStatementfull ⇒    if ParenthesizedExpression Statementfull |  if ParenthesizedExpression StatementnoShortIf else Statementfull IfStatementnoShortIf ⇒ if ParenthesizedExpression StatementnoShortIf else StatementnoShortIf SwitchStatement SwitchStatement ⇒    switch ParenthesizedExpression { } |  switch ParenthesizedExpression { CaseGroups LastCaseGroup } CaseGroups ⇒    «empty» |  CaseGroups CaseGroup CaseGroup ⇒ CaseGuards BlockStatementsPrefix
  • 22.
    @AndreasZeller Grammatiken lernen • JedesVerhalten eines Programmms kann durch dessen Eingabe hervorgerufen werden • Wir sehen die Eingabe als eine Folge von Zeichen (Buchstaben, Interaktionen, Ereignisse…) • Eine Sprache beschreibt die erlaubten Zeichenfolgen • Wir möchten die Eingabesprache eines Programmms lernen
  • 23.
    @AndreasZeller http:// @user:pass www.google.com:80path/ Grammatiken lernen http:// @user:pass www.google.com:80 path/ Programm
  • 24.
    @AndreasZeller http:// @user:pass www.google.com:80path/ Grammatiken lernen http :// @user:pass www.google.com:80 path/ – Protokoll
  • 25.
    @AndreasZeller http:// @user:pass www.google.com:80path/ Grammatiken lernen http :// @user:pass www.google.com :80 path/ – Protokoll – Hostname
  • 26.
    @AndreasZeller http:// @user:pass www.google.com:80path/ Grammatiken lernen http :// @user:pass www.google.com : 80 path/ – Protokoll – Hostname – Port
  • 27.
    @AndreasZeller http:// @user:pass www.google.com:80path/ Grammatiken lernen http :// @ user : pass www.google.com : 80 path/ – Protokoll – Hostname – Port – Anmeldedaten
  • 28.
    @AndreasZeller http:// @user:pass www.google.com:80path/ Grammatiken lernen http :// @ user : pass www.google.com : 80 path / – Protokoll – Hostname – Port – Anmeldedaten – Seite
  • 29.
    @AndreasZeller Grammatiken lernen http :// @ user : pass www.google.com : 80 path / –Protokoll – Hostname – Port – Anmeldedaten – Seite – Trenner http:// @user:pass www.google.com:80 path/
  • 30.
    @AndreasZeller Grammatiken lernen http :// @ user : pass www.google.com : 80 path / –Protokoll – Hostname – Port – Anmeldedaten – Seite – Trenner http:// @user:pass www.google.com:80 path/ } werden in unterschiedlichen Funktionen verarbeitet werden in verschiedenen Variablen gespeichert
  • 31.
    @AndreasZeller Eingaben verfolgen Wir verfolgenEingaben durch den Programmlauf: 1. Dynamisches Tainting versieht jedes Zeichen der Eingabe mit einem Etikett, das mit jeder Berechnung weitergereicht wird 2. Eingaben wiedererkennen prüft Zeichenketten im Speicher, ob sie Teil der Eingabe sind
  • 32.
    @AndreasZeller Grammatiken lernen • Wirbeginnen mit der (trivialen) Grammatik
 <start> ::= Eingabe <start> ::= http://user:pass@www.google.com:80/path#ref
  • 33.
    @AndreasZeller Grammatiken lernen fragment ='ref' url = '/path' path = '/path' scheme = 'http' netloc = 'user:pass@www.google.com:80' <start> ::= http://user:pass@www.google.com:80/path#ref • Für jede (Variable, Wert) im Programmlauf, wobei Wert in der Eingabe auftritt: 1. Ersetze alle Auftreten von Wert durch <Variable> 2. Füge eine neue Regel <Variable> ::= Wert hinzu
  • 34.
    @AndreasZeller <start> ::= http://<netloc>/path#ref
 <netloc>::= user:pass@www.google.com:80 Grammatiken lernen fragment = 'ref' url = '/path' path = '/path' scheme = 'http' • Für jede (Variable, Wert) im Programmlauf, wobei Wert in der Eingabe auftritt: 1. Ersetze alle Auftreten von Wert durch <Variable> 2. Füge eine neue Regel <Variable> ::= Wert hinzu
  • 35.
    @AndreasZeller Grammatiken lernen fragment ='ref' url = '/path' path = '/path' <start> ::= <scheme>://<netloc>/path#ref
 <netloc> ::= user:pass@www.google.com:80
 <scheme> ::= http • Für jede (Variable, Wert) im Programmlauf, wobei Wert in der Eingabe auftritt: 1. Ersetze alle Auftreten von Wert durch <Variable> 2. Füge eine neue Regel <Variable> ::= Wert hinzu
  • 36.
    @AndreasZeller <start> ::= <scheme>://<netloc><path>#ref
 <netloc>::= user:pass@www.google.com:80
 <scheme> ::= http
 <path> ::= /path fragment = 'ref' url = '/path' Grammatiken lernen • Für jede (Variable, Wert) im Programmlauf, wobei Wert in der Eingabe auftritt: 1. Ersetze alle Auftreten von Wert durch <Variable> 2. Füge eine neue Regel <Variable> ::= Wert hinzu
  • 37.
    @AndreasZeller Grammatiken lernen url ='/path' <start> ::= <scheme>://<netloc><path>#<fragment>
 <netloc> ::= user:pass@www.google.com:80
 <scheme> ::= http
 <path> ::= /path <fragment> ::= ref • Für jede (Variable, Wert) im Programmlauf, wobei Wert in der Eingabe auftritt: 1. Ersetze alle Auftreten von Wert durch <Variable> 2. Füge eine neue Regel <Variable> ::= Wert hinzu
  • 38.
    @AndreasZeller Grammatiken lernen <start> ::=<scheme>://<netloc><path>#<fragment>
 <netloc> ::= user:pass@www.google.com:80
 <scheme> ::= http
 <path> ::= <url> <fragment> ::= ref <url> ::= /path • Für jede (Variable, Wert) im Programmlauf, wobei Wert in der Eingabe auftritt: 1. Ersetze alle Auftreten von Wert durch <Variable> 2. Füge eine neue Regel <Variable> ::= Wert hinzu
  • 39.
  • 40.
    @AndreasZeller AUTOGRAM AUTOGRAM ist einGrammatik-Lerner für Java-Programme Durch systematische Experimente lernt AUTOGRAM • Wiederholungen • Optionale Teile • Häufige Elemente (Zahlen, Bezeichner…) Höschele, Zeller: "Mining Input Grammars from Dynamic Taints", ASE 2016
  • 41.
    @AndreasZeller URLs URL ::= PROTOCOL'://' AUTHORITY PATH ['?' QUERY] ['#' REF] AUTHORITY ::= [USERINFO '@'] HOST [':' PORT] PROTOCOL ::= 'http' | 'ftp' USERINFO ::= /[a-z]+:[a-z]+/ HOST ::= /[a-z.]+/ Port ::= '80' PATH ::= //[a-z0-9./]*/ QUERY ::= 'foo=bar&lorem=ipsum' REF ::= /[a-z]+/ http://user:password@www.google.com:80/command?foo=bar&lorem=ipsum#fragment http://www.guardian.co.uk/sPorts/worldcup#results ftp://bob:12345@ftp.example.com/oss/debian7.iso
  • 42.
    @AndreasZeller INI-Dateien INI ::= LINE+ LINE::= SECTION_LINE 'r'
 | OPTION_LINE ['r'] SECTION_LINE ::= '[' KEY ']' OPTION_LINE ::= KEY ' = ' VALUE KEY ::= /[a-zA-Z]*/ VALUE ::= /[a-zA-Z0-9/]/ [Application] Version = 0.5 WorkingDir = /tmp/mydir/ [User] User = Bob Password = 12345
  • 43.
    @AndreasZeller JSON-Daten JSON ::= VALUE
 VALUE::= JSONOBJECT | ARRAY | STRINGVALUE | TRUE | FALSE | NULL | NUMBER TRUE ::= ’true’ FALSE ::= ’false’ NULL ::= ’null’ NUMBER ::= [’-’] /[0-9]+/ STRINGVALUE ::= ’"’ INTERNALSTRING ’"’ INTERNALSTRING ::= /[a-zA-Z0-9 ]+/ ARRAY ::= ’[’ [VALUE [’,’ VALUE]+] ’]’ JSONOBJECT ::= ’{’ [STRINGVALUE ’:’ VALUE [’,’ STRINGVALUE ’:’ VALUE]
 +]
 '}' { "v": true, "x": 25, "y": -36, … }
  • 44.
    @AndreasZeller Lernen ohne Beispiele TestsGrammatik Test-Generator für Parser Programm Mathis et al.: "Parser-Directed Fuzzing", PLDI 2019
  • 45.
    @AndreasZeller Lernen ohne Beispiele xyzzy✘ – prüft auf Ziffer – prüft auf "true"/"false" – prüft auf '"' – prüft auf '[' – prüft auf '{' Test-Generator Programm
  • 46.
    @AndreasZeller Lernen ohne Beispiele 0✔ Test-Generator Programm
  • 47.
    @AndreasZeller Lernen ohne Beispiele –prüft auf Ziffer – prüft auf "true"/"false" – prüft auf '"' – prüft auf '[' – prüft auf '{' 0 ✔ Test-Generator Programm
  • 48.
    @AndreasZeller Lernen ohne Beispiele –prüft auf Ziffer – prüft auf "true"/"false" – prüft auf '"' – prüft auf '[' – prüft auf '{' 0 ✔ Test-Generator Programm
  • 49.
    @AndreasZeller Lernen ohne Beispiele true✔ Test-Generator Programm
  • 50.
    @AndreasZeller Lernen ohne Beispiele false✔ Test-Generator Programm
  • 51.
    @AndreasZeller Lernen ohne Beispiele –prüft auf Ziffer – prüft auf "true"/"false" – prüft auf '"' – prüft auf '[' – prüft auf '{' false ✔ Test-Generator Programm
  • 52.
    @AndreasZeller Lernen ohne Beispiele –prüft auf Ziffer – prüft auf "true"/"false" – prüft auf '"' – prüft auf '[' – prüft auf '{' false ✔ Test-Generator Programm
  • 53.
    @AndreasZeller Lernen ohne Beispiele "✘ – prüft auf '"' – prüft auf '' – prüft auf character Test-Generator Programm
  • 54.
    @AndreasZeller Lernen ohne Beispiele ""✔ Test-Generator Programm
  • 55.
    @AndreasZeller JSON lernen JSON ::=VALUE
 VALUE ::= JSONOBJECT | ARRAY | STRINGVALUE | TRUE | FALSE | NULL | NUMBER TRUE ::= ’true’ FALSE ::= ’false’ NULL ::= ’null’ NUMBER ::= [’-’] /[0-9]+/ STRINGVALUE ::= ’"’ INTERNALSTRING ’"’ INTERNALSTRING ::= /[a-zA-Z0-9 ]+/ ARRAY ::= ’[’ [VALUE [’,’ VALUE]+] ’]’ JSONOBJECT ::= ’{’ [STRINGVALUE ’:’ VALUE [’,’ STRINGVALUE ’:’ VALUE]
 +]
 '}' Test-Generator
  • 56.
    @AndreasZeller Fuzzing ohne Beispiele PYGMALIONPrototyp für Python-Programme Program Under Test Parser-Directed Test Generator ComparisonsTests Dynamic Taints Grammar Learner Test Inputs Inputs + Equivalence Classes Grammar Fuzzer Gopinath, Mathis, Höschele, Kampmann, Zeller: "Sample-Free Learning of Input Grammars", ArXiV 2018 Perfekte Abdeckung, beispiellose Effizienz
  • 57.
    @AndreasZeller Fuzzing ohne Beispiele PYGMALIONPrototyp für Python-Programme Program Under Test Parser-Directed Test Generator ComparisonsTests Dynamic Taints Grammar Learner Test Inputs Inputs + Equivalence Classes Grammar Fuzzer Gopinath, Mathis, Höschele, Kampmann, Zeller: "Sample-Free Learning of Input Grammars" Perfekte Abdeckung, beispiellose Effizienz
  • 58.
    @AndreasZeller Erzeugte Tests imVergleich [false ,[{ "o":{ , "$dYPrlj@?BR": 397  [+ ]"S|+|4GzCW(C":-94}} ], [false,null]] ............................ nullÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ AFL KLEE Pygmalion Niedrige Abdeckung, wenige gültige Eingaben Gute Abdeckung, aber flache Eingaben Gute Abdeckung, tiefe Strukturen, Kontrolle
  • 59.
  • 60.
  • 61.
    @AndreasZeller Eine Quelle fürAlles HTML Fuzzing: Breaking Things with Random Inputs A Chapter of “Generating Software Tests” Author: Andreas Zeller, Rahul Gopinath, Marcel Böhme, Gordon Fraser, and Christian Holler February 20, 2019 PDF Code + Folien + EPUB + LaTeX + Word + TXT …Notebook
  • 62.
    @AndreasZeller Beständige
 Software 1. Nutze einRepository 2. Jeder kann bauen 3. Nutze Tests 4. Sei offen für Erweiterungen 5. Nutze BeispieleNotebook
  • 63.
    @AndreasZeller Software-Tests automatisch erzeugen: FrischeAnsätze für Forschung, Praxis und Lehre Andreas Zeller CISPA Helmholtz-Zentrum für Informationssicherheit www.fuzzingbook.org @AndreasZeller Fuzzing
 Testen mit zufälligen Eingaben [;x1-GPZ+wcckc];,N9J+?#6^6e?]9lu2_%'4GX"0VUB[E/r ~fApu6b8<{%siq8Zh.6{V,hr?;{Ti.r3PIxMMMv6{xS^+'Hq!AxB"YXRS@! Kd6;wtAMefFWM(`|J_<1~o}z3K(CCzRH JIIvHz>_*.>JrlU32~eGP? lR=bF3+;y$3lodQ<B89!5"W2fK*vE7v{')KC-i,c{<[~m!]o;{.'}Gj(X} EtYetrpbY@aGZ1{P!AZU7x#4(Rtn!q4nCwqol^y6}0| Ko=*JK~;zMKV=9Nai:wxu{J&UV#HaU)*BiC<),`+t*gka<W=Z. %T5WGHZpI30D<Pq>&]BS6R&j?#tP7iaV}-}`?[_[Z^LBMPG- FKj'xwuZ1=Q`^`5,$N$Q@[!CuRzJ2D|vBy!^zkhdf3C5PAkR?V hn| 3='i2Qx]D$qs4O`1@fevnG'211Vf3piU37@55apzIyl"'f, $ee,J4Gw:cgNKLie3nx9(`efSlg6#[K"@WjhZ}r[Scun&sBCS,T[/ vY'pduwgzDlVNy7'rnzxNwI)(ynBa>%|b`;`9fG]P_0hdG~$@6 3]KAeEnQ7lU)3Pn,0)G/6N-wyzj/MTd#A;r @AndreasZeller Grammatiken lernen http :// @ user : pass www.google.com : 80 path / – Protokoll – Hostname – Port – Anmeldedaten – Seite – Trenner http:// @user:pass www.google.com:80 path/ } werden in unterschiedlichen Funktionen verarbeitet werden in verschiedenen Variablen gespeichert @AndreasZeller Fuzzing ohne Beispiele PYGMALION Prototyp für Python-Programme Program Under Test Parser-Directed Test Generator ComparisonsTests Dynamic Taints Grammar Learner Test Inputs Inputs + Equivalence Classes Grammar Fuzzer Gopinath, Mathis, Höschele, Kampmann, Zeller: "Sample-Free Learning of Input Grammars" Perfekte Abdeckung, beispiellose Effizienz @AndreasZeller Erzeugte Tests im Vergleich [false ,[{ "o":{ , "$dYPrlj@?BR": 397  [+ ]"S|+|4GzCW(C":-94}} ], [false,null]] ............................ nullÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ AFL KLEE Pygmalion Niedrige Abdeckung, wenige gültige Eingaben Gute Abdeckung, aber flache Eingaben Gute Abdeckung, tiefe Strukturen, Kontrolle