Off by one overflow
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Avere accesso a un overflow di 1B consente a un attaccante di modificare il campo size
del chunk successivo. Questo consente di manomettere quali chunk sono effettivamente liberati, generando potenzialmente un chunk che contiene un altro chunk legittimo. L'exploitation è simile a double free o chunk sovrapposti.
Ci sono 2 tipi di vulnerabilità off by one:
Byte arbitrario: Questo tipo consente di sovrascrivere quel byte con qualsiasi valore
Byte nullo (off-by-null): Questo tipo consente di sovrascrivere quel byte solo con 0x00
Un esempio comune di questa vulnerabilità può essere visto nel seguente codice dove il comportamento di strlen
e strcpy
è incoerente, il che consente di impostare un byte 0x00 all'inizio del chunk successivo.
Questo può essere sfruttato con la House of Einherjar.
Se si utilizza Tcache, questo può essere sfruttato in una situazione di double free.
Tra i vari controlli, ora ogni volta che un chunk viene liberato, la dimensione precedente viene confrontata con la dimensione configurata nei metadati del chunk, rendendo questo attacco piuttosto complesso dalla versione 2.28.
Questo attacco non funziona più a causa dell'uso di Tcaches.
Inoltre, se provi ad abusarne utilizzando chunk più grandi (quindi i tcaches non sono coinvolti), riceverai l'errore: malloc(): invalid next size (unsorted)
Far sì che un chunk sia contenuto all'interno di un altro chunk in modo che l'accesso in scrittura su quel secondo chunk consenta di sovrascrivere quello contenuto
Off by one overflow per modificare le informazioni sulla dimensione dei metadati
Allocare tre chunk A
, B
e C
(diciamo dimensioni 0x20), e un altro per prevenire la consolidazione con il top-chunk.
Liberare C
(inserito nella lista libera Tcache da 0x20).
Usare il chunk A
per sovrascrivere B
. Abusare dell'off-by-one per modificare il campo size
di B
da 0x21 a 0x41.
Ora abbiamo B
che contiene il chunk libero C
Liberare B
e allocare un chunk da 0x40 (verrà posizionato qui di nuovo)
Possiamo modificare il puntatore fd
di C
, che è ancora libero (avvelenamento Tcache)
3 chunk di memoria (a, b, c) vengono riservati uno dopo l'altro. Poi il chunk centrale viene liberato. Il primo contiene una vulnerabilità di overflow off by one e l'attaccante ne abusa con un 0x00 (se il byte precedente era 0x10 farebbe sì che il chunk centrale indichi che è 0x10 più piccolo di quanto non sia realmente).
Poi, vengono allocati altri 2 chunk più piccoli nel chunk liberato centrale (b), tuttavia, poiché b + b->size
non aggiorna mai il chunk c perché l'indirizzo puntato è più piccolo di quanto dovrebbe.
Poi, b1 e c vengono liberati. Poiché c - c->prev_size
punta ancora a b (ora b1), entrambi vengono consolidati in un chunk. Tuttavia, b2 è ancora all'interno tra b1 e c.
Infine, viene eseguita una nuova malloc reclamando quest'area di memoria che conterrà effettivamente b2, consentendo al proprietario della nuova malloc di controllare il contenuto di b2.
Questa immagine spiega perfettamente l'attacco:
Off-by-one a causa di strlen
che considera il campo size
del chunk successivo.
Tcache è in uso, quindi un attacco generale off-by-one funziona per ottenere una scrittura arbitraria con avvelenamento Tcache.
È possibile abusare di un off by one per rivelare un indirizzo dall'heap perché il byte 0x00 della fine di una stringa viene sovrascritto dal campo successivo.
La scrittura arbitraria è ottenuta abusando della scrittura off by one per far puntare il puntatore a un altro luogo dove verrà costruita una struttura falsa con puntatori falsi. Poi, è possibile seguire il puntatore di questa struttura per ottenere una scrittura arbitraria.
L'indirizzo libc è rivelato perché se l'heap viene esteso utilizzando mmap, la memoria allocata da mmap ha un offset fisso rispetto a libc.
Infine, la scrittura arbitraria viene abusata per scrivere nell'indirizzo di __free_hook con un one gadget.
C'è una vulnerabilità off by one NULL nella funzione getline
che legge le righe di input dell'utente. Questa funzione viene utilizzata per leggere la "chiave" del contenuto e non il contenuto.
Nella scrittura vengono creati 5 chunk iniziali:
chunk1 (0x200)
chunk2 (0x50)
chunk5 (0x68)
chunk3 (0x1f8)
chunk4 (0xf0)
chunk defense (0x400) per evitare la consolidazione con il top chunk
Poi i chunk 1, 5 e 3 vengono liberati, quindi:
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]