
Framework di analisi statica che identifica bersagli di funzioni fuzzabili in codice sorgente e binari, genera modelli di harness e si integra con AFL++ e libFuzzer per la scoperta automatizzata di vulnerabilità.
Framework per l'automazione della scoperta di target fuzzabili con l'analisi statica

I ricercatori di vulnerabilità che conducono valutazioni della sicurezza del software spesso sfruttano le capacità del fuzzing guidato dalla copertura attraverso strumenti potenti come AFL++ e libFuzzer. Ciò è importante poiché automatizza il processo di caccia ai bug e rivela rapidamente condizioni sfruttabili nei target. Tuttavia, quando si incontrano codebase grandi e complesse o binari closed-source, i ricercatori devono dedicare tempo notevole per revisionare manualmente e fare reverse engineering per identificare funzioni in cui l'esplorazione basata sul fuzzing può essere utile.
Fuzzable è un framework che si integra sia con codice sorgente C/C++ che con binari per assistere i ricercatori di vulnerabilità nell'identificare funzioni target che sono valide per il fuzzing. Ciò viene fatto applicando diverse euristiche basate sull'analisi statica per individuare comportamenti rischiosi nel software e le funzioni che li eseguono. I ricercatori possono quindi utilizzare il framework per generare modelli di harness di base, che possono poi essere usati per cacciare vulnerabilità, o essere integrati come parte di una pipeline di fuzzing continuo, come il progetto oss-fuzz di Google.
Oltre a funzionare come strumento autonomo, Fuzzable è anche integrato come plugin per il disassemblatore Binary Ninja, con supporto per altri backend di disassemblaggio in fase di sviluppo.
Consulta il post originale del blog che descrive lo strumento qui, che evidenzia le specifiche tecniche delle euristiche di analisi statica e come è nato questo strumento. Questo strumento è anche presentato al Black Hat Arsenal USA 2022.
Alcuni target binari potrebbero richiedere una certa sanificazione (ad esempio, corrispondenza delle firme o identificazione delle funzioni da inlining), e quindi fuzzable utilizza principalmente Binary Ninja come backend di disassemblaggio per la sua capacità di risolvere efficacemente questi problemi. Pertanto, può essere utilizzato sia come strumento autonomo che come plugin.
Poiché Binary Ninja non è accessibile a tutti e potrebbe esserci una richiesta di utilizzo per valutazioni di sicurezza e potenzialmente di scalare nel cloud, è supportato anche un backend fallback angr. Prevedo di incorporare anche altri disassemblatori in futuro (priorità: Ghidra).
Se possiedi Binary Ninja Commercial, assicurati di installare l'API per l'uso headless standalone:
$ python3 /Applications/Binary\ Ninja.app/Contents/Resources/scripts/install_api.py
Installa con pip:
$ pip install fuzzable
Usiamo poetry per la gestione delle dipendenze e il build. Per fare un build manuale, clona il repository con i moduli di terze parti:
$ git clone --recursive https://github.com/ex0dus-0x/fuzzable
Per installare manualmente:
$ cd fuzzable/
# without poetry
$ pip install .
# with poetry
$ poetry install
# with poetry for a development virtualenv
$ poetry shell
Ora puoi analizzare binari e/o codice sorgente con lo strumento!
# analyzing a single shared object library binary
$ fuzzable analyze examples/binaries/libbasic.so
# analyzing a single C source file
$ fuzzable analyze examples/source/libbasic.c
# analyzing a workspace with multiple C/C++ files and headers
$ fuzzable analyze examples/source/source_bundle/
fuzzable può essere facilmente installato tramite il marketplace dei plugin di Binary Ninja andando su Binary Ninja > Gestisci Plugin e cercandolo. Ecco un esempio del plugin fuzzable in esecuzione, che identifica con precisione i target per il fuzzing e ulteriori valutazioni di vulnerabilità:

