Stack Canaries
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
StackGuard umetne posebnu vrednost poznatu kao canary pre EIP (Extended Instruction Pointer), specifično 0x000aff0d
(koji predstavlja null, newline, EOF, carriage return) kako bi se zaštitio od buffer overflow-a. Međutim, funkcije kao što su recv()
, memcpy()
, read()
, i bcopy()
ostaju ranjive, i ne štiti EBP (Base Pointer).
StackShield koristi sofisticiraniji pristup od StackGuard-a održavajući Global Return Stack, koji čuva sve adrese povratka (EIPs). Ova postavka osigurava da bilo kakvo prelivanje ne uzrokuje štetu, jer omogućava poređenje između sačuvanih i stvarnih adresa povratka kako bi se otkrile pojave prelivanja. Pored toga, StackShield može proveriti adresu povratka u odnosu na graničnu vrednost kako bi otkrio da li EIP pokazuje izvan očekivanog prostora podataka. Međutim, ova zaštita može biti zaobiđena tehnikama kao što su Return-to-libc, ROP (Return-Oriented Programming), ili ret2ret, što ukazuje da StackShield takođe ne štiti lokalne promenljive.
-fstack-protector
:Omekšavanje stavlja canary pre EBP, i reorganizuje lokalne promenljive kako bi pozicionirao bafer na višim adresama memorije, sprečavajući ih da prepisuju druge promenljive. Takođe sigurno kopira argumente prosleđene na steku iznad lokalnih promenljivih i koristi te kopije kao argumente. Međutim, ne štiti nizove sa manje od 8 elemenata ili baferima unutar korisničke strukture.
Canary je nasumičan broj dobijen iz /dev/urandom
ili podrazumevana vrednost 0xff0a0000
. Čuva se u TLS (Thread Local Storage), omogućavajući deljenje memorijskih prostora između niti da imaju globalne ili statičke promenljive specifične za nit. Ove promenljive se inicijalno kopiraju iz roditeljskog procesa, a dečiji procesi mogu menjati svoje podatke bez uticaja na roditelja ili braću i sestre. Ipak, ako se fork()
koristi bez kreiranja novog canary-a, svi procesi (roditelj i deca) dele isti canary, što ga čini ranjivim. Na i386 arhitekturi, canary se čuva na gs:0x14
, a na x86_64, na fs:0x28
.
Ova lokalna zaštita identifikuje funkcije sa baferima ranjivim na napade i injektuje kod na početku ovih funkcija kako bi postavio canary, i na kraju da proveri njegovu integritet.
Kada web server koristi fork()
, omogućava napad silom da pogodi canary bajt po bajt. Međutim, korišćenje execve()
nakon fork()
prepisuje memorijski prostor, poništavajući napad. vfork()
omogućava dečijem procesu da izvrši bez dupliciranja dok ne pokuša da piše, u tom trenutku se kreira duplikat, nudeći drugačiji pristup kreaciji procesa i upravljanju memorijom.
U x64
binarnim datotekama, canary cookie je 0x8
bajt qword. Prvih sedam bajtova su nasumični i poslednji bajt je null bajt.
U x86
binarnim datotekama, canary cookie je 0x4
bajt dword. Prva tri bajta su nasumična i poslednji bajt je null bajt.
Najmanje značajan bajt oba canary-a je null bajt jer će biti prvi na steku dolazeći iz nižih adresa i stoga funkcije koje čitaju stringove će stati pre nego što ga pročitaju.
Icuranje canary-a i zatim njegovo prepisivanje (npr. buffer overflow) sa sopstvenom vrednošću.
Ako se canary fork-uje u dečijim procesima može biti moguće da se brute-force jedan bajt po jedan:
Ako postoji neka zanimljiva leak ili ranjivost u čitanju u bineru može biti moguće da se iscuri:
Prepisivanje pokazivača sačuvanih na steku
Stek ranjiv na stack overflow može sadržati adrese do stringova ili funkcija koje mogu biti prepisane kako bi se iskoristila ranjivost bez potrebe da se dođe do stack canary-a. Proverite:
Pointer RedirectingModifikovanje i master i thread canary
Buffer overflow u funkciji sa nitima zaštićenoj canary-em može se koristiti za modifikovanje master canary-a niti. Kao rezultat, mitigacija je beskorisna jer se provera koristi sa dva canary-a koja su ista (iako modifikovana).
Pored toga, buffer overflow u funkciji sa nitima zaštićenoj canary-em može se koristiti za modifikovanje master canary-a sačuvanog u TLS-u. To je zato što, može biti moguće doći do memorijske pozicije gde se TLS čuva (i stoga, canary) putem bof-a na steku niti. Kao rezultat, mitigacija je beskorisna jer se provera koristi sa dva canary-a koja su ista (iako modifikovana). Ovaj napad je izveden u pisanju: http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads
Proverite takođe prezentaciju https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015 koja pominje da se obično TLS čuva putem mmap
i kada se stack niti kreira takođe se generiše putem mmap
, što može omogućiti prelivanje kao što je prikazano u prethodnom pisanju.
Modifikujte GOT unos __stack_chk_fail
Ako binarni fajl ima Partial RELRO, onda možete koristiti proizvoljno pisanje da modifikujete GOT unos __stack_chk_fail
da bude dummy funkcija koja ne blokira program ako se canary modifikuje.
Ovaj napad je izveden u pisanju: https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)