Stack Canaries

Nauka hakowania AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

StackGuard i StackShield

StackGuard wstawia specjalną wartość znaną jako kanarka przed EIP (Extended Instruction Pointer), konkretnie 0x000aff0d (reprezentującą null, znak nowej linii, EOF, powrót karetki) w celu ochrony przed przepełnieniem bufora. Jednak funkcje takie jak recv(), memcpy(), read() i bcopy() pozostają podatne, a także nie chroni EBP (Base Pointer).

StackShield stosuje bardziej zaawansowane podejście niż StackGuard, utrzymując Globalny Stos Powrotu, który przechowuje wszystkie adresy powrotu (EIP). Ten układ zapewnia, że przepełnienie nie powoduje szkód, ponieważ umożliwia porównanie przechowywanych i rzeczywistych adresów powrotu w celu wykrycia wystąpienia przepełnienia. Dodatkowo, StackShield może sprawdzić adres powrotu względem wartości granicznej, aby wykryć, czy EIP wskazuje poza oczekiwaną przestrzeń danych. Jednak ta ochrona może być obejścia za pomocą technik takich jak Return-to-libc, ROP (Return-Oriented Programming) lub ret2ret, co oznacza, że StackShield również nie chroni zmiennych lokalnych.

Protector Stack Smash (ProPolice) -fstack-protector:

Ten mechanizm umieszcza kanarkę przed EBP i przestawia zmienne lokalne w taki sposób, aby bufory znajdowały się na wyższych adresach pamięci, uniemożliwiając nadpisywanie innych zmiennych. Bezpiecznie kopiuje również argumenty przekazane na stosie powyżej zmiennych lokalnych i używa tych kopii jako argumentów. Jednak nie chroni tablic o mniej niż 8 elementach ani buforów w strukturze użytkownika.

Kanarka to losowa liczba pochodząca z /dev/urandom lub domyślna wartość 0xff0a0000. Jest przechowywana w TLS (Thread Local Storage), co pozwala na współużytkowanie przestrzeni pamięci między wątkami dla zmiennych globalnych lub statycznych specyficznych dla wątku. 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 używane jest fork() bez tworzenia nowej kanarki, wszystkie procesy (rodzic i dzieci) współdzielą tę samą kanarkę, co czyni ją podatną. Na architekturze i386, kanarka jest przechowywana pod adresem gs:0x14, a na x86_64 pod adresem fs:0x28.

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

Gdy serwer WWW używa fork(), umożliwia atak brutalnej siły, aby zgadywać bajt kanarki po jednym bajcie. Jednak użycie execve() po fork() nadpisuje przestrzeń pamięci, unieważniając atak. vfork() pozwala procesowi potomnemu wykonywać się bez duplikacji, aż spróbuje zapisać, wtedy tworzony jest duplikat, oferując inny sposób tworzenia procesów i zarządzania pamięcią.

Długości

W binariach x64, ciasteczko kanarki to 0x8 bajtów qword. Pierwsze siedem bajtów jest losowe, a ostatni bajt to bajt null.

W binariach x86, ciasteczko kanarki to 0x4 bajty dword. Pierwsze trzy bajty są losowe, a ostatni bajt to bajt null.

Najmniej znaczący bajt obu kanarków to bajt null, ponieważ będzie pierwszy na stosie pochodzący z niższych adresów i dlatego funkcje czytające ciągi znaków zatrzymają się przed jego odczytaniem.

Ominięcia

Ujawnienie kanarki a następnie nadpisanie jej (np. przepełnienie bufora) jej własną wartością.

  • Jeśli kanarka jest klonowana w procesach potomnych, może być możliwe brutalne siłowe jej odczytanie po jednym bajcie:

pageBF Forked & Threaded Stack Canaries
  • Jeśli w binarnym pliku istnieje jakieś interesujące ujawnienie lub podatność na arbitralne odczytywanie, może być możliwe jej ujawnienie:

pagePrint Stack Canary
  • Nadpisanie wskaźników przechowywanych na stosie

Stos podatny na przepełnienie bufora może zawierać adresy do ciągów znaków lub funkcji, które można nadpisać, aby wykorzystać podatność bez konieczności dotarcia do kanarki stosu. Sprawdź:

pagePointer Redirecting
  • Modyfikacja zarówno kanarki głównej, jak i wątkowej

Przepełnienie bufora w funkcji wątkowej chronionej kanarką może być wykorzystane do modyfikacji kanarki głównej wątku. W rezultacie zastosowanie zabezpieczenia jest bezużyteczne, ponieważ sprawdzane są dwie kanarki, które są identyczne (choć zmodyfikowane).

Ponadto, przepełnienie bufora w funkcji wątkowej chronionej kanarką może być wykorzystane do modyfikacji kanarki głównej przechowywanej w TLS. Może to być możliwe, ponieważ można dotrzeć do pozycji pamięci, w której przechowywane jest TLS (a zatem kanarka) za pomocą przepełnienia bufora na stosie wątku. W rezultacie zastosowanie zabezpieczenia jest bezużyteczne, ponieważ sprawdzane są dwie kanarki, które są identyczne (choć zmodyfikowane). Ten atak jest przeprowadzany w opisie: 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, która wspomina, że zazwyczaj TLS jest przechowywane przez mmap i gdy tworzony jest stos wątku, jest on również generowany przez mmap, co może umożliwić przepełnienie, jak pokazano w poprzednim opisie.

  • Modyfikacja wpisu GOT __stack_chk_fail

Jeśli binarny plik ma Partial RELRO, można użyć arbitralnego zapisu do zmodyfikowania wpisu GOT __stack_chk_fail na funkcję-dummy, która nie blokuje programu, jeśli kanarka zostanie zmodyfikowana.

Ten atak jest przeprowadzany w opisie: https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/

Odnośniki

Zacznij od zera i zostań ekspertem AWS w dziedzinie hakerskiej dzięki htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Last updated