# Stack Canaries {{#include ../../../banners/hacktricks-training.md}} ## **StackGuard y StackShield** **StackGuard** inserta un valor especial conocido como **canary** antes del **EIP (Extended Instruction Pointer)**, específicamente `0x000aff0d` (que representa null, nueva línea, EOF, retorno de carro) para proteger contra desbordamientos de búfer. Sin embargo, funciones como `recv()`, `memcpy()`, `read()`, y `bcopy()` siguen siendo vulnerables, y no protege el **EBP (Base Pointer)**. **StackShield** adopta un enfoque más sofisticado que StackGuard al mantener una **Global Return Stack**, que almacena todas las direcciones de retorno (**EIPs**). Esta configuración asegura que cualquier desbordamiento no cause daño, ya que permite una comparación entre las direcciones de retorno almacenadas y las reales para detectar ocurrencias de desbordamiento. Además, StackShield puede verificar la dirección de retorno contra un valor límite para detectar si el **EIP** apunta fuera del espacio de datos esperado. Sin embargo, esta protección puede ser eludida a través de técnicas como Return-to-libc, ROP (Return-Oriented Programming), o ret2ret, lo que indica que StackShield tampoco protege las variables locales. ## **Stack Smash Protector (ProPolice) `-fstack-protector`:** Este mecanismo coloca un **canary** antes del **EBP**, y reorganiza las variables locales para posicionar los búferes en direcciones de memoria más altas, evitando que sobrescriban otras variables. También copia de manera segura los argumentos pasados en la pila por encima de las variables locales y utiliza estas copias como argumentos. Sin embargo, no protege arreglos con menos de 8 elementos o búferes dentro de la estructura de un usuario. El **canary** es un número aleatorio derivado de `/dev/urandom` o un valor predeterminado de `0xff0a0000`. Se almacena en **TLS (Thread Local Storage)**, permitiendo que los espacios de memoria compartidos entre hilos tengan variables globales o estáticas específicas del hilo. Estas variables se copian inicialmente del proceso padre, y los procesos hijos pueden alterar sus datos sin afectar al padre o a los hermanos. Sin embargo, si se utiliza un **`fork()` sin crear un nuevo canary, todos los procesos (padre e hijos) comparten el mismo canary**, lo que lo hace vulnerable. En la arquitectura **i386**, el canary se almacena en `gs:0x14`, y en **x86_64**, en `fs:0x28`. Esta protección local identifica funciones con búferes vulnerables a ataques e inyecta código al inicio de estas funciones para colocar el canary, y al final para verificar su integridad. Cuando un servidor web utiliza `fork()`, permite un ataque de fuerza bruta para adivinar el byte del canary byte por byte. Sin embargo, usar `execve()` después de `fork()` sobrescribe el espacio de memoria, negando el ataque. `vfork()` permite que el proceso hijo se ejecute sin duplicación hasta que intente escribir, momento en el cual se crea una duplicación, ofreciendo un enfoque diferente para la creación de procesos y el manejo de memoria. ### Longitudes En binarios `x64`, la cookie del canary es un **`0x8`** byte qword. Los **primeros siete bytes son aleatorios** y el último byte es un **byte nulo.** En binarios `x86`, la cookie del canary es un **`0x4`** byte dword. Los **primeros tres bytes son aleatorios** y el último byte es un **byte nulo.** > [!CAUTION] > El byte menos significativo de ambos canaries es un byte nulo porque será el primero en la pila proveniente de direcciones más bajas y, por lo tanto, **las funciones que leen cadenas se detendrán antes de leerlo**. ## Bypasses **Filtrar el canary** y luego sobrescribirlo (por ejemplo, desbordamiento de búfer) con su propio valor. - Si el **canary se bifurca en procesos hijos**, podría ser posible **forzarlo** un byte a la vez: {{#ref}} bf-forked-stack-canaries.md {{#endref}} - Si hay alguna **vulnerabilidad de filtrado o lectura arbitraria** interesante en el binario, podría ser posible filtrarlo: {{#ref}} print-stack-canary.md {{#endref}} - **Sobrescribiendo punteros almacenados en la pila** La pila vulnerable a un desbordamiento de pila podría **contener direcciones a cadenas o funciones que pueden ser sobrescritas** para explotar la vulnerabilidad sin necesidad de alcanzar el canary de la pila. Ver: {{#ref}} ../../stack-overflow/pointer-redirecting.md {{#endref}} - **Modificando tanto el canary maestro como el de hilo** Un desbordamiento de búfer en una función con hilos protegida con canary puede ser utilizado para **modificar el canary maestro del hilo**. Como resultado, la mitigación es inútil porque la verificación se utiliza con dos canaries que son iguales (aunque modificados). Además, un desbordamiento de búfer en una función con hilos protegida con canary podría ser utilizado para **modificar el canary maestro almacenado en el TLS**. Esto se debe a que podría ser posible alcanzar la posición de memoria donde se almacena el TLS (y, por lo tanto, el canary) a través de un **bof en la pila** de un hilo.\ Como resultado, la mitigación es inútil porque la verificación se utiliza con dos canaries que son iguales (aunque modificados).\ Este ataque se realiza en el 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) Ver también la presentación de [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) que menciona que generalmente el **TLS** se almacena mediante **`mmap`** y cuando se crea una **pila** de **hilo** también se genera mediante `mmap`, lo que podría permitir el desbordamiento como se mostró en el writeup anterior. - **Modificar la entrada GOT de `__stack_chk_fail`** Si el binario tiene Partial RELRO, entonces puedes usar una escritura arbitraria para modificar la **entrada GOT de `__stack_chk_fail`** para que sea una función ficticia que no bloquee el programa si el canary se modifica. Este ataque se realiza en el writeup: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/) ## Referencias - [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}}