hacktricks/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections-and-bypasses/stack-canaries
2024-07-18 22:15:55 +00:00
..
bf-forked-stack-canaries.md Translated ['binary-exploitation/basic-stack-binary-exploitation-methodo 2024-07-18 22:15:55 +00:00
print-stack-canary.md Translated ['binary-exploitation/basic-stack-binary-exploitation-methodo 2024-07-18 22:15:55 +00:00
README.md Translated ['binary-exploitation/basic-stack-binary-exploitation-methodo 2024-07-18 22:15:55 +00:00

Stack Canaries

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

StackGuard i StackShield

StackGuard wstawia specjalną wartość znaną jako canary przed EIP (Extended Instruction Pointer), konkretnie 0x000aff0d (reprezentująca null, newline, EOF, carriage return), aby chronić przed przepełnieniem bufora. Jednak funkcje takie jak recv(), memcpy(), read(), i bcopy() pozostają podatne, a ochrona nie obejmuje EBP (Base Pointer).

StackShield przyjmuje bardziej zaawansowane podejście niż StackGuard, utrzymując Global Return Stack, który przechowuje wszystkie adresy powrotu (EIPs). Ta konfiguracja zapewnia, że każde przepełnienie nie powoduje szkód, ponieważ pozwala na porównanie przechowywanych i rzeczywistych adresów powrotu w celu wykrycia wystąpień przepełnienia. Dodatkowo, StackShield może sprawdzić adres powrotu w stosunku do wartości granicznej, aby wykryć, czy EIP wskazuje poza oczekiwaną przestrzeń danych. Jednak ta ochrona może być obejściem za pomocą technik takich jak Return-to-libc, ROP (Return-Oriented Programming) lub ret2ret, co wskazuje, że StackShield również nie chroni zmiennych lokalnych.

Stack Smash Protector (ProPolice) -fstack-protector:

Ten mechanizm umieszcza canary przed EBP i reorganizuje zmienne lokalne, aby umieścić bufory na wyższych adresach pamięci, zapobiegając ich nadpisywaniu innych zmiennych. Bezpiecznie kopiuje również argumenty przekazywane na stosie powyżej zmiennych lokalnych i używa tych kopii jako argumentów. Jednak nie chroni tablic z mniej niż 8 elementami ani buforów w strukturze użytkownika.

Canary to losowa liczba pochodząca z /dev/urandom lub domyślna wartość 0xff0a0000. Jest przechowywana w TLS (Thread Local Storage), co pozwala na współdzielenie przestrzeni pamięci między wątkami, aby miały one specyficzne dla wątku zmienne globalne lub statyczne. Te zmienne są początkowo kopiowane z procesu nadrzędnego, a procesy potomne mogą zmieniać swoje dane bez wpływu na rodzica lub rodzeństwo. Niemniej jednak, jeśli fork() jest używane bez tworzenia nowego canary, wszystkie procesy (rodzic i dzieci) dzielą ten sam canary, co czyni je podatnymi. W architekturze i386 canary jest przechowywane w gs:0x14, a w x86_64 w fs:0x28.

Ta lokalna ochrona identyfikuje funkcje z buforami podatnymi na ataki i wstrzykuje kod na początku tych funkcji, aby umieścić canary, a na końcu, aby zweryfikować jego integralność.

Gdy serwer internetowy używa fork(), umożliwia to atak brute-force w celu odgadnięcia bajtu canary po bajcie. Jednak użycie execve() po fork() nadpisuje przestrzeń pamięci, niwecząc atak. vfork() pozwala procesowi potomnemu na wykonanie bez duplikacji, aż spróbuje zapisać, w tym momencie tworzona jest duplikacja, oferując inne podejście do tworzenia procesów i zarządzania pamięcią.

Długości

W binariach x64 cookie canary to 0x8 bajtowy qword. Pierwsze siedem bajtów jest losowych, a ostatni bajt to null byte.

W binariach x86 cookie canary to 0x4 bajtowy dword. Pierwsze trzy bajty są losowe, a ostatni bajt to null byte.

{% hint style="danger" %} Najmniej znaczący bajt obu canary to null byte, ponieważ będzie pierwszym na stosie pochodzącym z niższych adresów i dlatego funkcje, które odczytują ciągi, zatrzymają się przed jego odczytaniem. {% endhint %}

Obejścia

Wyciekanie canary i następnie nadpisywanie go (np. przepełnienie bufora) własną wartością.

  • Jeśli canary jest forkowane w procesach potomnych, może być możliwe brute-force go bajt po bajcie:

{% content-ref url="bf-forked-stack-canaries.md" %} bf-forked-stack-canaries.md {% endcontent-ref %}

  • Jeśli w binarnym kodzie występuje interesujące wyciekanie lub podatność na dowolne odczyty, może być możliwe jego wyciekanie:

{% content-ref url="print-stack-canary.md" %} print-stack-canary.md {% endcontent-ref %}

  • Nadpisywanie wskaźników przechowywanych na stosie

Stos podatny na przepełnienie stosu może zawierać adresy do ciągów lub funkcji, które mogą być nadpisane, aby wykorzystać podatność bez potrzeby dotarcia do canary. Sprawdź:

{% content-ref url="../../stack-overflow/pointer-redirecting.md" %} pointer-redirecting.md {% endcontent-ref %}

  • Modyfikacja zarówno master, jak i thread canary

Przepełnienie bufora w funkcji wątkowej chronionej canary może być użyte do modyfikacji master canary wątku. W rezultacie, łagodzenie jest bezużyteczne, ponieważ sprawdzenie jest używane z dwoma canary, które są takie same (choć zmodyfikowane).

  • Modyfikacja wpisu GOT __stack_chk_fail

Jeśli binarny kod ma Partial RELRO, można użyć dowolnego zapisu, aby zmodyfikować wpis GOT __stack_chk_fail, aby był to funkcja zastępcza, która nie blokuje programu, jeśli canary zostanie zmodyfikowane.

Referencje

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}