Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
FUZZING
• Fuzzing
• Symbolic execution
• Static analysis
• Dynamic analysis
• Program verification
Di queste, il fuzzing è la tecnica che ha la maggiore accuratezza, allo stesso tempo è la più
scalabile e quella più facile da impiegare.
Breve storia del fuzzing
Il fuzzing, detto anche software fuzzing o fuzz testing, è una tecnica di bug finding inventata nel
1989 da Barton Paul Miller, professore dell’università del Wisconsin-Madison, che venne da lui
impiegata per testare l’affidabilità di diverse utilities del sistema operativo Unix.
Da allora, il fuzzing si è evoluto in varie forme, e molti fuzz testers sono stati inventati, che
combinano il fuzzing con le altre tecniche prima menzionate, e più recentemente anche con
tecniche di machine learning.
Cos’è il fuzzing
Il fuzzing è una tecnica di bug finding che consiste nell’inviare una massiccia quantità di dati di
input generati randomicamente, detti testcases, ad un programma target. I testcases possono
prendere la forma di file o anche messaggi di protocollo, a seconda del tipo di applicazione
testata.
Il fuzzing è una delle tecniche più promettenti per scoprire vulnerabilità, e nonostante i suoi
svantaggi e limiti, resta molto utilizzato, soprattutto nel mondo dell’industria. La qualità del fuzz
testing, tuttavia, dipende molto dalla qualità del pool dei testcases.
Nel primo caso, è necessario conoscere la struttura del formato di file o dei messaggi di
protocollo. Tale conoscenza può essere acquisita mediante documenti di specifica o attraverso
gli RFC di riferimento, ma questo non è sempre possibile, specie nel caso di formati di file e
protocolli proprietari. I testcases vengono generati sulla base di un file di configurazione, che
funge da template.
Nel secondo caso, è necessario un pool di file iniziali. I testcases sono generati dalla mutazione
dei file iniziali. Due problemi chiave di questi fuzzer sono dove fare la mutazione e quali valori
utilizzare.
White box vs Grey box vs Black box
I white box fuzzers necessitano della disponibilità del codice sorgente. L’analisi del codice
sorgente permette di ottenere una comprensione più profonda dell’applicazione e di conseguenza
generare dei testcases migliori, che permettano una migliore copertura del codice.
I black box fuzzers, invece, fanno fuzz testing senza alcuna conoscenza del funzionamento
interno del programma target.
Il primo tipo di fuzzers genera dei testcases che ci permettono di percorrere certi path del
programma, in questo senso è appunto diretto verso uno specifico path.
Il secondo tipo di fuzzers genera testcases in modo tale da coprire quanto più codice sorgente
possibile.
Il primo tipo permette un fuzz testing più rapido, mentre dal secondo tipo ci si aspetta una maggiore
copertura del codice sorgente. Un problema chiave di entrambi i tipi di fuzzers è come estrarre le
informazioni sui path eseguiti.
Smart vs dumb
Gli smart fuzzers correggono la generazione dei testcases in base alle informazioni raccolte su
come i testcases influenzano il comportamento del programma. Per i fuzzers di tipo mutation
based, il feedback ricevuto potrebbe servire a capire quale parte del file mutare e come mutarla.
I dumb fuzzers permettono una migliore velocità di testing, mentre gli smart fuzzers generano
testacases migliori e permettono una maggiore efficacia del processo.
Vantaggi e svantaggi del fuzzing
2. Svantaggi: potrebbe essere necessaria la conoscenza del formato di file o del protocollo, che
potrebbero essere proprietari, inoltre gli input che generano un comportamento incorretto
potrebbero costituire una frazione molto piccola dell’insieme dei possibili input, per cui la
probabilità di accedere a certe parti di codice potrebbe essere molto bassa
Fuzzing mutation based e generation based a confronto
Nel caso dei fuzzers mutation based, capire dove e come mutare è fondamentale. Infatti, solo le
mutazioni in poche posizioni chiave del file potrebbero influenzare il flusso di controllo del
programma. Inoltre, un altro problema è determinare il valore che potrebbe dirigere il test verso
parti interessanti del programma.
In breve, una mutazione «cieca» potrebbe portare ad uno spreco di risorse computazionali e di
tempo, per cui una migliore strategia di mutazione accrescerebbe l’efficienza del processo.
Bassa copertura del codice
Una più alta copertura del codice sorgente si risolve in una copertura più alta degli stati di
esecuzione del programma, il che garantisce una maggiore probabilità di scoprire bug.
Molti testcases coprono gli stessi pochi path, mentre molto del codice non viene raggiunto.
I fuzzers coverage based tentano di risolvere il problema mediante tecniche di analisi del
programma, come l’instrumentazione del binario.
Passare la validazione dell’input
Spesso i programmi validano l’input, per controllare che sia conforme alle specifiche di
protocollo o di formato di file. Questo serve a risparmiare computazione e a proteggersi da input
malevoli e malformati.
I testcases generati dai black box fuzzers potrebbero non superare la validazione, il che
abbasserebbe l’efficienza del software fuzzing.
File format fuzzing
Molte applicazioni fanno della gestione dei file la loro attività principale, il fuzzing è usato
pesantemente per scoprire vulnerabilità in questo genere di applicazioni.
Un importante sottocampo di ricerca del fuzzing è il fuzzing dei browser, dato che i browser
permettono di gestire, oltre a tipi di file tradizionali come HTML, CSS e JavaScript, anche file
PDF, XML, SVG, solo per citarne alcuni.
Kernel fuzzing
Qui si verifica il problema di come raccogliere le informazioni sui crash, dato che un crash a livello
di kernel butta giù l’intero sistema.
Altro problema è come far interagire il fuzzer con il kernel, problema risolvibile attraverso l’uso
delle syscalls, qua però nasce la questione di come ordinare le chiamate di sistema, inoltre i valori
dei parametri delle chiamate dovrebbe essere random ma al tempo stesso ben formati secondo le
specifiche.
Inoltre è difficile instrumentare kernel closed source come quelli di Windows e Mac OS.
Fuzzing di protocolli
Molte applicazioni locali vengono trasformate in servizi di rete, e le applicazioni client comunicano
col server attraverso un protocollo.
Problemi di sicurezza nei protocolli possono portare a information leakage e denial of service, tra le
altre cose.
È però possibile che non siano disponibili gli RFC di riferimento per quanto riguarda un certo
protocollo, o che siano difficile da seguire.
Dati su questa metrica possono essere ottenuti attraverso una varietà di strumenti di profilazione
come gcov o lcov.
Ci sono vari tipi di code coverage, tra cui il line coverage (quante linee di codice sono state
eseguite) e il branch coverage (quanti salti condizionali sono stati eseguiti).
Benefici del code coverage
Consente di rispondere a queste domande: