Off by one overflow

Reading time: 5 minutes

tip

Impara e pratica l'Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica l'Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Supporta HackTricks

Basic Information

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 il House of Einherjar.
  • Se si utilizza Tcache, questo può essere sfruttato in una situazione di double free.
Off-by-null
c
// From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/
int main(void)
{
char buffer[40]="";
void *chunk1;
chunk1 = malloc(24);
puts("Get Input");
gets(buffer);
if(strlen(buffer)==24)
{
strcpy(chunk1,buffer);
}
return 0;
}

Tra i vari controlli, ora ogni volta che un chunk è libero, la dimensione precedente viene confrontata con la dimensione configurata nel chunk dei metadati, rendendo questo attacco piuttosto complesso dalla versione 2.28.

Esempio di codice:

Obiettivo

  • 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

Requisiti

  • Off by one overflow per modificare le informazioni sulla dimensione dei metadati

Attacco generale off-by-one

  • 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)

Attacco off-by-null

  • 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 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 (b1 ora), 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:

https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks

Altri Esempi & Riferimenti

  • https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
  • Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022
  • 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.
  • Asis CTF 2016 b00ks
  • È possibile abusare di un off by one per rivelare un indirizzo dall'heap perché il byte 0x00 alla 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 viene 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.
  • plaidctf 2015 plaiddb
  • Esiste 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 difensivo (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 ]

- Poi abusando di chunk3 (0x1f8) l'off-by-one nullo viene abusato scrivendo il prev_size a `0x4e0`.
- Nota come le dimensioni dei chunk inizialmente allocati 1, 2, 5 e 3 più le intestazioni di 4 di quei chunk siano uguali a `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Poi, il chunk 4 viene liberato, generando un chunk che consuma tutti i chunk fino all'inizio:
- ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ]

[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ]