
Analizza CVE-2026-42945, un heap overrun nella riscrittura di NGINX, fornendo un rilevatore differenziale, un PoC DoS deterministico e una porta RCE accreditata con verifica.
Ricerca di sicurezza su CVE-2026-42945 (CVSS 4.0 9.2 CRITICO): un
heap buffer overrun nel motore di script di NGINX in cui una rewrite con
argomenti nella sostituzione (es. rewrite ^(.*) /new?c=1;) lascia il flag
is_args del motore impostato e mai azzerato — quindi qualsiasi cattura
($1) valutata successivamente in set/if viene copiata con escaping
URI in un buffer dimensionato per la lunghezza senza escaping.
Raggiungibile pre-autenticazione da qualsiasi client la cui URI di richiesta
contenga escape %XX o +.
Risultato (fase 1): un (vulnerabile 1.30.0 vs corretto 1.30.1, zero crash) più un (SIGSEGV, core dumped — la risposta viene prima servita completamente). Entrambi riprodotti contro build compilate dal sorgente al commit .
71d62c6Risultato (fase 2): un port accreditato dell'RCE del reporter —
esecuzione di system() come utente worker (nobody), riprodotto 3/3
esecuzioni pulite contro la build bloccata del reporter replicata in
lab/rce/. La tecnica di sfruttamento è di Leo Lin (DepthFirst); vedi
Cosa è originale qui vs lavoro precedente e la sezione Lavoro precedente
del writeup.
| Affermazione | Evidenza |
|---|---|
| Causa radice derivata dal commit di fix (non dai blog) | finding-sheet |
Il fix è una riga — e->is_args = 0; in ngx_http_script_regex_end_code() | commit 524977e (citato in writeup) |
| Rilevatore sicuro: oracolo vulnerabile vs corretto, zero crash | poc/diagnose.py — impronta di troncamento (/foo%25b vs /foo%bar) |
| Matrice di trigger: URI con virgolette/plus e caratteri escapabili nella cattura — entrambi richiesti | batteria di probe poc/diagnose.py incl. il controllo /a%41b |
| DoS deterministico del worker (SIGSEGV, core dumped, risposta servita prima) | poc/crash.py — il cambio di X-Worker-PID prova la morte del worker |
| Il 1.30.1 corretto sopravvive all'attacco identico | poc/crash.py --host 127.0.0.1:29544 — 3/3 round sopravvissuti |
| RCE (fase 2, tecnica del reporter, port accreditato) | exploit/rce.py — 3/3 esecuzioni, file di prova + uid=65534(nobody), worker exited on signal 11 dopo l'esecuzione |
# coppia differenziale: nginx 1.30.0 (:29543) + 1.30.1 (:29544) compilati dal sorgente
cd lab && docker compose up -d --build && cd ..
python3 poc/diagnose.py # oracolo sicuro — non crasha mai nessun worker
python3 poc/crash.py --host 127.0.0.1:29543 # 1.30.0: il worker muore con segnale 11, core dumped
python3 poc/crash.py --host 127.0.0.1:29544 # 1.30.1: sopravvive a ogni round
docker logs cve-42945-vuln 2>&1 | grep 'exited on signal' | tail -3
Fase 2 — RCE contro la build bloccata del reporter (rev dev nginx
98fc3bb7 = release-1.29.8-14, ASLR disabilitato dall'entrypoint bloccato):
docker compose -f lab/rce/docker-compose.yml up -d --build # :29545, minuti per la build
python3 exploit/rce.py \
--cmd 'echo pwned-by-cve-2026-42945 > /tmp/proof' --verify --expect pwned
docker compose -f lab/rce/docker-compose.yml exec nginx cat /tmp/proof
| Doc | Cosa contiene |
|---|---|
| docs/finding-sheet.md | Scheda tecnica di una pagina: versioni, CVSS, pattern di configurazione, condizioni di trigger, firme di rilevamento |
| docs/report-ptes.md | Report strutturato PTES (7 fasi), limitato a ciò che è stato effettivamente fatto |
| docs/research-writeup.md | La narrazione dell'indagine — archeologia del commit di fix, la sorpresa del troncamento, lezioni portabili, lavoro futuro |
La catena di ricerca della fase 1 è lavoro originale: l'oracolo
differenziale senza crash e la sua impronta di troncamento (il corpo
servito è la cattura ri-escappata troncata alla lunghezza grezza — la firma
visibile del disallineamento a due passaggi lunghezza/valore), la matrice
di trigger che prova entrambe le precondizioni necessarie, la spiegazione a
livello di sorgente del perché il passaggio di lunghezza non può vedere
is_args, e l'uccisione deterministica del worker post-risposta. Il bug
stesso, il pattern di configurazione vulnerabile e l'analisi del commit di
fix sono lavoro precedente del reporter e dell'upstream — Leo Lin
(DepthFirst) ha divulgato il problema e Roman Arutyunyan lo ha corretto;
vedi la sezione Lavoro precedente del writeup e
DepthFirst Disclosures — Nginx-Rift,
albero CVE-2026-42945.
La fase 2 (RCE) è un port dell'exploit pubblicato dal reporter, non una
catena indipendente: il feng shui heap cross-richiesta che fa atterrare
l'overrun sul puntatore cleanup del pool di una richiesta adiacente, lo
spray fittizio di ngx_pool_cleanup_t tramite corpi POST trattenuti, il
redirect del dispatch di cleanup a system() di libc, la geometria
dell'overflow (349 A + 969 + + 6 byte target), le costanti base/offset
senza ASLR e la build bloccata in lab/rce/ (il loro env/) sono tutti
design di Leo Lin, riprodotti con credito in exploit/rce.py. Nostro nella
fase 2: il port stesso — le convenzioni CLI/logging/verifica di questo
repo, la scoperta candidata tramite scansione heap live e l'autorilevamento
della base (le loro costanti statiche dipendono dal kernel; vedi il
docstring dell'exploit), il listener reverse-shell della stdlib e
l'evidenza di verifica.
Questo repo condivide la sua metodologia con CVE-2026-42533 — NGINX Pre-Auth Heap Overflow: Analysis & RCE (repo gemello): la stessa classe di bug a due passaggi lunghezza/valore nel motore di script di nginx, portata lì attraverso una catena RCE completa pre-autenticazione. Quella catena ha delimitato il tetto plausibile per questo bug; la fase 2 di questo repo raggiunge lo stesso tetto qui — come port accreditato della tecnica del reporter, non una catena indipendente.
docs/ finding sheet · report PTES · writeup di ricerca
poc/ diagnose.py (oracolo differenziale sicuro) · crash.py (DoS deterministico)
exploit/ rce.py — port accreditato della catena system() del reporter
lab/ Dockerfile (nginx dal sorgente, -g -O0) + coppia differenziale compose
lab/nginx/ vulnerable.conf — la config PoC dal commit di fix
lab/rce/ ambiente RCE bloccato del reporter (il loro env/, il nostro mapping del port)
524977e7c534
"Rewrite: fixed escaping and possible buffer overrun" (Roman Arutyunyan) — rilasciato in nginx 1.30.1CVE-2026-42945 (lavoro precedente del reporter; Leo Lin)Artefatto di ricerca educativa. Eseguire solo contro sistemi di tua proprietà o per cui sei esplicitamente autorizzato a testare. La vulnerabilità è corretta — aggiorna nginx a ≥ 1.30.1.