Pular para o conteúdo

cargo-fuzz - Cheatsheet de Fuzzing de Rust com libFuzzer

cargo-fuzz - Cheatsheet de Fuzzing de Rust com libFuzzer

cargo-fuzz é a forma padrão de fuzz em código Rust. Ele fia libFuzzer com um fluxo de trabalho nativo de Cargo: escreva um alvo de fuzz como uma função Rust ordinária levando bytes arbitrários, execute cargo fuzz run, e fuzzing guiado por cobertura caça por panics, overflows aritméticos e — em código unsafe — erros de memória genuínos. Rust seguro previne corrupção de memória, mas não previne panics, loops infinitos ou bugs de lógica, e qualquer bloco unsafe ou dependência C reintroduz a classe inteira de problemas de memória.

Instalação

PassoComando
Instalacargo install cargo-fuzz
Nightly necessáriorustup install nightly (libFuzzer precisa nightly)
Inicializacargo fuzz init (no seu crate)
Verificarcargo fuzz --version

Criando um Alvo de Fuzz

cargo fuzz init                 # cria diretório fuzz/
cargo fuzz add parse_input      # cria um novo alvo
// 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 aqui se tornam descobertas
    }
});

Executando

ComandoDescrição
cargo fuzz run parse_inputFuzz o alvo
cargo fuzz run parse_input -- -max_total_time=300Executa por 5 minutos
cargo fuzz run parse_input -j 88 jobs paralelos
cargo fuzz listLista alvos
cargo fuzz buildConstrua sem executar

Input Estruturado com Arbitrary

Raw bytes desperdiçam tempo em inputs seu parser rejeita imediatamente. O crate arbitrary constrói valores digitados em vez disso:

use arbitrary::Arbitrary;

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

fuzz_target!(|cfg: Config| {
    let _ = my_crate::apply_config(cfg);
});
BenefícioPor quê
Inputs de forma válidaAlcança lógica mais profunda
Alvos digitadosFuzz APIs, não apenas parsers
Saída DebugReprodutores legíveis

Sanitizers

SanitizerFlag
AddressSanitizer (padrão)-s address
LeakSanitizerincluído com ASan
MemorySanitizer-s memory
ThreadSanitizer-s thread
Nenhum (mais rápido)-s none
# Fuzz código unsafe FFI com ASan
cargo fuzz run ffi_target -s address

Corpus e Cobertura

ComandoPropósito
fuzz/corpus/<target>/Onde inputs interessantes acumulam
cargo fuzz cmin <target>Minimiza o corpus
cargo fuzz tmin <target> <input>Minimiza um input travando
cargo fuzz coverage <target>Gera dados de cobertura
Seed corpusAdicione exemplos válidos para bootstrap

Semear o corpus com inputs reais e válidos é a forma única mais eficaz para tornar fuzzing produtivo rapidamente.

Reproduzindo Crashes

# Crashes caem em fuzz/artifacts/<target>/
cargo fuzz run parse_input fuzz/artifacts/parse_input/crash-abc123

# Encolha para um caso mínimo
cargo fuzz tmin parse_input fuzz/artifacts/parse_input/crash-abc123

Converta o input minimizado em um #[test] regular para que o bug permanece corrigido.

O que Fuzz em Rust

Bom alvoPor quê
Parsers / deserializadoresInput não confiável, estado complexo
Blocos unsafeSegurança de memória realmente em risco
Limites FFICódigo C atrás da interface
Protocolo/máquinas de estadoBugs de ordenação
Compressão / codificaçãoTerritório de bug clássico
Menos útilPor quê
Aritmética pura seguraPanics geralmente são óbvios
Thin wrappersPouca lógica para explorar

cargo-fuzz vs Outros Fuzzers

Aspectocargo-fuzzAFL++ (afl.rs)LibAFLhonggfuzz-rs
EnginelibFuzzerAFL++Customhonggfuzz
SetupMais fácil para RustModeradoConstrua o seuFácil
Input estruturadoarbitraryarbitraryTipos customizadosarbitrary
Melhor paraFuzzing Rust padrãoModos persistente/binaryAlvos incomunsFeedback de hardware

Para alvos não-Rust veja AFL++ ou honggfuzz; para fuzzers customizados veja LibAFL.

Recursos