Off by one overflow

Reading time: 5 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Podržite HackTricks

Basic Information

Imati pristup 1B overflow-u omogućava napadaču da izmeni size polje sledećeg dela. Ovo omogućava manipulaciju kojim delovima su zapravo oslobođeni, potencijalno generišući deo koji sadrži još jedan legitiman deo. Eksploatacija je slična double free ili preklapanju delova.

Postoje 2 tipa off by one ranjivosti:

  • Arbitrary byte: Ova vrsta omogućava prepisivanje tog bajta bilo kojom vrednošću
  • Null byte (off-by-null): Ova vrsta omogućava prepisivanje tog bajta samo sa 0x00
  • Uobičajen primer ove ranjivosti može se videti u sledećem kodu gde je ponašanje strlen i strcpy nekonzistentno, što omogućava postavljanje 0x00 bajta na početak sledećeg dela.
  • Ovo se može iskoristiti sa House of Einherjar.
  • Ako se koristi Tcache, ovo se može iskoristiti za situaciju 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;
}

Među ostalim proverama, sada kada je deo slobodan, prethodna veličina se upoređuje sa veličinom konfigurisanim u metapodacima, što ovu napad čini prilično složenim od verzije 2.28.

Primer koda:

Cilj

  • Napraviti deo koji je sadržan unutar drugog dela tako da pisanje pristupa preko tog drugog dela omogućava prepisivanje sadržanog dela

Zahtevi

  • Off by one overflow za modifikaciju informacija o veličini metapodataka

Opšti off-by-one napad

  • Alocirati tri dela A, B i C (recimo veličine 0x20), i još jedan da se spreči konsolidacija sa top-chunk.
  • Osloboditi C (ubacen u 0x20 Tcache slobodnu listu).
  • Koristiti deo A da preplavi B. Zloupotrebiti off-by-one da modifikujete polje size B sa 0x21 na 0x41.
  • Sada imamo B koji sadrži slobodan deo C
  • Osloboditi B i alocirati 0x40 deo (ponovo će biti postavljen ovde)
  • Možemo modifikovati fd pokazivač iz C, koji je još uvek slobodan (Tcache trovanje)

Off-by-null napad

  • 3 dela memorije (a, b, c) su rezervisana jedan za drugim. Zatim je srednji deo oslobođen. Prvi deo sadrži off by one overflow ranjivost i napadač je zloupotrebljava sa 0x00 (ako je prethodni bajt bio 0x10, to bi učinilo da srednji deo pokazuje da je 0x10 manji nego što zapravo jeste).
  • Zatim, 2 manja dela su alocirana u oslobođenom delu (b), međutim, pošto b + b->size nikada ne ažurira deo c jer je pokazana adresa manja nego što bi trebala.
  • Zatim, b1 i c se oslobađaju. Pošto c - c->prev_size još uvek pokazuje na b (sada b1), oba se konsoliduju u jedan deo. Međutim, b2 je još uvek unutra između b1 i c.
  • Na kraju, izvršava se nova malloc koja preuzima ovo područje memorije koje će zapravo sadržati b2, omogućavajući vlasniku nove malloc da kontroliše sadržaj b2.

Ova slika savršeno objašnjava napad:

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

Ostali primeri i reference

  • https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
  • Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022
  • Off-by-one zbog strlen koji uzima u obzir polje size sledećeg dela.
  • Tcache se koristi, tako da opšti off-by-one napadi funkcionišu da dobiju proizvoljnu write primitivu sa Tcache trovanjem.
  • Asis CTF 2016 b00ks
  • Moguće je zloupotrebiti off by one da se otkrije adresa iz heap-a jer bajt 0x00 na kraju stringa bude prepisan sledećim poljem.
  • Proizvoljno pisanje se dobija zloupotrebom off by one pisanja da se pokazivač usmeri na drugo mesto gde će biti izgrađena lažna struktura sa lažnim pokazivačima. Zatim, moguće je pratiti pokazivač ove strukture da bi se dobilo proizvoljno pisanje.
  • libc adresa se otkriva jer ako se heap proširi koristeći mmap, memorija alocirana od mmap ima fiksni offset od libc.
  • Na kraju, proizvoljno pisanje se zloupotrebljava da se piše u adresu __free_hook sa jednim gadgetom.
  • plaidctf 2015 plaiddb
  • Postoji NULL off by one ranjivost u funkciji getline koja čita linije korisničkog unosa. Ova funkcija se koristi za čitanje "ključa" sadržaja, a ne samog sadržaja.
  • U pisanju se kreira 5 inicijalnih delova:
  • chunk1 (0x200)
  • chunk2 (0x50)
  • chunk5 (0x68)
  • chunk3 (0x1f8)
  • chunk4 (0xf0)
  • chunk odbrane (0x400) da se izbegne konsolidacija sa top chunk
  • Zatim se oslobađaju chunk 1, 5 i 3, tako da:

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

- Zatim zloupotrebljavajući chunk3 (0x1f8) null off-by-one se zloupotrebljava pišući prev_size na `0x4e0`.
- Obratite pažnju na to kako veličine inicijalno alociranih chunk1, 2, 5 i 3 plus zaglavlja 4 od tih chunkova jednako je `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Zatim, chunk 4 se oslobađa, generišući chunk koji konzumira sve delove do početka:
- ```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 ]