99 lines
5.4 KiB
Markdown

# Stack Overflow
{{#include ../../banners/hacktricks-training.md}}
## Qué es un Stack Overflow
Un **stack overflow** es una vulnerabilidad que ocurre cuando un programa escribe más datos en la pila de los que se le ha asignado para contener. Este exceso de datos **sobrescribirá el espacio de memoria adyacente**, lo que llevará a la corrupción de datos válidos, interrupción del flujo de control y potencialmente a la ejecución de código malicioso. Este problema a menudo surge debido al uso de funciones inseguras que no realizan comprobaciones de límites en la entrada.
El principal problema de esta sobrescritura es que el **puntero de instrucción guardado (EIP/RIP)** y el **puntero base guardado (EBP/RBP)** para regresar a la función anterior están **almacenados en la pila**. Por lo tanto, un atacante podrá sobrescribir esos y **controlar el flujo de ejecución del programa**.
La vulnerabilidad generalmente surge porque una función **copia dentro de la pila más bytes de los que se le han asignado**, por lo que puede sobrescribir otras partes de la pila.
Algunas funciones comunes vulnerables a esto son: **`strcpy`, `strcat`, `sprintf`, `gets`**... Además, funciones como **`fgets`**, **`read` & `memcpy`** que toman un **argumento de longitud**, podrían usarse de manera vulnerable si la longitud especificada es mayor que la asignada.
Por ejemplo, las siguientes funciones podrían ser vulnerables:
```c
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}
```
### Encontrando los offsets de Stack Overflows
La forma más común de encontrar desbordamientos de pila es dar una entrada muy grande de `A`s (por ejemplo, `python3 -c 'print("A"*1000)'`) y esperar un `Segmentation Fault` que indique que se intentó acceder a la **dirección `0x41414141`**.
Además, una vez que encuentres que hay una vulnerabilidad de Stack Overflow, necesitarás encontrar el offset hasta que sea posible **sobrescribir la dirección de retorno**, para esto se suele usar una **secuencia de De Bruijn.** La cual, para un alfabeto dado de tamaño _k_ y subsecuencias de longitud _n_, es una **secuencia cíclica en la que cada posible subsecuencia de longitud _n_ aparece exactamente una vez** como una subsecuencia contigua.
De esta manera, en lugar de necesitar averiguar manualmente qué offset se necesita para controlar el EIP, es posible usar como relleno una de estas secuencias y luego encontrar el offset de los bytes que terminaron sobrescribiéndola.
Es posible usar **pwntools** para esto:
```python
from pwn import *
# Generate a De Bruijn sequence of length 1000 with an alphabet size of 256 (byte values)
pattern = cyclic(1000)
# This is an example value that you'd have found in the EIP/IP register upon crash
eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}")
```
o **GEF**:
```bash
#Patterns
pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp
```
## Explotación de desbordamientos de pila
Durante un desbordamiento (suponiendo que el tamaño del desbordamiento sea lo suficientemente grande) podrás **sobrescribir** valores de variables locales dentro de la pila hasta alcanzar el **EBP/RBP y EIP/RIP guardados (o incluso más)**.\
La forma más común de abusar de este tipo de vulnerabilidad es **modificando la dirección de retorno** para que cuando la función termine, el **flujo de control se redirija a donde el usuario especificó** en este puntero.
Sin embargo, en otros escenarios, tal vez solo **sobrescribir algunos valores de variables en la pila** podría ser suficiente para la explotación (como en desafíos CTF fáciles).
### Ret2win
En este tipo de desafíos CTF, hay una **función** **dentro** del binario que **nunca se llama** y que **necesitas llamar para ganar**. Para estos desafíos solo necesitas encontrar el **desplazamiento para sobrescribir la dirección de retorno** y **encontrar la dirección de la función** a llamar (generalmente [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) estaría deshabilitado) para que cuando la función vulnerable regrese, se llame a la función oculta:
{{#ref}}
ret2win/
{{#endref}}
### Shellcode en la pila
En este escenario, el atacante podría colocar un shellcode en la pila y abusar del EIP/RIP controlado para saltar al shellcode y ejecutar código arbitrario:
{{#ref}}
stack-shellcode/
{{#endref}}
### Técnicas ROP y Ret2...
Esta técnica es el marco fundamental para eludir la principal protección de la técnica anterior: **Pila no ejecutable (NX)**. Y permite realizar varias otras técnicas (ret2lib, ret2syscall...) que terminarán ejecutando comandos arbitrarios al abusar de instrucciones existentes en el binario:
{{#ref}}
../rop-return-oriented-programing/
{{#endref}}
## Desbordamientos de heap
Un desbordamiento no siempre va a estar en la pila, también podría estar en el **heap**, por ejemplo:
{{#ref}}
../libc-heap/heap-overflow.md
{{#endref}}
## Tipos de protecciones
Hay varias protecciones que intentan prevenir la explotación de vulnerabilidades, consúltalas en:
{{#ref}}
../common-binary-protections-and-bypasses/
{{#endref}}
{{#include ../../banners/hacktricks-training.md}}