Zum Inhalt springen

cargo-fuzz - Fuzzing Rust mit libFuzzer Cheatsheet

cargo-fuzz - Fuzzing Rust mit libFuzzer Cheatsheet

cargo-fuzz ist die Standard-Weise, Rust-Code zu fuzzen. Sie verdrahtet libFuzzer mit einem Cargo-nativen Workflow: schreibe ein Fuzz-Ziel als gewöhnliche Rust-Funktion, die willkürliche Bytes nimmt, führe cargo fuzz run aus, und Coverage-gesteuertes Fuzzing jagt nach Panics, Arithmetik-Überläufen und — in unsafe-Code — echter Speicherfehler. Safe Rust verhindert Memory-Korruption, aber es verhindert nicht Panics, Endlosschleifen oder Logik-Bugs, und jeder unsafe-Block oder C-Abhängigkeit reintroduziert die vollständige Klasse von Speicherproblemen.

Installation

SchrittBefehl
Installierencargo install cargo-fuzz
Nightly erforderlichrustup install nightly (libFuzzer braucht Nightly)
Initialisierencargo fuzz init (in deiner Crate)
Überprüfungcargo fuzz --version

Erstelle ein Fuzz-Ziel

cargo fuzz init                 # erstellt fuzz/ Verzeichnis
cargo fuzz add parse_input      # erstellt ein neues Ziel
// 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);   // Panics hier werden Befunde
    }
});

Ausführung

BefehlBeschreibung
cargo fuzz run parse_inputFuzz das Ziel
cargo fuzz run parse_input -- -max_total_time=300Laufe 5 Minuten
cargo fuzz run parse_input -j 88 parallele Jobs
cargo fuzz listListe Ziele auf
cargo fuzz buildBauen ohne zu laufen

Strukturierter Input mit Arbitrary

Raw-Bytes verschwenden Zeit mit Inputs, die dein Parser sofort ablehnt. Die arbitrary-Crate baut stattdessen getypte Werte:

use arbitrary::Arbitrary;

#[derive(Arbitrary, Debug)]
struct Config { name: String, retries: u8, enabled: bool }

fuzz_target!(|cfg: Config| {
    let _ = my_crate::apply_config(cfg);
});
VorteilWarum
Gültig-geformte InputsErreicht tiefere Logik
Getypte ZieleFuzz APIs, nicht nur Parser
Debug OutputLesbare Reproducer

Sanitizer

SanitizerFlag
AddressSanitizer (Standard)-s address
LeakSanitizerInklusive ASan
MemorySanitizer-s memory
ThreadSanitizer-s thread
Keine (Schneller)-s none
# Fuzz Unsafe-FFI-Code mit ASan
cargo fuzz run ffi_target -s address

Corpus und Coverage

BefehlZweck
fuzz/corpus/<target>/Wo interessante Inputs sich ansammeln
cargo fuzz cmin <target>Minimiere den Corpus
cargo fuzz tmin <target> <input>Minimiere einen Crashing-Input
cargo fuzz coverage <target>Generiere Coverage-Daten
Seed CorpusFüge gültige Beispiele zum Bootstrappen hinzu

Das Säen des Corpus mit echten, gültigen Inputs ist die einzelne wirksamste Weise, Fuzzing schnell produktiv zu machen.

Crashes reproduzieren

# Crashes landen in fuzz/artifacts/<target>/
cargo fuzz run parse_input fuzz/artifacts/parse_input/crash-abc123

# Schrumpfe es zu einem minimalen Fall
cargo fuzz tmin parse_input fuzz/artifacts/parse_input/crash-abc123

Konvertiere den minimierten Input zu einem gewöhnlichen #[test], sodass der Bug behoben bleibt.

Was zu fuzzen in Rust

Gutes ZielWarum
Parser / DeserializerNicht vertrauenswürdiger Input, komplexer Zustand
unsafe BlöckeSpeichersicherheit tatsächlich im Risiko
FFI-GrenzenC-Code hinter der Schnittstelle
Protokoll/State-MachinesReihenfolge-Bugs
Komprimierung / EncodingKlassisches Bug-Gebiet
Weniger nützlichWarum
Reine Safe-ArithmetikPanics sind normalerweise offensichtlich
Dünne WrapperWenig Logik zum Erkunden

cargo-fuzz vs andere Fuzzer

Aspektcargo-fuzzAFL++ (afl.rs)LibAFLhonggfuzz-rs
EnginelibFuzzerAFL++Customhonggfuzz
SetupEinfachste für RustModeratBaue dein eigenesEinfach
Strukturierter InputarbitraryarbitraryCustom Typenarbitrary
Bestes fürStandard Rust FuzzingPersistent/Binary-ModiUngewöhnliche ZieleHardware-Rückmeldung

Für Non-Rust-Ziele siehe AFL++ oder honggfuzz; für benutzerdefinierte Fuzzer siehe LibAFL.

Ressourcen