mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
99 lines
5.4 KiB
Markdown
99 lines
5.4 KiB
Markdown
# Stack Overflow
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|
|
|
|
## Cos'è uno Stack Overflow
|
|
|
|
Un **stack overflow** è una vulnerabilità che si verifica quando un programma scrive più dati nello stack di quanti ne siano allocati per contenerli. Questi dati in eccesso **sovrascriveranno lo spazio di memoria adiacente**, portando alla corruzione di dati validi, alla disruption del flusso di controllo e potenzialmente all'esecuzione di codice malevolo. Questo problema si verifica spesso a causa dell'uso di funzioni non sicure che non eseguono il controllo dei limiti sugli input.
|
|
|
|
Il problema principale di questa sovrascrittura è che il **puntatore di istruzione salvato (EIP/RIP)** e il **puntatore di base salvato (EBP/RBP)** per tornare alla funzione precedente sono **memorizzati nello stack**. Pertanto, un attaccante sarà in grado di sovrascrivere questi e **controllare il flusso di esecuzione del programma**.
|
|
|
|
La vulnerabilità di solito si verifica perché una funzione **copia nello stack più byte della quantità allocata per essa**, riuscendo quindi a sovrascrivere altre parti dello stack.
|
|
|
|
Alcune funzioni comuni vulnerabili a questo sono: **`strcpy`, `strcat`, `sprintf`, `gets`**... Inoltre, funzioni come **`fgets`**, **`read` & `memcpy`** che prendono un **argomento di lunghezza**, potrebbero essere utilizzate in modo vulnerabile se la lunghezza specificata è maggiore di quella allocata.
|
|
|
|
Ad esempio, le seguenti funzioni potrebbero essere vulnerabili:
|
|
```c
|
|
void vulnerable() {
|
|
char buffer[128];
|
|
printf("Enter some text: ");
|
|
gets(buffer); // This is where the vulnerability lies
|
|
printf("You entered: %s\n", buffer);
|
|
}
|
|
```
|
|
### Trovare gli offset degli Stack Overflow
|
|
|
|
Il modo più comune per trovare gli stack overflow è fornire un input molto grande di `A`s (ad esempio `python3 -c 'print("A"*1000)'`) e aspettarsi un `Segmentation Fault` che indica che l'**indirizzo `0x41414141` è stato tentato di essere accesso**.
|
|
|
|
Inoltre, una volta trovata la vulnerabilità di Stack Overflow, sarà necessario trovare l'offset fino a quando non sarà possibile **sovrascrivere l'indirizzo di ritorno**, per questo si usa solitamente una **sequenza di De Bruijn.** Che per un dato alfabeto di dimensione _k_ e sottosequenze di lunghezza _n_ è una **sequenza ciclica in cui ogni possibile sottosequenza di lunghezza \_n**\_\*\* appare esattamente una volta\*\* come sottosequenza contigua.
|
|
|
|
In questo modo, invece di dover capire manualmente quale offset è necessario per controllare l'EIP, è possibile utilizzare come padding una di queste sequenze e poi trovare l'offset dei byte che hanno finito per sovrascriverlo.
|
|
|
|
È possibile utilizzare **pwntools** per questo:
|
|
```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
|
|
```
|
|
## Sfruttamento degli Stack Overflow
|
|
|
|
Durante un overflow (supponendo che la dimensione dell'overflow sia abbastanza grande) sarai in grado di **sovrascrivere** i valori delle variabili locali all'interno dello stack fino a raggiungere il **EBP/RBP e EIP/RIP salvati (o anche di più)**.\
|
|
Il modo più comune per abusare di questo tipo di vulnerabilità è **modificare l'indirizzo di ritorno** in modo che, quando la funzione termina, il **flusso di controllo venga reindirizzato ovunque l'utente abbia specificato** in questo puntatore.
|
|
|
|
Tuttavia, in altri scenari, potrebbe essere sufficiente **sovrascrivere alcuni valori delle variabili nello stack** per l'exploitation (come in semplici sfide CTF).
|
|
|
|
### Ret2win
|
|
|
|
In questo tipo di sfide CTF, c'è una **funzione** **all'interno** del binario che **non viene mai chiamata** e che **devi chiamare per vincere**. Per queste sfide devi solo trovare l'**offset per sovrascrivere l'indirizzo di ritorno** e **trovare l'indirizzo della funzione** da chiamare (di solito [**ASLR**](../common-binary-protections-and-bypasses/aslr/) sarebbe disabilitato) in modo che, quando la funzione vulnerabile restituisce, la funzione nascosta venga chiamata:
|
|
|
|
{{#ref}}
|
|
ret2win/
|
|
{{#endref}}
|
|
|
|
### Stack Shellcode
|
|
|
|
In questo scenario, l'attaccante potrebbe posizionare uno shellcode nello stack e abusare dell'EIP/RIP controllato per saltare allo shellcode ed eseguire codice arbitrario:
|
|
|
|
{{#ref}}
|
|
stack-shellcode/
|
|
{{#endref}}
|
|
|
|
### Tecniche ROP & Ret2...
|
|
|
|
Questa tecnica è il framework fondamentale per bypassare la principale protezione della tecnica precedente: **Stack non eseguibile (NX)**. E consente di eseguire diverse altre tecniche (ret2lib, ret2syscall...) che porteranno all'esecuzione di comandi arbitrari abusando delle istruzioni esistenti nel binario:
|
|
|
|
{{#ref}}
|
|
../rop-return-oriented-programing/
|
|
{{#endref}}
|
|
|
|
## Heap Overflows
|
|
|
|
Un overflow non sarà sempre nello stack, potrebbe anche essere nell'**heap**, per esempio:
|
|
|
|
{{#ref}}
|
|
../libc-heap/heap-overflow.md
|
|
{{#endref}}
|
|
|
|
## Tipi di protezioni
|
|
|
|
Ci sono diverse protezioni che cercano di prevenire l'exploitation delle vulnerabilità, controllale in:
|
|
|
|
{{#ref}}
|
|
../common-binary-protections-and-bypasses/
|
|
{{#endref}}
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|