Fuzzing

Nell'ambito della programmazione e dello sviluppo software, il fuzzing (o fuzz testing) è una tecnica automatizzata di test del software che consiste nel fornire in input a un programma dati non validi, inattesi o casuali. Il programma viene quindi monitorato per individuare anomalie quali crash, il fallimento di asserzioni interne al codice o potenziali memory leak. Tipicamente i fuzzer sono utilizzati per testare programmi che accettano input strutturati. Tale struttura è specificata, ad esempio, in un formato di file o in un protocollo, e distingue gli input validi da quelli non validi. Un fuzzer efficace genera input semi-validi, cioè "sufficientemente validi" da non essere rifiutati direttamente dal parser, ma "sufficientemente non validi" da provocare comportamenti inattesi nelle parti più profonde del programma ed esporre casi limite non gestiti correttamente.
A fini di sicurezza, gli input che attraversano un confine di fiducia (trust boundary) sono spesso i più utili.[1] Ad esempio, è più importante sottoporre a fuzzing il codice che gestisce un file caricato da un utente qualsiasi rispetto a quello che analizza un file di configurazione accessibile solo a un utente privilegiato.
Dalla diffusione, a partire dal 2013, dei fuzzer coverage-guided come AFL, il fuzzing è divenuto una delle tecniche più efficaci per la scoperta automatica di vulnerabilità ed è oggi integrato nei processi di sviluppo di grandi progetti software.[2]
Storia
[modifica | modifica wikitesto]Precursori: il test con input casuali
[modifica | modifica wikitesto]Il test di un programma con input casuali è una pratica che precede il fuzzing vero e proprio ed è nota anche come random testing, monkey testing o Monte Carlo debugging[3] (in analogia con i metodi Monte Carlo).
Nel 1981 Duran e Ntafos indagarono formalmente l'efficacia del test di un programma con input casuali.[4][5] Sebbene il random testing fosse ampiamente percepito come il peggior metodo per testare un programma, gli autori dimostrarono che si tratta di un'alternativa economicamente vantaggiosa rispetto a tecniche di test più sistematiche. Nel 1983 Steve Capps presso Apple sviluppò "The Monkey",[6] uno strumento che generava input casuali per le applicazioni del Mac OS classico, come MacPaint.[7] La "scimmia" figurativa rimanda al teorema delle scimmie infinite. Nel 1991 fu rilasciato lo strumento crashme, concepito per verificare la robustezza dei sistemi operativi Unix e Unix-like eseguendo casualmente chiamate di sistema con parametri scelti a caso.[8]
La nascita del «fuzz» (1988)
[modifica | modifica wikitesto]Il termine fuzz nasce da un progetto del 1988[9] svolto nell'ambito del corso magistrale di sistemi operativi avanzati (CS736) tenuto dal professor Barton Miller presso l'Università del Wisconsin-Madison, i cui risultati furono successivamente pubblicati nel 1990.[10][11] Sottoporre a fuzz testing una utility UNIX significava generare automaticamente input e parametri da riga di comando casuali per il programma. Il progetto era concepito per verificare l'affidabilità dei programmi a riga di comando di UNIX eseguendo un gran numero di input casuali in rapida successione fino a provocarne il crash. Il gruppo di Miller riuscì a mandare in crash dal 25 al 33 per cento delle utility testate. Successivamente effettuò il debug di ciascun crash per determinarne la causa e classificò ogni anomalia rilevata. Per consentire ad altri ricercatori di condurre esperimenti analoghi su altro software, il codice sorgente degli strumenti, le procedure di test e i dati grezzi furono resi pubblicamente disponibili.[12] Questa forma primordiale di fuzzing sarebbe oggi definita fuzzing black box, generazionale e non strutturato (dumb o "classico").
Secondo Barton Miller:
«Nel descrivere il progetto, avevo bisogno di dare un nome a questo tipo di test. Volevo un nome che evocasse la sensazione di dati casuali e non strutturati. Dopo aver provato diverse idee, mi sono fermato sul termine fuzz.[11]»
Un contributo chiave di questo lavoro pionieristico fu un oracolo di test semplice (quasi semplicistico): un programma falliva il test se andava in crash o si bloccava sotto l'input casuale, e veniva altrimenti considerato superato. Sebbene la costruzione degli oracoli di test possa risultare complessa, l'oracolo di questi primi fuzz test era semplice e universalmente applicabile.
Diffusione e industrializzazione
[modifica | modifica wikitesto]Nell'aprile 2012 Google annunciò ClusterFuzz, un'infrastruttura di fuzzing basata su cloud per i componenti critici dal punto di vista della sicurezza del browser Chromium.[13] I ricercatori di sicurezza possono caricare i propri fuzzer e ottenere bug bounty se ClusterFuzz individua un crash con il fuzzer caricato.
Nel settembre 2014 Shellshock[14] fu reso noto come una famiglia di vulnerabilità della shell Bash di UNIX, ampiamente diffusa; la maggior parte delle vulnerabilità di Shellshock fu individuata tramite il fuzzer AFL.[15] Molti servizi esposti su Internet, come alcune installazioni di server web, utilizzano Bash per elaborare determinate richieste, consentendo a un attaccante di indurre le versioni vulnerabili di Bash a eseguire comandi arbitrari.[16]
Nell'aprile 2015 Hanno Böck mostrò come il fuzzer AFL avrebbe potuto individuare la vulnerabilità Heartbleed del 2014.[17][18] Heartbleed è una grave vulnerabilità, introdotta accidentalmente in OpenSSL, che consente a un attaccante di decifrare comunicazioni altrimenti cifrate. Nel gennaio 2017 Shodan segnalava ancora circa 200.000 macchine potenzialmente vulnerabili.[19]
Nell'agosto 2016 la Defense Advanced Research Projects Agency (DARPA) tenne la finale della prima Cyber Grand Challenge, una competizione di tipo capture the flag completamente automatizzata, durata 11 ore.[20] L'obiettivo era sviluppare sistemi in grado di scoprire, sfruttare e correggere in tempo reale i difetti del software; il fuzzing fu impiegato come efficace strategia offensiva. Il sistema vincitore fu "Mayhem",[21] sviluppato dal gruppo ForAllSecure guidato da David Brumley.
Sempre nel 2016 Microsoft annunciò Project Springfield, un servizio di fuzz testing basato su cloud,[22] e Google annunciò OSS-Fuzz, che consente il fuzzing continuo di diversi progetti open source critici per la sicurezza.[23] Alla conferenza Black Hat del 2018, Christopher Domas dimostrò l'uso del fuzzing per rivelare l'esistenza di un core RISC nascosto all'interno di un processore.[24] Nel settembre 2020 Microsoft rilasciò OneFuzz, una piattaforma di fuzzing-as-a-service auto-ospitabile,[25] poi archiviata il 1º novembre 2023.[26]
Funzionamento
[modifica | modifica wikitesto]La maggior parte dei fuzzer moderni condivide un modello algoritmico comune, descritto in letteratura come un ciclo iterativo di generazione ed esecuzione di input. A partire da una configurazione iniziale, il fuzzer ripete le seguenti fasi finché non esaurisce il proprio budget di tempo o risorse: seleziona l'input o il seed successivo (scheduling), genera un nuovo caso di test, lo esegue osservando il comportamento del programma e aggiorna il proprio stato in base a ciò che ha osservato. Gli input che si rivelano interessanti, ad esempio perché aumentano la copertura del codice o provocano un fallimento, vengono conservati e riutilizzati.[2]
Preparazione e seed
[modifica | modifica wikitesto]Nella fase iniziale (preprocessing) il fuzzer viene predisposto per la campagna: il programma bersaglio può essere strumentato, e viene raccolto un insieme di input iniziali detti seed. Il corpus di seed può contenere migliaia di input potenzialmente simili; la selezione automatica dei seed (o riduzione della suite di test) consente di scegliere i seed migliori per massimizzare il numero totale di bug individuati durante una campagna di fuzzing.[27]
Scheduling
[modifica | modifica wikitesto]A ogni iterazione il fuzzer deve decidere quale input della propria collezione utilizzare come base per il caso di test successivo e quante risorse (energia) dedicargli. Una scelta oculata dello scheduling migliora sensibilmente l'efficienza: AFLFast, ad esempio, modella il fuzzing coverage-guided come una catena di Markov e assegna più energia ai seed che esercitano percorsi di programma raramente raggiunti.[28]
Generazione degli input
[modifica | modifica wikitesto]Un fuzzer mutation-based (basato sulla mutazione) sfrutta il corpus di seed esistenti, generando nuovi input modificando (o meglio, mutando) quelli forniti.[29] Ad esempio, nel fuzzing della libreria di immagini libpng, l'utente fornisce alcuni file PNG validi come seed, mentre il fuzzer li modifica per produrre varianti semi-valide. Un fuzzer generation-based (basato sulla generazione) genera invece gli input da zero, tipicamente a partire da un modello di input;[30] a differenza di quelli mutation-based, non dipende dall'esistenza o dalla qualità di un corpus di seed. Alcuni fuzzer sono in grado di fare entrambe le cose.[31]
Esecuzione e osservazione
[modifica | modifica wikitesto]Ogni input generato viene fornito al programma, di cui si osserva il comportamento. Per esporre i bug, un fuzzer deve distinguere il comportamento atteso (normale) da quello inatteso (anomalo); poiché una macchina non sempre riesce a distinguere un bug da una funzionalità, ciò è noto come problema dell'oracolo di test.[32][33] Tipicamente un fuzzer distingue tra input che provocano un crash e input che non lo provocano: i crash sono facilmente identificabili e possono indicare potenziali vulnerabilità (ad esempio denial of service o esecuzione di codice arbitrario). Tuttavia l'assenza di crash non indica l'assenza di vulnerabilità: un programma scritto in C, ad esempio, può andare in crash oppure no in presenza di un buffer overflow, poiché il suo comportamento è indefinito.
Per rendere un fuzzer più sensibile a fallimenti diversi dai crash si utilizzano dei sanitizer, che iniettano asserzioni per mandare in crash il programma quando viene rilevato un fallimento.[34][35] Esistono diversi sanitizer per diverse classi di bug:
- errori di memoria come buffer overflow e use-after-free (AddressSanitizer);
- race condition e deadlock (ThreadSanitizer);
- comportamenti indefiniti (UndefinedBehaviorSanitizer);
- memory leak (LeakSanitizer);
- violazioni dell'integrità del flusso di controllo (CFISanitizer).
Nei fuzzer coverage-guided l'esecuzione è inoltre osservata tramite strumentazione che traccia gli elementi di codice (blocchi di base o transizioni) esercitati dall'input, così da misurare l'aumento di copertura del codice. In assenza di un'implementazione di riferimento è anche possibile ricorrere al differential testing: gli stessi input vengono eseguiti su due implementazioni distinte dello stesso programma (ad esempio lighttpd e httpd, entrambi server web) e una divergenza negli output segnala un possibile bug in una delle due.[36]
Triage e minimizzazione
[modifica | modifica wikitesto]Un fuzzer produce un enorme numero di input in poco tempo: nel 2016 il progetto Google OSS-Fuzz ne generava circa 4000 miliardi alla settimana.[23] Per questo molti fuzzer includono una toolchain che automatizza le attività successive alla generazione degli input che inducono il fallimento. Il triage automatico raggruppa gli input in base alla causa radice e ne stabilisce la priorità in base alla gravità, poiché molti input distinti possono esporre lo stesso bug e solo alcuni sono critici per la sicurezza. Ad esempio, i Linux triage tools del CERT Coordination Center raggruppano i crash in base allo stack trace e ne stimano la probabilità di sfruttamento,[37] mentre lo strumento "!exploitable" di Microsoft assegna a ciascun crash una valutazione di sfruttabilità.[38] La minimizzazione automatica dell'input (o test case reduction) isola invece la porzione di input che effettivamente induce il fallimento, rimuovendo quanti più byte possibile pur continuando a riprodurre il bug: il Delta Debugging ne è un esempio, basato su un algoritmo di ricerca dicotomica esteso.[39]
Classificazione dei fuzzer
[modifica | modifica wikitesto]Un fuzzer può essere classificato secondo tre assi tra loro ortogonali:[40][2]
- generation-based o mutation-based, a seconda che gli input siano generati da zero o modificando input esistenti (vedi #Generazione degli input);
- dumb (non strutturato) o smart (strutturato), a seconda che sia consapevole o meno della struttura dell'input;
- white box, gray box o black box, a seconda che sia consapevole o meno della struttura del programma.
Consapevolezza della struttura del programma
[modifica | modifica wikitesto]Tipicamente un fuzzer è considerato più efficace se raggiunge un grado più elevato di copertura del codice: se non esercita determinati elementi strutturali del programma, non può nemmeno rivelare i bug in essi nascosti.
Un fuzzer black box[41][31] tratta il programma come una scatola nera, ignaro della sua struttura interna. Può eseguire diverse centinaia di input al secondo, è facilmente parallelizzabile e scala a programmi di dimensioni arbitrarie, ma tende a esporre soltanto bug "superficiali". Esistono tentativi di apprendere incrementalmente la struttura interna del programma osservandone l'output: LearnLib, ad esempio, impiega l'apprendimento attivo per generare un automa che rappresenta il comportamento di un'applicazione web.
Un fuzzer white box[1][31] sfrutta l'analisi del programma per aumentare sistematicamente la copertura o raggiungere posizioni critiche. SAGE,[42] ad esempio, usa l'esecuzione simbolica per esplorare sistematicamente i diversi percorsi del programma. Un fuzzer white box può esporre bug nascosti in profondità, ma il tempo dedicato all'analisi può diventare proibitivo: se impiega troppo tempo per generare un input, un fuzzer black box risulta più efficiente.[43]
Un fuzzer gray box rappresenta una via di mezzo: sfrutta la strumentazione anziché un'analisi completa del programma per ricavarne informazioni. AFL e libFuzzer, ad esempio, usano una strumentazione leggera per tracciare le transizioni tra blocchi di base esercitate da un input, con un overhead ragionevole; ciò informa il fuzzer sull'aumento di copertura, rendendo i fuzzer gray box strumenti di rilevamento delle vulnerabilità estremamente efficienti.[28]
Consapevolezza della struttura dell'input
[modifica | modifica wikitesto]I fuzzer generano input per programmi che accettano input strutturati, come file, sequenze di eventi da tastiera o mouse, o sequenze di messaggi. Ciò che costituisce un input valido può essere esplicitamente specificato in un modello di input, quali grammatiche formali, formati di file, modelli di GUI e protocolli di rete.
Un fuzzer smart (basato su modello,[31] su grammatica[30] o su protocollo[44]) sfrutta il modello di input per generare una proporzione maggiore di input validi. Se l'input è modellato mediante una grammatica formale, un fuzzer generation-based di tipo smart istanzia le regole di produzione per generare input validi rispetto alla grammatica. In genere il modello deve però essere fornito esplicitamente, cosa difficile quando è proprietario, sconosciuto o molto complesso; se è disponibile un ampio corpus di input, una tecnica di induzione grammaticale come l'algoritmo L* di Angluin è in grado di ricostruirlo.[45]
Un fuzzer dumb[41][1] non richiede un modello di input e può quindi essere applicato a una più ampia varietà di programmi. AFL, ad esempio, è un fuzzer dumb di tipo mutation-based che modifica un file seed invertendo bit casuali, sostituendo byte con valori "interessanti" e spostando o eliminando blocchi di dati. Un fuzzer dumb genera però una proporzione inferiore di input validi: un limite illustrato dal caso dei checksum, come nel controllo a ridondanza ciclica (CRC), che un fuzzer ignaro difficilmente riuscirà a generare correttamente. Esistono tuttavia tecniche per identificare e ricalcolare il checksum dopo la mutazione.[46]
Tecniche principali
[modifica | modifica wikitesto]Fuzzing coverage-guided (greybox)
[modifica | modifica wikitesto]Il fuzzing coverage-guided è il paradigma dominante dalla metà degli anni 2010. Un fuzzer di questo tipo strumenta il programma per misurare la copertura del codice raggiunta da ciascun input e conserva nel proprio corpus solo gli input che scoprono nuovo codice, usandoli poi come base per ulteriori mutazioni. Questo ciclo di retroazione evolutiva permette di raggiungere progressivamente porzioni sempre più profonde del programma partendo da pochi seed. AFL ne è il capostipite; le sue evoluzioni più diffuse sono AFL++ e libFuzzer, quest'ultimo integrato nel compilatore LLVM per il fuzzing a livello di singola funzione (in-process).[28] Framework più recenti come AFL++ e LibAFL consentono di comporre fuzzer modulari e riutilizzabili a partire da componenti standardizzati.[47]
Directed greybox fuzzing
[modifica | modifica wikitesto]Il directed greybox fuzzing orienta la campagna verso specifiche posizioni del codice (ad esempio una modifica recente, il sito di una segnalazione di bug o un punto ritenuto vulnerabile) anziché massimizzare la copertura complessiva. Il fuzzer privilegia gli input che, secondo una metrica di distanza rispetto ai bersagli, si avvicinano maggiormente a essi, concentrando le risorse dove servono. AFLGo è l'implementazione di riferimento del paradigma;[48] un altro esempio è TaintScope, indirizzato al superamento dei controlli di checksum.[46] La scelta di quali posizioni assumere come bersaglio è essa stessa oggetto di studio sistematico.[49]
Hybrid fuzzing
[modifica | modifica wikitesto]Il hybrid fuzzing combina l'efficienza dei fuzzer gray box con l'efficacia dell'analisi white box, tipicamente delegando all'esecuzione concolica il compito di superare i controlli sugli input che bloccano il fuzzer (ad esempio confronti con valori "magici" o vincoli complessi). Il fuzzer esplora rapidamente il codice ordinario e invoca l'analisi simbolica, computazionalmente costosa, solo quando i suoi progressi si arrestano. Driller è un esempio noto di questo approccio.[50]
Fuzzing del kernel e dei sistemi operativi
[modifica | modifica wikitesto]Il fuzzing dei kernel dei sistemi operativi pone sfide specifiche, come la necessità di generare sequenze valide di chiamate di sistema e di gestire lo stato condiviso del sistema. Syzkaller, sviluppato da Google, è lo strumento di riferimento per il fuzzing del kernel Linux: genera programmi di test a partire da descrizioni formali delle chiamate di sistema ed è impiegato per il testing continuo del kernel.[51]
Fuzzing di protocolli di rete
[modifica | modifica wikitesto]I programmi che implementano protocolli di rete mantengono uno stato interno e si aspettano sequenze di messaggi in un ordine preciso, il che rende poco efficace il fuzzing di singoli messaggi isolati. I fuzzer per protocolli, come AFLNet, sono stateful: modellano la macchina a stati del protocollo e utilizzano le risposte del programma come feedback per esplorarne gli stati.[52]
Fuzzing basato su snapshot
[modifica | modifica wikitesto]Per bersagli complessi o difficili da isolare, come interi sistemi operativi, macchine virtuali o firmware, si ricorre al fuzzing basato su snapshot: lo stato del sistema viene salvato in un punto preciso e ripristinato rapidamente prima di ogni esecuzione, evitando di riavviare il bersaglio a ogni test. Nyx, ad esempio, applica questa tecnica al fuzzing di hypervisor sfruttando snapshot rapidi.[53]
Applicazioni
[modifica | modifica wikitesto]Il fuzzing è utilizzato principalmente come tecnica automatizzata per esporre le vulnerabilità nei programmi critici per la sicurezza che potrebbero essere sfruttate con intento malevolo.[13][22][23] Più in generale, il fuzzing serve a dimostrare la presenza di bug, non la loro assenza: condurre una campagna per diverse settimane senza individuare bug non prova che il programma sia corretto,[54] poiché esso potrebbe ancora fallire su un input non ancora eseguito. Dimostrare la correttezza per tutti gli input richiede una specifica formale e tecniche di metodi formali. Infrastrutture di fuzzing continuo come OSS-Fuzz applicano queste tecniche su larga scala, sottoponendo automaticamente a test un gran numero di progetti open source critici per la sicurezza.[23]
Validazione dell'analisi statica
[modifica | modifica wikitesto]L'analisi statica del programma analizza un programma senza eseguirlo, e può produrre falsi positivi. Il fuzzing, in combinazione con l'analisi dinamica del programma, può essere usato per generare un input che dimostri concretamente il problema segnalato.[55]
Sicurezza dei browser
[modifica | modifica wikitesto]I moderni browser web sono sottoposti a fuzzing intensivo. Il codice di Chromium di Google Chrome è sottoposto a fuzzing continuo da parte del Chrome Security Team con 15.000 core.[56] Per Microsoft Edge Legacy e Internet Explorer, Microsoft ha effettuato test di fuzzing per 670 anni-macchina durante lo sviluppo, generando oltre 400 miliardi di manipolazioni del DOM a partire da 1 miliardo di file HTML.[56]
Valutazione
[modifica | modifica wikitesto]Confrontare l'efficacia di fuzzer diversi è un problema noto e delicato. Le due metriche più usate sono la copertura del codice raggiunta e il numero di bug distinti individuati; la copertura è più facile da misurare, ma un'alta copertura non implica necessariamente un maggior numero di bug trovati. Poiché il fuzzing è un processo intrinsecamente casuale, i risultati variano tra esecuzioni diverse: una valutazione rigorosa richiede quindi la ripetizione degli esperimenti, l'uso di test statistici e tempi di campagna sufficientemente lunghi.[57]
Per rendere i confronti riproducibili sono stati proposti dei benchmark condivisi, cioè insiemi standardizzati di programmi bersaglio con bug noti: tra i più diffusi vi sono Magma,[58] UniFuzz[59] e FuzzBench, quest'ultimo offerto da Google come servizio di benchmarking.[60]
Strumenti
[modifica | modifica wikitesto]Quello che segue è un elenco di fuzzer descritti come "popolari", "ampiamente utilizzati" o simili nella letteratura accademica.[58][59]
| Nome | White/gray/black box | Smart/dumb | Scritto in | Licenza |
|---|---|---|---|---|
| AFL | Gray | Dumb | C | Apache 2.0 |
| AFL++ | Gray | Dumb | C | Apache 2.0 |
| AFLFast | Gray | Dumb | C | Apache 2.0 |
| Angora | Gray | Dumb | C++ | Apache 2.0 |
| honggfuzz | Gray | Dumb | C | Apache 2.0 |
| QSYM | Gray | n/d | C++ | GPL |
| SymCC | White | n/d | C++ | GPL, LGPL |
| libFuzzer | Gray | Dumb | C++ | Apache 2.0 |
| AFLNet | Gray | Dumb | C | Apache 2.0 |
| Syzkaller | Gray | Smart | Go | Apache 2.0 |
| LibAFL | Gray | n/d | Rust | MIT, Apache 2.0 |
Note
[modifica | modifica wikitesto]- 1 2 3 Ari Takanen, Jared D. DeMott e Charles Miller, Fuzzing for Software Security Testing and Quality Assurance, Second Edition, Artech House, 31 gennaio 2018, p. 15, ISBN 978-1-63081-519-6.
- 1 2 3 Valentin J. M. Manès, HyungSeok Han, Choongwoo Han, Sang Kil Cha, Manuel Egele, Edward J. Schwartz e Maverick Woo, The Art, Science, and Engineering of Fuzzing: A Survey, in IEEE Transactions on Software Engineering, vol. 47, n. 11, 2021, pp. 2312-2331, DOI:10.1109/TSE.2019.2946563, arXiv:1812.00140.
- ↑ R. Charles Bell, Monte Carlo debugging: a brief tutorial, in Communications of the ACM, vol. 26, n. 2, 1º febbraio 1983, pp. 126-127, DOI:10.1145/358024.358056.
- ↑ Joe W. Duran e Simeon C. Ntafos, A report on random testing, in Proceedings of the ACM SIGSOFT International Conference on Software Engineering (ICSE'81), 9 marzo 1981, pp. 179-183, ISBN 9780897911467.
- ↑ Joe W. Duran e Simeon C. Ntafos, An Evaluation of Random Testing, in IEEE Transactions on Software Engineering, SE-10, n. 4, 1º luglio 1984, pp. 438-444, DOI:10.1109/TSE.1984.5010257.
- ↑ Andy Hertzfeld, Revolution in the Valley: The Insanely Great Story of How the Mac Was Made, O'Reilly Press, 2004, ISBN 978-0596007195.
- ↑ Macintosh Stories: Monkey Lives (TXT), su folklore.org, 22 febbraio 1999. URL consultato il 1º luglio 2026.
- ↑ crashme, su archive.codeplex.com, CodePlex. URL consultato il 1º luglio 2026.
- ↑ Barton P. Miller, Fall 1988 CS736 Project List (PDF), su pages.cs.wisc.edu, Computer Sciences Department, University of Wisconsin-Madison, settembre 1988. URL consultato il 1º luglio 2026.
- ↑ Barton P. Miller, Lars Fredriksen e Bryan So, An Empirical Study of the Reliability of UNIX Utilities, in Communications of the ACM, vol. 33, n. 11, dicembre 1990, pp. 32-44, DOI:10.1145/96267.96279.
- 1 2 Barton Miller, Foreword for Fuzz Testing Book, su pages.cs.wisc.edu, UW-Madison Computer Sciences, aprile 2008. URL consultato il 1º luglio 2026.
- ↑ Fuzz Testing of Application Reliability, su cs.wisc.edu, University of Wisconsin-Madison. URL consultato il 1º luglio 2026.
- 1 2 Announcing ClusterFuzz, su blog.chromium.org. URL consultato il 1º luglio 2026.
- ↑ Nicole Perlroth, Security Experts Expect 'Shellshock' Software Bug in Bash to Be Significant, in The New York Times, 25 settembre 2014. URL consultato il 1º luglio 2026.
- ↑ Michał Zalewski, Bash bug: the other two RCEs, or how we chipped away at the original fix (CVE-2014-6277 and '78), su lcamtuf.blogspot.com, lcamtuf's blog, 1º ottobre 2014. URL consultato il 1º luglio 2026.
- ↑ Larry Seltzer, Shellshock makes Heartbleed look insignificant, su zdnet.com, ZDNet, 29 settembre 2014. URL consultato il 1º luglio 2026.
- ↑ (DE) Hanno Böck, Fuzzing: Wie man Heartbleed hätte finden können, su golem.de. URL consultato il 1º luglio 2026.
- ↑ (EN) Hanno Böck, How Heartbleed could've been found, su blog.hboeck.de, Hanno's blog. URL consultato il 1º luglio 2026.
- ↑ Heartbleed Report (2017-01), su shodan.io. URL consultato il 1º luglio 2026 (archiviato dall'url originale il 23 gennaio 2017).
- ↑ DARPA Celebrates Cyber Grand Challenge Winners, su darpa.mil, DARPA, 5 agosto 2016. URL consultato il 1º luglio 2026.
- ↑ Mayhem Declared Preliminary Winner of Historic Cyber Grand Challenge, su darpa.mil, DARPA, 4 agosto 2016. URL consultato il 1º luglio 2026.
- 1 2 Announcing Project Springfield, su blogs.microsoft.com, 26 settembre 2016. URL consultato il 1º luglio 2026 (archiviato dall'url originale il 29 marzo 2017).
- 1 2 3 4 Announcing OSS-Fuzz, su opensource.googleblog.com. URL consultato il 1º luglio 2026.
- ↑ Christopher Domas, GOD MODE UNLOCKED - Hardware Backdoors in x86 CPUs, su github.com, agosto 2018. URL consultato il 1º luglio 2026.
- ↑ Microsoft: Windows 10 is hardened with these fuzzing security tools – now they're open source, su zdnet.com, ZDNet, 15 settembre 2020. URL consultato il 1º luglio 2026.
- ↑ microsoft/onefuzz, su github.com, Microsoft, 3 marzo 2024. URL consultato il 1º luglio 2026.
- ↑ Alexandre Rebert, Sang Kil Cha e Thanassis Avgerinos, Optimizing Seed Selection for Fuzzing, in Proceedings of the 23rd USENIX Conference on Security Symposium, 2014, pp. 861-875.
- 1 2 3 Marcel Böhme, Van-Thuan Pham e Abhik Roychoudhury, Coverage-based Greybox Fuzzing as Markov Chain, in Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security (CCS'16), 28 ottobre 2016, pp. 1032-1043, DOI:10.1145/2976749.2978428, ISBN 9781450341394.
- ↑ Jeff Offutt e Wuzhi Xu, Generating test cases for web services using data perturbation, in ACM SIGSOFT Software Engineering Notes, vol. 29, n. 5, 2004, pp. 1-10, DOI:10.1145/1022494.1022529.
- 1 2 Patrice Godefroid, Adam Kiezun e Michael Y. Levin, Grammar-based Whitebox Fuzzing (PDF), in Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI 2008), 2008.
- 1 2 3 4 Van-Thuan Pham, Marcel Böhme e Abhik Roychoudhury, Model-based whitebox fuzzing for program binaries, in Proceedings of the 31st IEEE/ACM International Conference on Automated Software Engineering (ASE'16), 7 settembre 2016, pp. 543-553, DOI:10.1145/2970276.2970316, ISBN 9781450338455.
- ↑ Elaine J. Weyuker, On Testing Non-Testable Programs, in The Computer Journal, vol. 25, n. 4, 1º novembre 1982, pp. 465-470, DOI:10.1093/comjnl/25.4.465.
- ↑ Earl T. Barr, Mark Harman, Phil McMinn, Muzammil Shahbaz e Shin Yoo, The Oracle Problem in Software Testing: A Survey, in IEEE Transactions on Software Engineering, vol. 41, n. 5, 1º maggio 2015, pp. 507-525, DOI:10.1109/TSE.2014.2372785.
- ↑ Clang compiler documentation, su clang.llvm.org. URL consultato il 1º luglio 2026.
- ↑ GNU GCC sanitizer options, su gcc.gnu.org. URL consultato il 1º luglio 2026.
- ↑ William M. McKeeman, Differential Testing for Software, in Digital Technical Journal, vol. 10, n. 1, 1998, pp. 100-107.
- ↑ CERT Triage Tools, su cert.org, CERT Division of the Software Engineering Institute (SEI), Carnegie Mellon University. URL consultato il 1º luglio 2026.
- ↑ Microsoft !exploitable Crash Analyzer, su archive.codeplex.com, CodePlex. URL consultato il 1º luglio 2026.
- ↑ Andreas Zeller e Ralf Hildebrandt, Simplifying and Isolating Failure-Inducing Input, in IEEE Transactions on Software Engineering, vol. 28, n. 2, febbraio 2002, pp. 183-200, DOI:10.1109/32.988498, ISSN 0098-5589.
- ↑ Michael Sutton, Adam Greene e Pedram Amini, Fuzzing: Brute Force Vulnerability Discovery, Addison-Wesley, 2007, ISBN 978-0-321-44611-4.
- 1 2 VDA Labs - Evolutionary Fuzzing System, su vdalabs.com. URL consultato il 1º luglio 2026 (archiviato dall'url originale il 5 novembre 2015).
- ↑ Patrice Godefroid, Michael Y. Levin e David Molnar, Automated Whitebox Fuzz Testing, in Proceedings of Network and Distributed Systems Symposium (NDSS'08), 8 febbraio 2008.
- ↑ Marcel Böhme e Soumya Paul, A Probabilistic Analysis of the Efficiency of Automated Software Testing, in IEEE Transactions on Software Engineering, vol. 42, n. 4, 5 ottobre 2015, pp. 345-360, DOI:10.1109/TSE.2015.2487274.
- ↑ Greg Banks, Marco Cova, Viktoria Felmetsger, Kevin Almeroth, Richard Kemmerer e Giovanni Vigna, SNOOZE: Toward a Stateful NetwOrk prOtocol fuzZEr, in Proceedings of the Information Security Conference (ISC'06), 2006.
- ↑ Osbert Bastani, Rahul Sharma, Alex Aiken e Percy Liang, Synthesizing Program Input Grammars, in Proceedings of the ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI 2017), giugno 2017, arXiv:1608.01723.
- 1 2 T. Wang, T. Wei, G. Gu e W. Zou, TaintScope: A Checksum-Aware Directed Fuzzing Tool for Automatic Software Vulnerability Detection, in 2010 IEEE Symposium on Security and Privacy, maggio 2010, pp. 497-512, DOI:10.1109/SP.2010.37, ISBN 978-1-4244-6894-2.
- ↑ Andrea Fioraldi, Dominik Christian Maier, Dongjia Zhang e Davide Balzarotti, LibAFL: A Framework to Build Modular and Reusable Fuzzers, in Proceedings of the 2022 ACM SIGSAC Conference on Computer and Communications Security (CCS'22), 2022, DOI:10.1145/3548606.3560602.
- ↑ Marcel Böhme, Van-Thuan Pham, Manh-Dung Nguyen e Abhik Roychoudhury, Directed Greybox Fuzzing, in Proceedings of the 2017 ACM SIGSAC Conference on Computer and Communications Security (CCS'17), 2017, pp. 2329-2344, DOI:10.1145/3133956.3134020.
- ↑ Felix Weissberg, SoK: Where to Fuzz? Assessing Target Selection Methods in Directed Fuzzing, in arXiv, 2025, arXiv:2502.08341.
- ↑ Nick Stephens, John Grosen, Christopher Salls, Andrew Dutcher, Ruoyu Wang, Jacopo Corbetta, Yan Shoshitaishvili, Christopher Kruegel e Giovanni Vigna, Driller: Augmenting Fuzzing Through Selective Symbolic Execution, in Proceedings of Network and Distributed Systems Symposium (NDSS'16), 24 febbraio 2016.
- ↑ Jiacheng Xu, A Survey of Operating System Kernel Fuzzing, in arXiv, 2025, arXiv:2501.16165.
- ↑ Van-Thuan Pham, Marcel Böhme e Abhik Roychoudhury, AFLNet: A Greybox Fuzzer for Network Protocols, in 2020 IEEE 13th International Conference on Software Testing, Validation and Verification (ICST), 2020, DOI:10.1109/ICST46399.2020.00062.
- ↑ Sergej Schumilo, Cornelius Aschermann, Ali Abbasi, Simon Wörner e Thorsten Holz, Nyx: Greybox Hypervisor Fuzzing using Fast Snapshots and Affine Types, in Proceedings of the 30th USENIX Security Symposium, 2021, pp. 2597-2614.
- ↑ Richard G. Hamlet e Ross Taylor, Partition testing does not inspire confidence, in IEEE Transactions on Software Engineering, vol. 16, n. 12, dicembre 1990, pp. 1402-1411, DOI:10.1109/32.62448.
- ↑ Domagoj Babić, Lorenzo Martignoni, Stephen McCamant e Dawn Song, Statically-directed dynamic automated test generation, in Proceedings of the 2011 International Symposium on Software Testing and Analysis, 2011, pp. 12-22, DOI:10.1145/2001420.2001423, ISBN 9781450305624.
- 1 2 Eric Sesterhenn, Berend-Jan Wever, Michele Orrù e Markus Vervier, Browser Security WhitePaper (PDF), su browser-security.x41-dsec.de, X41D SEC GmbH, 19 settembre 2017.
- ↑ Moritz Schloegel, Nils Bars e Nico Schiller, SoK: Prudent Evaluation Practices for Fuzzing, in 2024 IEEE Symposium on Security and Privacy (SP), 2024, DOI:10.1109/SP54263.2024.00137, arXiv:2405.10220.
- 1 2 Ahmad Hazimeh, Adrian Herrera e Mathias Payer, Magma: A Ground-Truth Fuzzing Benchmark, in Proceedings of the ACM on Measurement and Analysis of Computing Systems, vol. 4, n. 3, 15 giugno 2021, pp. 49:1-49:29, DOI:10.1145/3428334, arXiv:2009.01120.
- 1 2 Yuwei Li, Shouling Ji e Yuan Chen, UNIFUZZ: A Holistic and Pragmatic Metrics-Driven Platform for Evaluating Fuzzers, 2021, ISBN 978-1-939133-24-3.
- ↑ Jonathan Metzman, László Szekeres, Laurent Simon, Read Sprabery e Abhishek Arya, FuzzBench: An Open Fuzzer Benchmarking Platform and Service, in Proceedings of the 29th ACM Joint Meeting on European Software Engineering Conference and Symposium on the Foundations of Software Engineering (ESEC/FSE 2021), 2021, pp. 1393-1403, DOI:10.1145/3468264.3473932.
Bibliografia
[modifica | modifica wikitesto]- Valentin J. M. Manès, HyungSeok Han, Choongwoo Han, Sang Kil Cha, Manuel Egele, Edward J. Schwartz e Maverick Woo, The Art, Science, and Engineering of Fuzzing: A Survey, in IEEE Transactions on Software Engineering, vol. 47, n. 11, 2021, pp. 2312-2331, DOI:10.1109/TSE.2019.2946563, arXiv:1812.00140.
- Andreas Zeller, Rahul Gopinath, Marcel Böhme, Gordon Fraser e Christian Holler, The Fuzzing Book, Saarbrücken, CISPA + Saarland University, 2019.
- A. Nappa e E. Blázquez, Fuzzing Against the Machine: Automate Vulnerability Research with Emulated IoT Devices on Qemu, Packt Publishing, 2023, ISBN 9781804614976.
- Ari Takanen, Jared D. DeMott e Charles Miller, Fuzzing for Software Security Testing and Quality Assurance, 2008, ISBN 978-1-59693-214-2.
- Michael Sutton, Adam Greene e Pedram Amini, Fuzzing: Brute Force Vulnerability Discovery, 2007, ISBN 0-321-44611-9.
Voci correlate
[modifica | modifica wikitesto]Collegamenti esterni
[modifica | modifica wikitesto]- (EN) University of Wisconsin Fuzz Testing, su cs.wisc.edu.
- (EN) The Fuzzing Project, su fuzzing-project.org.
- (EN) The Fuzzing Book, su fuzzingbook.org.