# Stack Canaries {{#include ../../../banners/hacktricks-training.md}} ## **StackGuard e StackShield** **StackGuard** inserisce un valore speciale noto come **canary** prima dell'**EIP (Extended Instruction Pointer)**, specificamente `0x000aff0d` (che rappresenta null, newline, EOF, carriage return) per proteggere contro i buffer overflow. Tuttavia, funzioni come `recv()`, `memcpy()`, `read()`, e `bcopy()` rimangono vulnerabili, e non protegge l'**EBP (Base Pointer)**. **StackShield** adotta un approccio più sofisticato rispetto a StackGuard mantenendo uno **Global Return Stack**, che memorizza tutti gli indirizzi di ritorno (**EIPs**). Questa configurazione garantisce che qualsiasi overflow non causi danni, poiché consente un confronto tra gli indirizzi di ritorno memorizzati e quelli effettivi per rilevare le occorrenze di overflow. Inoltre, StackShield può controllare l'indirizzo di ritorno rispetto a un valore di confine per rilevare se l'**EIP** punta al di fuori dello spazio dati previsto. Tuttavia, questa protezione può essere elusa attraverso tecniche come Return-to-libc, ROP (Return-Oriented Programming), o ret2ret, indicando che StackShield non protegge nemmeno le variabili locali. ## **Stack Smash Protector (ProPolice) `-fstack-protector`:** Questo meccanismo posiziona un **canary** prima dell'**EBP**, e riorganizza le variabili locali per posizionare i buffer a indirizzi di memoria più alti, impedendo loro di sovrascrivere altre variabili. Copia anche in modo sicuro gli argomenti passati sullo stack sopra le variabili locali e utilizza queste copie come argomenti. Tuttavia, non protegge gli array con meno di 8 elementi o i buffer all'interno di una struttura utente. Il **canary** è un numero casuale derivato da `/dev/urandom` o un valore predefinito di `0xff0a0000`. È memorizzato in **TLS (Thread Local Storage)**, consentendo spazi di memoria condivisi tra i thread di avere variabili globali o statiche specifiche per il thread. Queste variabili vengono inizialmente copiate dal processo padre, e i processi figli possono alterare i loro dati senza influenzare il padre o i fratelli. Tuttavia, se un **`fork()` viene utilizzato senza creare un nuovo canary, tutti i processi (padre e figli) condividono lo stesso canary**, rendendolo vulnerabile. Sull'architettura **i386**, il canary è memorizzato in `gs:0x14`, e su **x86_64**, in `fs:0x28`. Questa protezione locale identifica le funzioni con buffer vulnerabili ad attacchi e inietta codice all'inizio di queste funzioni per posizionare il canary, e alla fine per verificarne l'integrità. Quando un server web utilizza `fork()`, consente un attacco di forza bruta per indovinare il byte del canary byte per byte. Tuttavia, utilizzare `execve()` dopo `fork()` sovrascrive lo spazio di memoria, annullando l'attacco. `vfork()` consente al processo figlio di eseguire senza duplicazione fino a quando non tenta di scrivere, momento in cui viene creata una duplicazione, offrendo un approccio diverso alla creazione di processi e alla gestione della memoria. ### Lunghezze Nei binari `x64`, il cookie del canary è un **`0x8`** byte qword. I **primi sette byte sono casuali** e l'ultimo byte è un **byte nullo.** Nei binari `x86`, il cookie del canary è un **`0x4`** byte dword. I **primi tre byte sono casuali** e l'ultimo byte è un **byte nullo.** > [!CAUTION] > Il byte meno significativo di entrambi i canary è un byte nullo perché sarà il primo nello stack proveniente da indirizzi più bassi e quindi **le funzioni che leggono stringhe si fermeranno prima di leggerlo**. ## Bypass **Fuggire il canary** e poi sovrascriverlo (ad es. buffer overflow) con il proprio valore. - Se il **canary è forkato nei processi figli** potrebbe essere possibile **brute-forzarlo** un byte alla volta: {{#ref}} bf-forked-stack-canaries.md {{#endref}} - Se c'è qualche interessante **fuga o vulnerabilità di lettura arbitraria** nel binario potrebbe essere possibile fugare: {{#ref}} print-stack-canary.md {{#endref}} - **Sovrascrivere i puntatori memorizzati nello stack** Lo stack vulnerabile a un overflow dello stack potrebbe **contenere indirizzi a stringhe o funzioni che possono essere sovrascritti** per sfruttare la vulnerabilità senza dover raggiungere il canary dello stack. Controlla: {{#ref}} ../../stack-overflow/pointer-redirecting.md {{#endref}} - **Modificare sia il canary master che quello del thread** Un buffer **overflow in una funzione thread** protetta con canary può essere utilizzato per **modificare il canary master del thread**. Di conseguenza, la mitigazione è inutile perché il controllo viene effettuato con due canary che sono gli stessi (anche se modificati). Inoltre, un buffer **overflow in una funzione thread** protetta con canary potrebbe essere utilizzato per **modificare il canary master memorizzato nel TLS**. Questo perché, potrebbe essere possibile raggiungere la posizione di memoria in cui è memorizzato il TLS (e quindi, il canary) tramite un **bof nello stack** di un thread.\ Di conseguenza, la mitigazione è inutile perché il controllo viene effettuato con due canary che sono gli stessi (anche se modificati).\ Questo attacco è descritto nel writeup: [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) Controlla anche la presentazione di [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) che menziona che di solito il **TLS** è memorizzato da **`mmap`** e quando viene creato uno **stack** di **thread** viene generato anch'esso da `mmap`, il che potrebbe consentire l'overflow come mostrato nel precedente writeup. - **Modificare l'entry GOT di `__stack_chk_fail`** Se il binario ha Partial RELRO, allora puoi utilizzare una scrittura arbitraria per modificare l'**entry GOT di `__stack_chk_fail`** per essere una funzione fittizia che non blocca il programma se il canary viene modificato. Questo attacco è descritto nel writeup: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/) ## Riferimenti - [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}}