77 lines
6.5 KiB
Markdown

# 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}}