cargo-fuzz - Fuzzing di Rust con libFuzzer Cheatsheet
cargo-fuzz è il modo standard per fare fuzzing del codice Rust. Connette libFuzzer con un workflow nativo di Cargo: scrivi un target di fuzz come una funzione Rust ordinaria che accetta byte arbitrari, esegui cargo fuzz run, e il fuzzing guidato da copertura ricerca panic, overflow aritmetici e — nel codice unsafe — veri errori di memoria. Rust sicuro previene corruzione della memoria, ma non previene panic, loop infiniti o bug di logica, e qualsiasi blocco unsafe o dipendenza C reintroduce l”intera classe di problemi di memoria.
Installazione
| Passo | Comando |
|---|
| Installa | cargo install cargo-fuzz |
| Nightly richiesto | rustup install nightly (libFuzzer ha bisogno di nightly) |
| Inizializza | cargo fuzz init (nel tuo crate) |
| Verifica | cargo fuzz --version |
Creazione di Un Target di Fuzz
cargo fuzz init # crea directory fuzz/
cargo fuzz add parse_input # crea un nuovo target
// fuzz/fuzz_targets/parse_input.rs
#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: &[u8]| {
if let Ok(s) = std::str::from_utf8(data) {
let _ = my_crate::parse(s); // panic qui diventano risultati
}
});
Esecuzione
| Comando | Descrizione |
|---|
cargo fuzz run parse_input | Fuzz il target |
cargo fuzz run parse_input -- -max_total_time=300 | Esegui per 5 minuti |
cargo fuzz run parse_input -j 8 | 8 job paralleli |
cargo fuzz list | Elenca i target |
cargo fuzz build | Costruisci senza eseguire |
I byte grezzi sprecano tempo su input che il tuo parser rifiuta immediatamente. Il crate arbitrary costruisce valori tipizzati:
use arbitrary::Arbitrary;
#[derive(Arbitrary, Debug)]
struct Config { name: String, retries: u8, enabled: bool }
fuzz_target!(|cfg: Config| {
let _ = my_crate::apply_config(cfg);
});
| Beneficio | Perché |
|---|
| Input di forma valida | Raggiunge logica più profonda |
| Target tipizzati | Fuzz API, non solo parser |
Output di Debug | Reproducer leggibili |
Sanitizer
| Sanitizer | Flag |
|---|
| AddressSanitizer (predefinito) | -s address |
| LeakSanitizer | incluso con ASan |
| MemorySanitizer | -s memory |
| ThreadSanitizer | -s thread |
| Nessuno (più veloce) | -s none |
# Fuzz il codice FFI unsafe con ASan
cargo fuzz run ffi_target -s address
Corpus e Copertura
| Comando | Scopo |
|---|
fuzz/corpus/<target>/ | Dove gli input interessanti si accumulano |
cargo fuzz cmin <target> | Minimizza il corpus |
cargo fuzz tmin <target> <input> | Minimizza un input che crasha |
cargo fuzz coverage <target> | Genera dati di copertura |
| Seed corpus | Aggiungi esempi validi per fare bootstrap |
Seminare il corpus con input veri e validi è il modo singolo più efficace per rendere il fuzzing produttivo velocemente.
Riproduzione di Crash
# I crash finiscono in fuzz/artifacts/<target>/
cargo fuzz run parse_input fuzz/artifacts/parse_input/crash-abc123
# Riduci al minimo a un caso minimo
cargo fuzz tmin parse_input fuzz/artifacts/parse_input/crash-abc123
Converti l”input minimizzato in un #[test] regolare in modo che il bug rimanga corretto.
Cosa Fare il Fuzz in Rust
| Buon target | Perché |
|---|
| Parser / deserializzatori | Input non affidabile, stato complesso |
Blocchi unsafe | Sicurezza della memoria realmente a rischio |
| Confini FFI | Codice C dietro l”interfaccia |
| Protocollo/state machine | Bug di ordinamento |
| Compressione / codifica | Territorio di bug classico |
| Meno utile | Perché |
|---|
| Aritmetica pura sicura | I panic sono solitamente ovvi |
| Thin wrapper | Poca logica da esplorare |
cargo-fuzz vs Altri Fuzzer
| Aspetto | cargo-fuzz | AFL++ (afl.rs) | LibAFL | honggfuzz-rs |
|---|
| Engine | libFuzzer | AFL++ | Custom | honggfuzz |
| Setup | Più facile per Rust | Moderato | Costruisci il tuo | Facile |
| Input strutturato | arbitrary | arbitrary | Tipi custom | arbitrary |
| Migliore per | Fuzzing Rust standard | Modalità persistente/binaria | Target insoliti | Feedback hardware |
Per target non-Rust vedi AFL++ o honggfuzz; per fuzzer custom vedi LibAFL.
Risorse