Unlink Attack
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)
Check the subscription plans!
Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Als dieser Angriff entdeckt wurde, erlaubte er hauptsächlich ein WWW (Write What Where), jedoch wurden einige Überprüfungen hinzugefügt, die die neue Version des Angriffs interessanter, komplexer und nutzlos machten.
```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 3 Adressen vor sich selbst zeigt**. Wenn dieser neue Standort (Umgebung, in der sich der Zeiger befand) interessante Inhalte hat, wie andere kontrollierbare Zuweisungen / Stack..., ist es möglich, diese zu lesen/überschreiben, um größeren Schaden zu verursachen.
* Wenn sich dieser Zeiger im Stack befand, weil er jetzt 3 Adressen vor sich selbst zeigt und der Benutzer ihn potenziell lesen und ändern kann, wird es möglich sein, sensible Informationen aus dem Stack zu leaken oder sogar die Rücksprungadresse (vielleicht) zu ändern, ohne den Canary zu berühren.
* In CTF-Beispielen befindet sich dieser Zeiger in einem Array von Zeigern auf andere Zuweisungen, daher ist es möglich, ihn 3 Adressen vorzuzeigen und ihn lesen und schreiben zu können, sodass die anderen Zeiger auf andere Adressen zeigen.\
Da der Benutzer potenziell auch die anderen Zuweisungen lesen/schreiben kann, kann er Informationen leaken oder neue Adressen an beliebigen Orten (wie im GOT) überschreiben.
### Anforderungen
* Etwas Kontrolle über einen Speicher (z.B. Stack), um ein paar Chunks zu erstellen, indem Werte für einige der Attribute zugewiesen werden.
* 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.
* In chunk1 erstellt der Angreifer die Struktur eines gefälschten Chunks:
* Um Schutzmaßnahmen 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 -3 und -2 gespeichert ist, sodass `fake_chunk->fd->bk` und `fake_chunk->bk->fd` auf die Position im Speicher (Stack) zeigen, an der die echte chunk1-Adresse gespeichert ist:
<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 von chunk2 werden geändert, um anzuzeigen, dass der vorherige Chunk nicht verwendet wird und dass die Größe die Größe des enthaltenen gefälschten Chunks ist.
* Wenn der zweite Chunk freigegeben wird, wird dieser gefälschte Chunk unlinked, was passiert:
* `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 denselben Ort zeigen (den Ort im Stack, an dem `chunk1` gespeichert war, sodass es eine gültige verkettete Liste war). Da **beide auf denselben Ort zeigen**, wird nur der letzte (`fake_chunk->bk->fd = fake_chunk->fd`) **wirksam**.
* Dies wird **den Zeiger auf chunk1 im Stack auf die Adresse (oder Bytes) überschreiben, die 3 Adressen vorher im Stack gespeichert sind**.
* Daher, wenn ein Angreifer den Inhalt von chunk1 erneut kontrollieren könnte, wäre er in der Lage, **im Stack zu schreiben**, wodurch er potenziell die Rücksprungadresse überschreiben und die Werte und Punkte lokaler Variablen ändern könnte. Sogar die Adresse von chunk1, die im Stack gespeichert ist, auf einen anderen Ort ändern, wo der Angreifer, wenn er den Inhalt von chunk1 erneut kontrollieren könnte, überall schreiben könnte.
* Beachten Sie, dass dies möglich war, weil die **Adressen im Stack gespeichert sind**. Das Risiko und die Ausnutzung könnten 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 sogar in einem CTF zu finden, haben Sie hier einige Writeups, 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 mallocierten Adressen. Der unlink-Angriff wird durchgeführt, um hier einen Chunk zuzuweisen, wodurch die Zeiger des Arrays von mallocierten Adressen kontrolliert werden können. Dann gibt es eine andere Funktionalität, die es ermöglicht, den Inhalt von Chunks in diesen Adressen zu ändern, was es ermöglicht, Adressen auf den GOT zu zeigen, Funktionsadressen zu ändern, um Leaks zu erhalten und RCE.
* 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 Zuweisungen. Es ist möglich, einen unlink-Angriff durchzuführen, um die Adresse zur ersten Zuweisung auf einige Positionen vor dem Beginn des Arrays zeigen zu lassen und diese Zuweisung an der neuen Position zu überschreiben. Daher ist es möglich, Zeiger anderer Zuweisungen zu überschreiben, um auf den GOT von atoi zu zeigen, ihn auszudrucken, um einen libc-Leak zu erhalten, und dann den atoi-GOT mit der Adresse zu einem One-Gadget zu überschreiben.
* CTF-Beispiel mit benutzerdefinierten malloc- und free-Funktionen, die eine sehr ähnliche Schwachstelle wie den unlink-Angriff ausnutzen: [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 einen Überlauf, der es ermöglicht, die FD- und BK-Zeiger von benutzerdefiniertem malloc zu kontrollieren, das (benutzerdefiniert) freigegeben wird. Darüber hinaus hat der Heap das Ausführungsbit, sodass es möglich ist, eine Heap-Adresse zu leaken und eine Funktion vom GOT auf einen Heap-Chunk mit einem Shellcode zu zeigen, um ihn auszuführen.
<div data-gb-custom-block data-tag="hint" data-style='success'>
Lernen & üben Sie AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Lernen & üben Sie GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Support HackTricks</summary>
* Überprüfen Sie die [**Abonnementpläne**](https://github.com/sponsors/carlospolop)!
* **Treten Sie der** 💬 [**Discord-Gruppe**](https://discord.gg/hRep4RUj7f) oder der [**Telegram-Gruppe**](https://t.me/peass) bei oder **folgen** Sie uns auf **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Teilen Sie Hacking-Tricks, indem Sie PRs an die** [**HackTricks**](https://github.com/carlospolop/hacktricks) und [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) GitHub-Repos senden.
</details>
</div>