Come dovrei compilare il programma per il test fuzz?

7

Sto facendo alcuni test fuzz di un programma per il quale ho un codice sorgente. Dovrei compilare il programma con qualche particolare opzione del compilatore, per rendere più efficace il test fuzz? In tal caso, qual è l'elenco corretto dei flag da riga di comando da passare al compilatore, per rendere il test fuzz il più efficace possibile?

Dovrei provare ad abilitare esplicitamente i cookie stack (gcc -fstack-protector)? Controllo della lunghezza per i buffer allocati nello stack (gcc -D_FORTIFY_SOURCE = 2)? Malloc / controllo gratuito (env MALLOC_CHECK_ = 2)? L'allocatore di debugging di Glib (G_SLICE = debug-blocks)?

Consiglieresti di utilizzare Mudflap (ad esempio, gcc -fmudflap -fmudflapir + MUDFLAP_OPTIONS = '- modo -check -viol-abort -check-initializations -ignore-reads ')?

Sono particolarmente interessato alle risposte per gcc su Linux, ma sentiti libero di rispondere anche per altre piattaforme.

    
posta D.W. 08.09.2011 - 23:50
fonte

3 risposte

4

Se un'applicazione sta andando in crash da un test, l'opzione del compilatore non la salverà. Se si compila l'applicazione con gcc -D_FORTIFY_SOURCE=2 -O2 , il processo verrà eliminato più spesso a causa di infrazioni di memoria minori che normalmente non causano il blocco del processo. Un buon esempio di questo è che avrai una maggiore capacità di rilevare overflow di heap adiacenti.

GCC Mudflap è uno strumento di debug più avanzato per cercare Puntatori Dangling, Double Frees, Buffer Overflow e potenzialmente altra memoria vulnerabilità della corruzione. Questa opzione del compilatore GCC rende l'applicazione molto lenta, quindi non è pensata per la produzione. Tuttavia registra tutte le violazioni della memoria, anche violazioni che non causano l'arresto anomalo dell'applicazione. Ti fornisce informazioni dettagliate per limitare il tipo di violazione della memoria con cui stai lavorando.

tuttavia è un pollo o un uovo. Dopo aver trovato uno di questi difetti dovrai quindi sconfiggere questo sistema di sicurezza che non è un compito di piccole dimensioni (o qualcuno che non utilizza questa misura di sicurezza). Non sarai in grado di trovare un semplice attacco "Smashing the stack for fun and profit". Le tecniche moderne includono concatenamento delle vulnerabilità di corruzione della memoria e l'uso di ROP Chains per sconfiggere ASLR.

    
risposta data 10.09.2011 - 18:44
fonte
5

Nessuno ha suggerito una risposta definitiva, quindi ho eseguito un piccolo esperimento. Sulla base di questo esperimento, ecco la mia raccomandazione fino ad ora:

Raccomandazione. Durante la procedura di fuzzing, potresti prendere in considerazione l'impostazione delle variabili di ambiente LIBC_FATAL_STDERR_=1 MALLOC_CHECK_=3 . Questa impostazione non ha avuto alcun impatto misurabile sulle prestazioni nel mio esperimento e, in base ai miei risultati, questa impostazione potrebbe aumentare leggermente il numero di bug rilevati.

Nessuna delle altre impostazioni ha apportato alcuna differenza rilevabile nel mio esperimento.

Facoltativo. Se lo desideri, puoi compilare con -fstack-protector o -fstack-protector-all , con -O2 -D_FORTIFY_SOURCE=2 e / o con mudflap; ed è possibile eseguire con la variabile di ambiente G_SLICE=debug-blocks . Nessuno di loro ha avuto alcun impatto misurabile sulle prestazioni nel mio esperimento. Tuttavia, nessuno di loro ha avuto alcun impatto sul set di bug trovati. Quindi, mentre nel mio esperimento non c'era alcun costo, non c'era alcun vantaggio.

Metodologia e dettagli sperimentali. In ogni esecuzione, ho confuso ffmpeg con zzuf , utilizzando un file seme, per 5000 iterazioni. C'era una corsa per impostazione di flag del compilatore / variabili di ambiente. Ho assicurato che fuzzing avrebbe generato esattamente lo stesso insieme di file variant in ogni esecuzione, quindi l'unica differenza erano le variabili del compilatore / variabili di ambiente. Per misurare l'impatto sulle prestazioni, ho misurato il tempo CPU + del sistema per completare la fuzzing. Per misurare l'impatto sulla capacità di rilevare i bug, ho registrato quali file di varianti hanno attivato un arresto rilevabile.

