10 KiB
Atak na nieposortowany blok
{% hint style="success" %}
Dowiedz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Dowiedz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Wesprzyj HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Udostępnij sztuczki hakerskie, przesyłając PR-y do HackTricks i HackTricks Cloud na GitHubie.
Podstawowe informacje
Aby uzyskać więcej informacji na temat tego, co oznacza nieposortowany blok, sprawdź tę stronę:
{% content-ref url="bins-and-memory-allocations.md" %} bins-and-memory-allocations.md {% endcontent-ref %}
Nieposortowane listy mogą zapisać adres w unsorted_chunks (av)
w adresie bk
fragmentu. Dlatego jeśli atakujący może zmodyfikować adres wskaźnika bk
w fragmencie wewnątrz nieposortowanego bloku, może zapisać ten adres w dowolnym adresie, co może być pomocne do wycieku adresów Glibc lub obejścia niektórych zabezpieczeń.
W zasadzie ten atak pozwala ustawić dużą liczbę pod dowolnym adresem. Ta duża liczba to adres, który może być adresem sterty lub adresem Glibc. Typowym celem jest global_max_fast
, aby umożliwić tworzenie szybkich bloków o większych rozmiarach (i przejście od ataku na nieposortowany blok do ataku na szybki blok).
{% hint style="success" %}
Przyjrzenie się przykładowi podanemu w https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle i użycie 0x4000 i 0x5000 zamiast 0x400 i 0x500 jako rozmiarów fragmentów (aby uniknąć Tcache) pozwala zobaczyć, że obecnie błąd malloc(): unsorted double linked list corrupted
jest wywoływany.
Dlatego ten atak na nieposortowany blok teraz (oprócz innych sprawdzeń) wymaga również naprawienia podwójnej listy połączonej, aby to ominąć victim->bk->fd == victim
lub nie victim->fd == av (arena)
, co oznacza, że adres, gdzie chcemy zapisać, musi mieć adres fałszywego fragmentu w swojej pozycji fd
i że fałszywy fragment fd
wskazuje na arenę.
{% endhint %}
{% hint style="danger" %} Zauważ, że ten atak psuje nieposortowany blok (a także mały i duży). Dlatego teraz możemy korzystać tylko z alokacji z szybkiego bloku (bardziej złożony program może wykonywać inne alokacje i się zawieszać), a aby to wywołać, musimy alokować ten sam rozmiar, w przeciwnym razie program się zawiesi.
Zauważ, że nadpisanie global_max_fast
może pomóc w tym przypadku, zakładając, że szybki blok będzie w stanie obsłużyć wszystkie inne alokacje, dopóki exploit nie zostanie zakończony.
{% endhint %}
Kod od guyinatuxedo dobrze to wyjaśnia, chociaż jeśli zmodyfikujesz alokacje pamięci, aby alokować pamięć wystarczająco dużą, aby nie trafić do Tcache, zobaczysz, że wcześniej wspomniany błąd uniemożliwia zastosowanie tej techniki: malloc(): unsorted double linked list corrupted
Atak na wyciek informacji z nieposortowanego bloku
To tak naprawdę bardzo podstawowe pojęcie. Fragmenty w nieposortowanym bloku będą miały wskaźniki. Pierwszy fragment w nieposortowanym bloku będzie faktycznie mieć linki fd
i bk
wskazujące na część głównej areny (Glibc).
Dlatego jeśli możesz umieścić fragment wewnątrz nieposortowanego bloku i odczytać go (użyj po zwolnieniu) lub ponownie go zaalokować bez nadpisywania co najmniej 1 z wskaźników, aby następnie go odczytać, możesz uzyskać wyciek informacji z Glibc.
Podobny atak użyty w tym opisie, polegał na wykorzystaniu struktury 4 fragmentów (A, B, C i D - D służył tylko do zapobiegania konsolidacji z górnym fragmentem), więc przepełnienie null bajtów w B zostało wykorzystane do spowodowania, że C wskazywało, że B jest nieużywane. Ponadto w B zmodyfikowano dane prev_size
, więc rozmiar zamiast być rozmiarem B, był A+B.
Następnie C został zwolniony i zkonsolidowany z A+B (ale B nadal był używany). Zaalokowano nowy fragment o rozmiarze A, a następnie wyciekły adresy Glibc, które zostały zapisane w B, skąd zostały wycieknięte.
Odwołania i inne przykłady
- https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap
- Celem jest nadpisanie zmiennej globalnej wartością większą niż 4869, aby można było uzyskać flagę, a PIE nie jest włączone.
- Możliwe jest generowanie fragmentów o dowolnych rozmiarach i występuje przepełnienie sterty o pożądanym rozmiarze.
- Atak rozpoczyna się od utworzenia 3 fragmentów: fragmentu0 do wykorzystania przepełnienia, fragmentu1 do przepełnienia i fragmentu2, aby górny fragment nie konsolidował poprzednich.
- Następnie fragment1 jest zwalniany, a fragment0 jest przepełniany, aby wskaźnik
bk
fragmentu1 wskazywał na:bk = magic - 0x10
- Następnie alokowany jest fragment3 o tym samym rozmiarze co fragment1, co spowoduje atak na nieposortowany blok i zmodyfikuje wartość zmiennej globalnej, umożliwiając uzyskanie flagi.
- https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html
- Funkcja łączenia jest podatna, ponieważ jeśli oba przekazane indeksy są takie same, to zrealokuje na nim i zwolni go, ale zwróci wskaźnik do tego zwolnionego obszaru, który można wykorzystać.
- Dlatego tworzone są 2 fragmenty: fragment0, który zostanie połączony ze sobą i fragment1, aby zapobiec konsolidacji z górnym fragmentem. Następnie funkcja merge jest wywoływana z fragmentem0 dwukrotnie, co spowoduje użycie po zwolnieniu.
- Następnie wywoływana jest funkcja
view
z indeksem 2 (który jest indeksem używanego po zwolnieniu fragmentu), co spowoduje wyciek adresu libc. - Ponieważ binarny ma zabezpieczenia, aby alokować tylko rozmiary większe niż
global_max_fast
, więc nie używany jest szybki blok, atak na nieposortowany blok zostanie wykorzystany do nadpisania zmiennej globalnejglobal_max_fast
. - Następnie możliwe jest wywołanie funkcji edycji z indeksem 2 (wskaźnik używany po zwolnieniu) i nadpisanie wskaźnika
bk
, aby wskazywał nap64(global_max_fast-0x10)
. Następnie tworzenie nowego fragmentu użyje wcześniej skompromitowanego adresu zwolnienia (0x20) i wywoła atak na nieposortowany blok, nadpisującglobal_max_fast
dużą wartością, co teraz pozwala na tworzenie fragmentów w szybkich blokach. - Teraz wykonywany jest atak na szybki blok:
- Po pierwsze odkryto, że możliwe jest pracowanie z szybkimi fragmentami o rozmiarze 200 w lokalizacji
__free_hook
: -
gef➤ p &__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
- Jeśli uda nam się uzyskać szybki kawałek o rozmiarze 0x200 w tym miejscu, będzie możliwe nadpisanie wskaźnika funkcji, który zostanie wykonany
- W tym celu tworzony jest nowy kawałek o rozmiarze
0xfc
i funkcja scalająca jest wywoływana z tym wskaźnikiem dwukrotnie, w ten sposób uzyskujemy wskaźnik do zwolnionego kawałka o rozmiarze0xfc*2 = 0x1f8
w szybkim pojemniku. - Następnie funkcja edycji jest wywoływana w tym kawałku, aby zmodyfikować adres
fd
tego szybkiego pojemnika wskazujący na poprzednią funkcję__free_hook
. - Następnie tworzony jest kawałek o rozmiarze
0x1f8
w celu pobrania z szybkiego pojemnika poprzedniego nieużytecznego kawałka, więc tworzony jest kolejny kawałek o rozmiarze0x1f8
, aby uzyskać kawałek z szybkiego pojemnika w__free_hook
, który jest nadpisany adresem funkcjisystem
. - I wreszcie zwalniany jest kawałek zawierający ciąg znaków
/bin/sh\x00
, wywołując funkcję usuwania, co powoduje wywołanie funkcji__free_hook
, która wskazuje na system z parametrem/bin/sh\x00
. - CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html
- Kolejny przykład nadużycia przepełnienia o 1B w celu skonsolidowania kawałków w nieuporządkowanym pojemniku i uzyskania wycieku informacji o libc, a następnie przeprowadzenia ataku na szybki pojemnik w celu nadpisania haka malloc adresem jednego gadżetu
- Robot Factory. BlackHat MEA CTF 2022
- Możemy przydzielać tylko kawałki o rozmiarze większym niż
0x100
. - Nadpisanie
global_max_fast
za pomocą ataku na nieuporządkowany pojemnik (działa 1/16 razy ze względu na ASLR, ponieważ musimy zmodyfikować 12 bitów, ale musimy zmodyfikować 16 bitów). - Atak na szybki pojemnik w celu zmodyfikowania globalnej tablicy kawałków. Zapewnia to arbitralne odczyt/zapis, co pozwala na modyfikację GOT i ustawienie pewnej funkcji na wskazanie
system
.