Capire un overflow del buffer basato su stack reale

1

durante la lettura di come e cosa è l'overflow del buffer nella pagina owasp Ho visto la documentazione su un buffer overflow in LibPNG

Ha affermato che il seguente codice è vulnerabile:

if (!(png_ptr->mode & PNG_HAVE_PLTE)) {
    /* Should be an error, but we can cope with it */
    png_warning(png_ptr, "Missing PLTE before tRNS");
}
else if (length > (png_uint_32)png_ptr->num_palette) {
    png_warning(png_ptr, "Incorrect tRNS chunk length");
    png_crc_finish(png_ptr, length);
    return;
}
...
png_crc_read(png_ptr, readbuf, (png_size_t)length);

Ho difficoltà a capire perché è vulnerabile.

    
posta Fumerian Gaming 20.02.2017 - 18:45
fonte

2 risposte

2

Dall'articolo wiki che hai collegato:

The code appears to safely perform bounds checking because it checks the size of the variable length, which it later uses to control the amount of data copied by png_crc_read(). However, immediately before it tests length, the code performs a check on png_ptr->mode, and if this check fails a warning is issued and processing continues. Because length is tested in an else if block, length would not be tested if the first check fails, and is used blindly in the call to png_crc_read(), potentially allowing a stack buffer overflow.

Il codice sembra controllare se la lunghezza è più breve del buffer. Ma il controllo della lunghezza viene eseguito in un blocco else if . Quando png_ptr->mode & PNG_HAVE_PLTE è false, viene registrato un avviso e l'esecuzione del programma continua senza eseguire il ramo else e quindi senza controllare length > (png_uint_32)png_ptr->num_palette . Ciò significa che in qualsiasi situazione in cui viene generato l'avviso "Manca PLTE prima di tRNS", la lunghezza viene passata a png_crc_read senza essere mai verificata.

Una spiegazione plausibile su come questo bug possa essere stato introdotto è che "PLTE mancante prima di tRNS" era una condizione di errore che interrompeva l'intera funzione. In quel caso non c'era motivo di preoccuparsi di cosa sarebbe accaduto in seguito. Ma qualche tempo dopo qualcuno lo ridusse a una condizione di avviso senza verificare cosa significasse per ogni codice successivo.

Modifica: Un'altra possibilità di un buffer overflow nel codice sopra potrebbe essere se il valore di png_ptr->num_palette proviene da una fonte non attendibile. Ma l'esempio non menziona da dove proviene, quindi dubito che questo sia ciò che questo esempio vuole illustrare.

    
risposta data 20.02.2017 - 19:33
fonte
1

Risponderò con i commenti nell'esempio.

Se per qualche ragione il primo if valuta essere TRUE , tutto ciò che accade è un avviso registrato.

if (!(png_ptr->mode & PNG_HAVE_PLTE)) {
    png_warning(png_ptr, "Missing PLTE before tRNS");
}

Tuttavia, se valuta TRUE , il seguente controllo di lunghezza non verrà mai eseguito perché il blocco else-if è stato risolto.

else if (length > (png_uint_32)png_ptr->num_palette) {
    png_warning(png_ptr, "Incorrect tRNS chunk length");
    png_crc_finish(png_ptr, length);
    return;
}

Ora, quando viene chiamato png_crc_read , è possibile che non sia mai stato effettuato alcun controllo della lunghezza.

...
png_crc_read(png_ptr, readbuf, (png_size_t)length);

Questa è una vulnerabilità se la modalità può essere controllata dall'attaccante per forzare il percorso del codice a saltare il controllo della lunghezza. L'autore dell'attacco può quindi fornire una lunghezza maggiore di quella che dovrebbe essere possibile, causando un overflow del buffer. A seconda di dove si verifica questo overflow, potrebbe essere o meno sfruttabile.

    
risposta data 20.02.2017 - 19:42
fonte

Leggi altre domande sui tag