fuzzable viene fornito con varie opzioni per aiutarti a ottimizzare l'analisi. Altre saranno supportate in piani futuri e in base a eventuali richieste di funzionalità.
Per determinare la fuzzabilità, fuzzable utilizza diverse euristiche per determinare quali target sono i più validi per l'analisi dinamica. Queste euristiche vengono tutte ponderate in modo diverso utilizzando la libreria scikit-criteria, che utilizza l'analisi decisionale multi-criterio per determinare i migliori candidati. Queste metriche e i loro pesi possono essere visti qui:
Come detto, consulta il post tecnico del blog per un approfondimento su perché e come vengono utilizzate queste metriche.
Molte metriche sono state ampiamente ispirate dal lavoro originale di Vincenzo Iozzo nel fuzzing a conoscenza zero.
Ogni target che vuoi analizzare è diverso, e fuzzable non sarà in grado di tenere conto di ogni comportamento borderline nel programma target. Pertanto, durante l'analisi potrebbe essere importante regolare questi pesi in modo appropriato per vedere se risultati diversi hanno più senso per il tuo caso d'uso. Per regolare questi pesi nella CLI, specifica semplicemente l'argomento --score-weights:
$ fuzzable analyze <TARGET> --score-weights=0.2,0.2,0.2,0.2,0.2
Per impostazione predefinita, fuzzable filtrerà i target di funzione in base ai seguenti criteri:
static e non sono esposte attraverso gli header.Per vedere le chiamate filtrate da fuzzable, imposta il flag --list_ignored:
$ fuzzable analyze --list-ignored <TARGET>
In Binary Ninja, puoi attivare questa impostazione in Impostazioni > Fuzzable > Elenca chiamate ignorate.
Nel caso in cui fuzzable filtri erroneamente chiamate importanti che dovrebbero essere analizzate, si consiglia di utilizzare gli argomenti --include-* per includerle durante l'esecuzione:
# include ALL non top-level calls that were filtered out
$ fuzzable analyze --include-nontop <TARGET>
# include specific symbols that were filtered out
$ fuzzable analyze --include-sym <SYM> <TARGET>
In Binary Ninja, questo è supportato tramite Impostazioni > Fuzzable > Includi chiamate non di primo livello e Simboli da escludere.
Ora che hai trovato i tuoi candidati ideali per il fuzzing, fuzzable ti aiuterà anche a generare harness di fuzzing (quasi) pronti per essere strumentati e compilati per l'uso con un fuzzer basato su file (es. AFL++, Honggfuzz) o un fuzzer in memoria (libFuzzer). Per farlo nella CLI:
# generate harness from a candidate
$ fuzzable create-harness target --symbol-name=some_unsafe_call
# make minimal and necessary modifications to the harness
$ vim target_some_unsafe_call_harness.cpp
# example compilation for AFL-QEMU, which is specified in the comments of the generated harness
$ clang target_some_unsafe_call_harness.cpp -no-pie -o target_some_unsafe_call_harness -ldl
# create your base seeds, ideally should be more well-formed for input
$ mkdir in/
$ echo "seed" >> in/seed
# start black box fuzzing
$ afl-fuzz -Q -m none -i in/ -o out/ -- ./target_some_unsafe_call_harness
Se questo target è un codebase sorgente, verrà utilizzato il modello sorgente generico. Se il target è un binario, verrà utilizzato il modello generico black-box, che idealmente può essere usato con una modalità di emulazione di fuzzing come AFL-QEMU. Verrà anche creata una copia del binario come oggetto condiviso se il simbolo non è esportato direttamente per essere dlopenato utilizzando LIEF.
Al momento, questa funzionalità è piuttosto rudimentale, in quanto creerà semplicemente un harness C++ standalone popolato con i parametri appropriati, e non genererà automaticamente il codice necessario per i comportamenti runtime (ad esempio, istanziare e liberare strutture). Tuttavia, i modelli creati per fuzzable dovrebbero comunque farti partire rapidamente. Ecco alcune funzionalità ambiziose che vorrei implementare in futuro:
fuzzable supporta la generazione di report in vari formati. Quelli attualmente supportati sono JSON, CSV e Markdown. Ciò può essere utile se lo usi come parte dell'automazione dove vorresti ingerire l'output in un formato serializzabile. Nella CLI, passa semplicemente l'argomento --export con un nome file con l'estensione appropriata:
$ fuzzable analyze --export=report.json <TARGET>
In Binary Ninja, vai su Plugin > Fuzzable > Esporta report di fuzzabilità > ... e seleziona il formato in cui vuoi esportare e il percorso in cui vuoi scriverlo.
Questo strumento sarà sviluppato continuamente, e qualsiasi aiuto da parte di manutentori esterni è apprezzato!
Fuzzable è concesso in licenza sotto la Licenza MIT.
| Euristiche | Descrizione | Peso |
|---|
| Fuzz Friendly Name | Il nome del simbolo implica un comportamento che assume input da file/buffer | 0.3 |
| Risky Sinks | Argomenti che fluiscono in chiamate rischiose (es. memcpy) | 0.3 |
| Natural Loops | Numero di cicli rilevati con la frontiera di dominanza | 0.05 |
| Cyclomatic Complexity | Complessità della funzione target basata su archi + nodi | 0.05 |
| Coverage Depth | Numero di callee che il target attraversa | 0.3 |