77 lines
6.7 KiB
Markdown

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