Ho misurato le prestazioni, ma nessuna delle opzioni ha avuto alcun effetto rilevabile sulle prestazioni (le differenze erano < 1% in tutti i casi e probabilmente a causa di rumore casuale).

Per potere di rilevamento bug, I MALLOC_CHECK_=3 ha dato un leggero vantaggio, ma nessuno degli altri flag o impostazioni ha fatto alcuna differenza nella potenza di rilevamento bug:

  • MALLOC_CHECK_=3 ha avuto un'influenza su quali file di varianti hanno causato un arresto anomalo. Senza bandiere, 22 delle 5000 iterazioni hanno causato un crash. Altre 2 iterazioni hanno causato un messaggio di avvertimento ( *** glibc detected *** ...) che, se si sapeva di cercarlo, poteva essere usato per rilevare un bug, quindi se si è stati abbastanza intelligenti da rendere grep i log di fuzzing per quel messaggio, 24 di le 5000 iterazioni fornirebbero segni di un bug - mentre se non si conosce il grep dei log per quel particolare messaggio di avviso, solo 22 delle 5000 iterazioni hanno fornito indicazioni di un bug. Al contrario, quando ho attivato MALLOC_CHECK_=3 , 25 delle iterazioni 5000 hanno causato un arresto anomalo e non è stato necessario eseguire il comando grep dei registri. Pertanto, MALLOC_CHECK_=3 è leggermente più efficace a scoprire i segni di un bug, e riduce anche la necessità di postelaborare i tuoi log di fuzzing in modo speciale.

    È interessante notare che c'è stato un file variante che ha arrestato il programma senza le impostazioni ma non ha bloccato il programma con MALLOC_CHECK_=3 , confermando l'ipotesi di @ this.josh che il controllo aggiuntivo in alcuni casi potrebbe farci perdere alcuni bug - ma allo stesso tempo, c'erano 2 file di varianti che non bloccavano il programma senza impostazioni, ma questo ha fatto crashare il programma con MALLOC_CHECK_=3 . Pertanto, i benefici di MALLOC_CHECK_=3 hanno superato i suoi costi.

  • Oltre a MALLOC_CHECK_ , nessuna delle altre impostazioni ha avuto alcuna influenza su quale file di varianti ha provocato un arresto anomalo rilevabile. L'insieme di file di varianti che causavano il crash del programma di base (nessun flag speciale) era esattamente come l'insieme di file di varianti che causavano il crash del programma quando compilato con flag speciali. Pertanto, almeno in questo esperimento, quelle altre impostazioni non ci sono costate nulla (in termini di prestazioni), ma non ci hanno procurato nulla (in termini di capacità di rilevamento bug).

Il mio esperimento è tutt'altro che autorevole. Per fare ciò, è necessario provarlo con molti programmi diversi (non solo uno) e più file seme diversi (non uno solo). Quindi ti avverto di non trarre troppe conclusioni da questo piccolo esperimento. Ma pensavo che i risultati fossero comunque interessanti.

    
risposta data 13.09.2011 - 09:42
fonte
4

Che domanda interessante. Ho capito che è solo unix, ma se non lo è, la prima cosa che consiglierei è testarla in entrambi gli ambienti. Windows ha un ottimo set di strumenti per eseguire il debugging dell'heap, la gestione pericolosa delle API e così via - google App Verifier se sei interessato.

Ma in generale, direi che dovresti almeno provare una versione di rilascio, con le stesse impostazioni di ottimizzazione che prevedi di utilizzare in produzione. Vuoi avere una configurazione nel test in cui non viene salvato dai controlli di debug avanzati come verificatore di app o roba malloc_check. Dopotutto, l'autore dell'attacco prenderà di mira il tuo codice ottimizzato di rilascio della versione.

Potresti provare anche qualche altro compilatore linux e sfocare questi risultati.

Oltre a ciò, sono interessato a sentire le risposte a questo come sei. : -)

    
risposta data 09.09.2011 - 03:59
fonte

Leggi altre domande sui tag