Unsorted Bin Attack

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Podstawowe informacje

Aby uzyskać więcej informacji na temat tego, co oznacza kubełek nieposortowany, sprawdź tę stronę:

Bins & Memory Allocations

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 w kubełku nieposortowanym, może zapisać ten adres w dowolnym adresie, co może pomóc w wycieku adresów libc lub obejściu niektórych zabezpieczeń.

W zasadzie ten atak pozwala nadpisać dowolny adres dużą liczbą (adres, który może być adresem sterty lub adresem libc), na przykład adresem stosu, który może być wyciekany, lub jakąś restrykcją, taką jak globalna zmienna global_max_fast, aby umożliwić tworzenie kubełków fast bin o większych rozmiarach (i przejście od ataku na kubełek nieposortowany do ataku na fast bin).

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ąć tcaches) pozwala zobaczyć, że obecnie błąd malloc(): unsorted double linked list corrupted jest wywoływany.

Dlatego teraz ten atak na kubełek nieposortowany (oprócz innych sprawdzeń) wymaga również naprawienia podwójnej listy połączonej, aby to ominąć victim->bck->fd == victim lub nie victim->fd == av (arena). Oznacza to, że adres, w który chcemy zapisać, musi mieć adres fałszywego fragmentu w swojej pozycji fd, a fałszywy fragment fd musi wskazywać na arenę.

Zauważ, że ten atak psuje kubełek nieposortowany (a także mały i duży). Dlatego teraz możemy korzystać tylko z alokacji z kubełka fast bin (bardziej złożony program może wykonywać inne alokacje i się zawiesić), aby to wywołać, musimy zaalokować ten sam rozmiar, inaczej program się zawiesi.

Zauważ, że ustawienie global_max_fast może pomóc w tym przypadku, zakładając, że kubełek fast będzie w stanie obsłużyć wszystkie inne alokacje, aż exploit zostanie zakończony.

Kod od guyinatuxedo wyjaśnia to bardzo dobrze, chociaż jeśli zmodyfikujesz alokacje pamięci tak, aby alokować pamięć wystarczająco dużą, aby nie trafić do tcaches, zobaczysz, że wcześniej wspomniany błąd uniemożliwia zastosowanie tej techniki: malloc(): unsorted double linked list corrupted

Atak na wyciek informacji z kubełka nieposortowanego

To tak naprawdę bardzo podstawowe pojęcie. Fragmenty w kubełku nieposortowanym będą miały wskaźniki podwójne wskaźniki, aby utworzyć kubełek. Pierwszy fragment w kubełku nieposortowanym będzie faktycznie mieć FD i BK łącza wskazujące na część głównej areny (libc). Dlatego jeśli możesz umieścić fragment w kubełku nieposortowanym 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 libc.

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 fragmentem górnym), więc przepełnienie bajtów null 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 skonsolidowany z A+B (ale B nadal był używany). Zaalokowano nowy fragment o rozmiarze A, a następnie wyciekane były adresy libc, które zostały zapisane do B, skąd zostały wycieknięte.

Odwołania i inne przykłady

  • 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 fragmenty poprzednie nie zostały skonsolidowane z fragmentem górnym.

  • Następnie fragment1 jest zwalniany, a fragment0 jest przepełniany, aby wskaźnik bk fragmentu1 wskazywał na: bk = magic - 0x10

  • Następnie zaalokowany jest fragment3 o tym samym rozmiarze co fragment1, co spowoduje atak na kubełek nieposortowany i zmodyfikuje wartość zmiennej globalnej, umożliwiając uzyskanie flagi.

  • Funkcja scalania 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 scalony sam ze sobą i fragment1, aby zapobiec konsolidacji z fragmentem górnym. Następnie funkcja scalania jest wywoływana z fragmentem0 dwa razy, co spowoduje użycie po zwolnieniu.

  • Następnie wywoływana jest funkcja view z indeksem 2 (który jest indeksem fragmentu użytego po zwolnieniu), 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 fastbin, atak na kubełek nieposortowany zostanie wykorzystany do nadpisania zmiennej globalnej global_max_fast.

  • Następnie możliwe jest wywołanie funkcji edycji z indeksem 2 (wskaźnik użyty po zwolnieniu) i nadpisanie wskaźnika bk, aby wskazywał na p64(global_max_fast-0x10). Następnie tworząc nowy fragment użyje się wcześniej skompromitowanego adresu zwolnienia (0x20) i wywoła atak na kubełek nieposortowany, nadpisując global_max_fast dużą wartością, co teraz pozwala na tworzenie fragmentów w kubełkach fast.

  • Teraz wykonywany jest atak na fast bin:

  • Po pierwsze odkryto, że możliwe jest pracowanie z fragmentami fast 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 tej lokalizacji, 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 rozmiarze 0xfc*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 odzyskania z szybkiego pojemnika poprzedniego nieużytecznego kawałka, więc tworzony jest kolejny kawałek o rozmiarze 0x1f8, aby uzyskać kawałek z szybkiego pojemnika w __free_hook, który jest nadpisany adresem funkcji system.

  • 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.

  • Kolejny przykład nadużycia przepełnienia o 1B w celu skonsolidowania kawałków w nieuporządkowanym pojemniku i uzyskania wycieku informacji z libc, a następnie przeprowadzenia ataku na szybki pojemnik w celu nadpisania haka malloc adresem jednego gadżetu

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Last updated