Salta ai contenuti

cargo-fuzz - Fuzzing di Rust con libFuzzer

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

PassoComando
Installacargo install cargo-fuzz
Nightly richiestorustup install nightly (libFuzzer ha bisogno di nightly)
Inizializzacargo fuzz init (nel tuo crate)
Verificacargo 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

ComandoDescrizione
cargo fuzz run parse_inputFuzz il target
cargo fuzz run parse_input -- -max_total_time=300Esegui per 5 minuti
cargo fuzz run parse_input -j 88 job paralleli
cargo fuzz listElenca i target
cargo fuzz buildCostruisci senza eseguire

Input Strutturato con Arbitrary

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);
});
BeneficioPerché
Input di forma validaRaggiunge logica più profonda
Target tipizzatiFuzz API, non solo parser
Output di DebugReproducer leggibili

Sanitizer

SanitizerFlag
AddressSanitizer (predefinito)-s address
LeakSanitizerincluso 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

ComandoScopo
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 corpusAggiungi 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 targetPerché
Parser / deserializzatoriInput non affidabile, stato complesso
Blocchi unsafeSicurezza della memoria realmente a rischio
Confini FFICodice C dietro l”interfaccia
Protocollo/state machineBug di ordinamento
Compressione / codificaTerritorio di bug classico
Meno utilePerché
Aritmetica pura sicuraI panic sono solitamente ovvi
Thin wrapperPoca logica da esplorare

cargo-fuzz vs Altri Fuzzer

Aspettocargo-fuzzAFL++ (afl.rs)LibAFLhonggfuzz-rs
EnginelibFuzzerAFL++Customhonggfuzz
SetupPiù facile per RustModeratoCostruisci il tuoFacile
Input strutturatoarbitraryarbitraryTipi customarbitrary
Migliore perFuzzing Rust standardModalità persistente/binariaTarget insolitiFeedback hardware

Per target non-Rust vedi AFL++ o honggfuzz; per fuzzer custom vedi LibAFL.

Risorse