
Analiza CVE-2026-42945, un desbordamiento de montón en la reescritura de NGINX, proporcionando un detector diferencial, un PoC de DoS determinista y un puerto de RCE acreditado con verificación.
Investigación de seguridad sobre CVE-2026-42945 (CVSS 4.0 9.2 CRÍTICO): un
desbordamiento de búfer en el montón en el motor de scripts de NGINX donde una
rewrite con argumentos en la
sustitución (p. ej. rewrite ^(.*) /new?c=1;) deja el indicador
is_args del motor establecido y nunca se limpia — por lo que cualquier captura ($1) evaluada
posteriormente en set/if se copia con escape de URI en un búfer
que se dimensionó para la longitud sin escape. Alcanzable pre-autenticación por cualquier
cliente cuya URI de solicitud contenga escapes %XX o +.
Resultado (fase 1): un detector diferencial seguro (vulnerable
1.30.0 vs corregido 1.30.1, cero fallos) además de un DoS determinista del worker
(SIGSEGV, volcado de núcleo — la respuesta se sirve completamente primero). Ambos
reproducidos contra compilaciones construidas desde el código fuente en el commit 71d62c6.
Resultado (fase 2): un puerto acreditado del RCE del informante —
ejecución de system() como el usuario worker (nobody), reproducido 3/3 ejecuciones
limpias contra la compilación fijada del informante replicada en lab/rce/.
La técnica de explotación es de Leo Lin (DepthFirst); consulte
Qué es original aquí frente al trabajo previo y la sección Trabajo previo del informe.
| Afirmación | Evidencia |
|---|---|
| Causa raíz derivada del commit de corrección (no de blogs) | hoja-de-hallazgos |
La corrección es de una línea — e->is_args = 0; en ngx_http_script_regex_end_code() | commit 524977e (citado en informe) |
| Detector seguro: oráculo vulnerable vs corregido, cero fallos | poc/diagnose.py — huella de truncamiento (/foo%25b vs /foo%bar) |
| Matriz de activación: URI con comillas/más y caracteres escapables en la captura — ambos requeridos | batería de sondas de poc/diagnose.py incl. el control /a%41b |
| DoS determinista del worker (SIGSEGV, volcado de núcleo, respuesta servida primero) | poc/crash.py — el cambio de X-Worker-PID prueba la muerte del worker |
| El corregido 1.30.1 sobrevive al ataque idéntico | poc/crash.py --host 127.0.0.1:29544 — 3/3 rondas sobrevividas |
| RCE (fase 2, técnica del informante, puerto acreditado) | exploit/rce.py — 3/3 ejecuciones, archivo de prueba + uid=65534(nobody), workers exited on signal 11 después de la ejecución |
# par diferencial: nginx 1.30.0 (:29543) + 1.30.1 (:29544) compilados desde el código fuente
cd lab && docker compose up -d --build && cd ..
python3 poc/diagnose.py # oráculo seguro — nunca falla ningún worker
python3 poc/crash.py --host 127.0.0.1:29543 # 1.30.0: el worker muere con señal 11, volcado de núcleo
python3 poc/crash.py --host 127.0.0.1:29544 # 1.30.1: sobrevive a cada ronda
docker logs cve-42945-vuln 2>&1 | grep 'exited on signal' | tail -3
Fase 2 — RCE contra la compilación fijada del informante (rev de desarrollo de nginx
98fc3bb7 = release-1.29.8-14, ASLR deshabilitado por el punto de entrada fijado):
docker compose -f lab/rce/docker-compose.yml up -d --build # :29545, minutos de compilación
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
| Documento | Qué es |
|---|---|
| docs/finding-sheet.md | Hoja de datos de una página: versiones, CVSS, patrón de configuración, condiciones de activación, firmas de detección |
| docs/report-ptes.md | Informe estructurado según PTES (7 fases), limitado a lo que realmente se hizo |
| docs/research-writeup.md | La narrativa de la investigación — arqueología del commit de corrección, la sorpresa del truncamiento, lecciones portables, trabajo futuro |
La cadena de investigación de la fase 1 es trabajo original: el oráculo
diferencial sin fallos y su huella de truncamiento (el cuerpo servido es la
captura re-escapada truncada a la longitud bruta — la firma visible del
desajuste de dos pasadas longitud/valor), la matriz de activación que prueba ambas
precondiciones necesarias, la explicación a nivel de código fuente de por qué la pasada
de longitud no puede ver is_args, y la muerte determinista del worker posterior a la
respuesta. El error en sí, el patrón de configuración vulnerable y el análisis del
commit de corrección son trabajo previo del informante y del proyecto upstream — Leo Lin
(DepthFirst) divulgó el problema y Roman Arutyunyan lo corrigió; consulte la
sección Trabajo previo del informe y
DepthFirst Disclosures — Nginx-Rift,
árbol CVE-2026-42945.
La fase 2 (RCE) es un puerto del exploit publicado del informante, no una
cadena independiente: el feng shui de montón entre solicitudes que coloca el desbordamiento
en el puntero cleanup del pool de una solicitud adyacente, el spray de
ngx_pool_cleanup_t falso mediante cuerpos POST retenidos, el redireccionamiento de
despacho de limpieza a system() de libc, la geometría del desbordamiento (349 A + 969 + +
6 bytes objetivo), las constantes de base/desplazamiento sin ASLR y la compilación fijada
en lab/rce/ (su env/) son todo diseño de Leo Lin, reproducido con
crédito en exploit/rce.py. Lo nuestro en la fase 2: el puerto en sí — las
convenciones de CLI/registro/verificación de este repositorio, el descubrimiento de candidatos
mediante escaneo de montón en vivo y la autodetección de base (sus constantes estáticas
dependen del kernel; consulte el docstring del exploit), el listener de shell inversa
de la biblioteca estándar y la evidencia de verificación.
Este repositorio comparte su metodología con CVE-2026-42533 — Desbordamiento de montón pre-autenticación de NGINX: Análisis y RCE (repositorio hermano): la misma clase de error de dos pasadas longitud/valor en el motor de scripts de nginx, llevada allí a través de una cadena RCE completa pre-autenticación. Esa cadena delimitó el techo plausible para este error; la fase 2 de este repositorio alcanza el mismo techo aquí — como un puerto acreditado de la técnica del informante, no una cadena independiente.
docs/ hoja de hallazgos · informe PTES · informe de investigación
poc/ diagnose.py (oráculo diferencial seguro) · crash.py (DoS determinista)
exploit/ rce.py — puerto acreditado de la cadena system() del informante
lab/ Dockerfile (nginx desde el código fuente, -g -O0) + par diferencial de compose
lab/nginx/ vulnerable.conf — la configuración PoC del commit de corrección
lab/rce/ entorno RCE fijado del informante (su env/, nuestro mapeo del puerto)
524977e7c534
"Rewrite: fixed escaping and possible buffer overrun" (Roman Arutyunyan) — publicado en nginx 1.30.1CVE-2026-42945 (trabajo previo del informante; Leo Lin)Artefacto de investigación educativa. Ejecútelo únicamente contra sistemas que posea o para los que tenga autorización explícita de prueba. La vulnerabilidad está parcheada — actualice nginx a ≥ 1.30.1.