Unlink Attack

Unterstützen Sie HackTricks

Grundlegende Informationen

Als dieser Angriff entdeckt wurde, ermöglichte er hauptsächlich ein WWW (Write What Where), jedoch wurden einige Überprüfungen hinzugefügt, was die neue Version des Angriffs interessanter, komplexer und nutzloser macht.

Codebeispiel:

Code

```c #include #include #include #include

// Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work

struct chunk_structure { size_t prev_size; size_t size; struct chunk_structure *fd; struct chunk_structure *bk; char buf[10]; // padding };

int main() { unsigned long long *chunk1, *chunk2; struct chunk_structure *fake_chunk, *chunk2_hdr; char data[20];

// First grab two chunks (non fast) chunk1 = malloc(0x8000); chunk2 = malloc(0x8000); printf("Stack pointer to chunk1: %p\n", &chunk1); printf("Chunk1: %p\n", chunk1); printf("Chunk2: %p\n", chunk2);

// Assuming attacker has control over chunk1's contents // Overflow the heap, override chunk2's header

// First forge a fake chunk starting at chunk1 // Need to setup fd and bk pointers to pass the unlink security check fake_chunk = (struct chunk_structure *)chunk1; fake_chunk->size = 0x8000; fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P

// Next modify the header of chunk2 to pass all security checks chunk2_hdr = (struct chunk_structure *)(chunk2 - 2); chunk2_hdr->prev_size = 0x8000; // chunk1's data region size chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit

// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked' // This results in chunk1 pointer pointing to chunk1 - 3 // i.e. chunk1[3] now contains chunk1 itself. // We then make chunk1 point to some victim's data free(chunk2); printf("Chunk1: %p\n", chunk1); printf("Chunk1[3]: %x\n", chunk1[3]);

chunk1[3] = (unsigned long long)data;

strcpy(data, "Victim's data");

// Overwrite victim's data using chunk1 chunk1[0] = 0x002164656b636168LL;

printf("%s\n", data);

return 0; }

</details>

* Der Angriff funktioniert nicht, wenn tcaches verwendet werden (nach 2.26)

### Ziel

Dieser Angriff ermöglicht es, **einen Zeiger auf einen Chunk so zu ändern, dass er auf 3 Adressen vor sich selbst zeigt**. Wenn diese neue Position (Umgebung, in der sich der Zeiger befand) interessante Informationen enthält, wie andere steuerbare Allokationen / Stack..., ist es möglich, sie zu lesen/überschreiben, um größeren Schaden anzurichten.

* Wenn dieser Zeiger im Stack war, weil er jetzt 3 Adressen vor sich selbst zeigt und der Benutzer ihn potenziell lesen und ändern kann, ist es möglich, sensible Informationen aus dem Stack auszulesen oder sogar die Rückkehradresse zu ändern (vielleicht) ohne den Canary zu berühren.
* In CTF-Beispielen befindet sich dieser Zeiger in einem Array von Zeigern auf andere Allokationen. Daher ist es möglich, indem er 3 Adressen vor sich zeigt und lesen und schreiben kann, die anderen Zeiger auf andere Adressen zu zeigen.\
Da der Benutzer potenziell auch die anderen Allokationen lesen/schreiben kann, kann er Informationen auslesen oder neue Adressen an beliebigen Stellen überschreiben (z. B. im GOT).

### Anforderungen

* Kontrolle über einen Speicherbereich (z. B. Stack), um ein paar Chunks zu erstellen und Werte für einige der Attribute festzulegen.
* Stack-Leak, um die Zeiger des gefälschten Chunks festzulegen.

### Angriff

* Es gibt ein paar Chunks (Chunk1 und Chunk2).
* Der Angreifer kontrolliert den Inhalt von Chunk1 und die Header von Chunk2.
* Im Chunk1 erstellt der Angreifer die Struktur eines gefälschten Chunks:
* Um Schutzmechanismen zu umgehen, stellt er sicher, dass das Feld `size` korrekt ist, um den Fehler zu vermeiden: `corrupted size vs. prev_size while consolidating`
* und die Felder `fd` und `bk` des gefälschten Chunks zeigen auf die Stelle, an der der Chunk1-Zeiger mit den Offsets von -3 bzw. -2 gespeichert ist, sodass `fake_chunk->fd->bk` und `fake_chunk->bk->fd` auf die Position im Speicher (Stack) zeigen, an der sich die tatsächliche Chunk1-Adresse befindet:

<figure><img src="../../.gitbook/assets/image (1245).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>

* Die Header des Chunk2 werden geändert, um anzuzeigen, dass der vorherige Chunk nicht verwendet wird und dass die Größe der Größe des enthaltenen gefälschten Chunks entspricht.
* Wenn der zweite Chunk freigegeben wird, wird dieser gefälschte Chunk entkoppelt:
* `fake_chunk->fd->bk` = `fake_chunk->bk`
* `fake_chunk->bk->fd` = `fake_chunk->fd`
* Zuvor wurde sichergestellt, dass `fake_chunk->fd->bk` und `fake_chunk->bk->fd` auf dieselbe Stelle zeigen (die Stelle im Stack, an der `Chunk1` gespeichert war, sodass es eine gültige verkettete Liste war). Da **beide auf dieselbe Stelle zeigen**, wird nur der letzte (`fake_chunk->bk->fd = fake_chunk->fd`) **effektiv**.
* Dies wird dazu führen, dass der **Zeiger auf Chunk1 im Stack mit der Adresse (oder Bytes) überschrieben wird, die sich 3 Adressen vor dem Stack befinden**.
* Daher kann ein Angreifer, wenn er erneut den Inhalt von Chunk1 kontrollieren kann, **im Stack schreiben**, potenziell die Rückkehradresse überschreiben, den Canary überspringen und die Werte und Zeiger von lokalen Variablen ändern. Selbst wenn er erneut die Adresse von Chunk1 im Stack an eine andere Stelle ändert, an der der Angreifer erneut den Inhalt von Chunk1 kontrollieren kann, kann er überall schreiben.
* Beachten Sie, dass dies möglich war, weil die **Adressen im Stack gespeichert sind**. Das Risiko und die Ausnutzung können davon abhängen, **wo die Adressen des gefälschten Chunks gespeichert sind**.

<figure><img src="../../.gitbook/assets/image (1246).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>

## Referenzen

* [https://heap-exploitation.dhavalkapil.com/attacks/unlink\_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink\_exploit)
* Obwohl es seltsam wäre, einen unlink-Angriff selbst in einem CTF zu finden, hier sind einige Write-ups, in denen dieser Angriff verwendet wurde:
* CTF-Beispiel: [https://guyinatuxedo.github.io/30-unlink/hitcon14\_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14\_stkof/index.html)
* In diesem Beispiel gibt es anstelle des Stacks ein Array von malloc-Adressen. Der unlink-Angriff wird durchgeführt, um einen Chunk hier zu allozieren und somit die Zeiger des Arrays von malloc-Adressen zu kontrollieren. Dann gibt es eine weitere Funktionalität, die es ermöglicht, den Inhalt von Chunks an diesen Adressen zu ändern, was es ermöglicht, Adressen auf die GOT zu zeigen, Funktionenadressen zu ändern, um Lecks und RCE zu erhalten.
* Ein weiteres CTF-Beispiel: [https://guyinatuxedo.github.io/30-unlink/zctf16\_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16\_note2/index.html)
* Genau wie im vorherigen Beispiel gibt es ein Array von Adressen von Allokationen. Es ist möglich, einen unlink-Angriff durchzuführen, um die Adresse der ersten Allokation ein paar Positionen vor dem Array zu machen und dann diese Allokation an der neuen Position zu überschreiben. Daher ist es möglich, Zeiger anderer Allokationen zu überschreiben, um auf die GOT von atoi zu zeigen, diese auszugeben, um ein libc-Leck zu erhalten, und dann die atoi-GOT mit der Adresse zu einem One-Gadget zu überschreiben.
* CTF-Beispiel mit benutzerdefinierten malloc- und free-Funktionen, die eine Schwachstelle missbrauchen, die der unlink-Attacke sehr ähnlich ist: [https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw17\_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw17\_minesweeper/index.html)
* Es gibt ein Überlauf, der es ermöglicht, die FD- und BK-Zeiger des benutzerdefinierten malloc zu kontrollieren, der (benutzerdefiniert) freigegeben wird. Darüber hinaus hat der Heap das Ausführungsbit, sodass es möglich ist, eine Heap-Adresse auszulesen und eine Funktion aus der GOT auf einen Heap-Chunk mit einem Shellcode zu zeigen, um sie auszuführen.

Last updated