Off by one overflow

Reading time: 5 minutes

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Unterstützen Sie HackTricks

Grundinformationen

Der Zugriff auf einen 1B-Overflow ermöglicht es einem Angreifer, das size-Feld des nächsten Chunks zu ändern. Dies ermöglicht es, zu manipulieren, welche Chunks tatsächlich freigegeben werden, was potenziell einen Chunk erzeugt, der einen anderen legitimen Chunk enthält. Die Ausnutzung ist ähnlich wie bei double free oder überlappenden Chunks.

Es gibt 2 Arten von Off-by-One-Sicherheitsanfälligkeiten:

  • Arbiträres Byte: Diese Art ermöglicht es, dieses Byte mit einem beliebigen Wert zu überschreiben.
  • Null-Byte (off-by-null): Diese Art ermöglicht es, dieses Byte nur mit 0x00 zu überschreiben.
  • Ein häufiges Beispiel für diese Sicherheitsanfälligkeit ist im folgenden Code zu sehen, wo das Verhalten von strlen und strcpy inkonsistent ist, was es ermöglicht, ein 0x00-Byte am Anfang des nächsten Chunks zu setzen.
  • Dies kann mit dem House of Einherjar ausgenutzt werden.
  • Wenn Tcache verwendet wird, kann dies zu einer double free-Situation ausgenutzt werden.
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;
}

Unter anderen Überprüfungen wird jetzt jedes Mal, wenn ein Chunk freigegeben wird, die vorherige Größe mit der in den Metadaten des Chunks konfigurierten Größe verglichen, was diesen Angriff ab Version 2.28 ziemlich komplex macht.

Codebeispiel:

Ziel

  • Einen Chunk in einen anderen Chunk einzufügen, sodass der Schreibzugriff auf diesen zweiten Chunk es ermöglicht, den enthaltenen zu überschreiben.

Anforderungen

  • Off-by-one-Overflow, um die Größenmetadateninformationen zu ändern.

Allgemeiner Off-by-One-Angriff

  • Drei Chunks A, B und C (sagen wir Größen 0x20) zuweisen und einen weiteren, um die Konsolidierung mit dem Top-Chunk zu verhindern.
  • C freigeben (in die 0x20 Tcache-Freiliste eingefügt).
  • Chunk A verwenden, um auf B zu überlaufen. Off-by-one ausnutzen, um das size-Feld von B von 0x21 auf 0x41 zu ändern.
  • Jetzt haben wir B, das den freien Chunk C enthält.
  • B freigeben und einen 0x40 Chunk zuweisen (er wird hier wieder platziert).
  • Wir können den fd-Zeiger von C ändern, der immer noch frei ist (Tcache-Vergiftung).

Off-by-Null-Angriff

  • 3 Chunks Speicher (a, b, c) werden nacheinander reserviert. Dann wird der mittlere freigegeben. Der erste enthält eine Off-by-One-Overflow-Schwachstelle, und der Angreifer nutzt dies mit einem 0x00 aus (wenn das vorherige Byte 0x10 war, würde es den mittleren Chunk anzeigen, dass er 0x10 kleiner ist, als er tatsächlich ist).
  • Dann werden 2 weitere kleinere Chunks im freigegebenen Chunk (b) zugewiesen, jedoch wird b + b->size den Chunk c nie aktualisieren, da die angegebene Adresse kleiner ist, als sie sein sollte.
  • Dann werden b1 und c freigegeben. Da c - c->prev_size immer noch auf b (jetzt b1) zeigt, werden beide in einem Chunk konsolidiert. b2 befindet sich jedoch immer noch zwischen b1 und c.
  • Schließlich wird ein neues malloc durchgeführt, das diesen Speicherbereich zurückgewinnt, der tatsächlich b2 enthalten wird, wodurch der Besitzer des neuen malloc den Inhalt von b2 kontrollieren kann.

Dieses Bild erklärt den Angriff perfekt:

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

Weitere Beispiele & Referenzen

  • https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks
  • Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022
  • Off-by-one aufgrund von strlen, das das size-Feld des nächsten Chunks berücksichtigt.
  • Tcache wird verwendet, sodass ein allgemeiner Off-by-One-Angriff funktioniert, um eine beliebige Schreibprimitive mit Tcache-Vergiftung zu erhalten.
  • Asis CTF 2016 b00ks
  • Es ist möglich, einen Off-by-One auszunutzen, um eine Adresse aus dem Heap zu leaken, da das Byte 0x00 am Ende eines Strings durch das nächste Feld überschrieben wird.
  • Beliebiger Schreibzugriff wird erlangt, indem der Off-by-One-Schreibzugriff ausgenutzt wird, um den Zeiger auf einen anderen Ort zu zeigen, an dem eine gefälschte Struktur mit gefälschten Zeigern erstellt wird. Dann ist es möglich, dem Zeiger dieser Struktur zu folgen, um beliebigen Schreibzugriff zu erhalten.
  • Die libc-Adresse wird geleakt, da, wenn der Heap mit mmap erweitert wird, der durch mmap zugewiesene Speicher einen festen Offset von libc hat.
  • Schließlich wird der beliebige Schreibzugriff ausgenutzt, um in die Adresse von __free_hook mit einem One-Gadget zu schreiben.
  • plaidctf 2015 plaiddb
  • Es gibt eine NULL Off-by-One-Schwachstelle in der Funktion getline, die Benutzereingabezeilen liest. Diese Funktion wird verwendet, um den "Schlüssel" des Inhalts und nicht den Inhalt selbst zu lesen.
  • Im Writeup werden 5 anfängliche Chunks erstellt:
  • chunk1 (0x200)
  • chunk2 (0x50)
  • chunk5 (0x68)
  • chunk3 (0x1f8)
  • chunk4 (0xf0)
  • Chunk-Verteidigung (0x400), um die Konsolidierung mit dem Top-Chunk zu vermeiden.
  • Dann werden Chunk 1, 5 und 3 freigegeben, sodass:

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

- Dann wird Chunk3 (0x1f8) ausgenutzt, um den null Off-by-One auszunutzen, indem `prev_size` auf `0x4e0` geschrieben wird.
- Beachten Sie, wie die Größen der ursprünglich zugewiesenen Chunks 1, 2, 5 und 3 sowie die Header von 4 dieser Chunks gleich `0x4e0` sind: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Dann wird Chunk 4 freigegeben, wodurch ein Chunk entsteht, der alle Chunks bis zum Anfang verbraucht:
- ```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 ]