# Stack Canaries {{#include ../../../banners/hacktricks-training.md}} ## **StackGuard i StackShield** **StackGuard** wstawia specjalną wartość znaną jako **canary** przed **EIP (Extended Instruction Pointer)**, konkretnie `0x000aff0d` (reprezentujący 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 proces nadrzędny lub rodzeństwo. Niemniej jednak, jeśli **`fork()` jest używane bez tworzenia nowego canary, wszystkie procesy (nadrzędne i potomne) 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 WWW 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 którym momencie tworzony jest duplikat, 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.** > [!CAUTION] > 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**. ## 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: {{#ref}} bf-forked-stack-canaries.md {{#endref}} - Jeśli w binarnym kodzie występuje interesujące **wyciekanie lub podatność na odczyt dowolny**, może być możliwe jego wyciekanie: {{#ref}} print-stack-canary.md {{#endref}} - **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ź: {{#ref}} ../../stack-overflow/pointer-redirecting.md {{#endref}} - **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 wątku**. W rezultacie, łagodzenie jest bezużyteczne, ponieważ sprawdzenie jest używane z dwoma canary, które są takie same (choć zmodyfikowane). Ponadto, przepełnienie bufora w funkcji wątkowej chronionej canary mogłoby być użyte do **modyfikacji master canary przechowywanego w TLS**. To dlatego, że może być możliwe dotarcie do pozycji pamięci, w której przechowywane jest TLS (a zatem, canary) za pomocą **bof na stosie** wątku.\ W rezultacie, łagodzenie jest bezużyteczne, ponieważ sprawdzenie jest używane z dwoma canary, które są takie same (choć zmodyfikowane).\ Ten atak jest opisany w artykule: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads) Sprawdź również prezentację [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015), która wspomina, że zazwyczaj **TLS** jest przechowywane przez **`mmap`**, a gdy **stos** **wątku** jest tworzony, jest również generowany przez `mmap`, co może umożliwić przepełnienie, jak pokazano w poprzednim artykule. - **Modyfikacja wpisu GOT `__stack_chk_fail`** Jeśli binarny kod ma Partial RELRO, można użyć dowolnego zapisu, aby zmodyfikować **GOT entry `__stack_chk_fail`** na funkcję zastępczą, która nie blokuje programu, jeśli canary zostanie zmodyfikowane. Ten atak jest opisany w artykule: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/) ## Odniesienia - [https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html) - [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads) - [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/) {{#include ../../../banners/hacktricks-training.md}}