
Laboratorio privado de Nginx Rift ASLR, cadena de exploits y grabaciones de demostración
Prueba de concepto de RCE para CVE-2026-42945, un desbordamiento crítico de búfer en el montón en ngx_http_rewrite_module de NGINX introducido en 2008. El error permite ejecución remota de código no autenticada contra servidores que utilizan directivas rewrite y set.
Esta bifurcación extiende el PoC original con una cadena de bypass de ASLR que combina el desbordamiento de NGINX con una primitiva común de LFI/lectura arbitraria de archivos en el mismo host. La primitiva de lectura de archivos se utiliza para recuperar los mapas del worker de nginx, libc y /proc/<worker>/mem en vivo, y luego derivar la dirección de system() y los objetivos de montón utilizables de forma remota.
Versiones anteriores de este laboratorio forzaban intencionalmente un fallo de un worker de nginx para que el servicio escribiera un volcado de núcleo, luego obtenían y analizaban ese volcado de núcleo a través de la primitiva de lectura de archivos para recuperar el estado del proceso sensible a ASLR, incluidos los objetivos del montón. En este repositorio, coreless es solo una abreviatura de "sin un volcado de núcleo legible": la ruta predeterminada actual reemplaza esa dependencia del volcado de núcleo con lecturas de memoria procfs en vivo, mientras que la ruta heredada conservada core-guided todavía utiliza el volcado de núcleo generado del worker.
Esta vulnerabilidad — junto con otros tres problemas de corrupción de memoria (CVE-2026-42946, CVE-2026-40701, CVE-2026-42934) — fue descubierta de forma autónoma por el sistema de análisis de seguridad de depthfirst después de un solo clic al incorporar el código fuente de NGINX.
¿Quieres encontrar problemas como este en tu propio código? Prueba el mismo sistema en https://depthfirst.com/open-defense.
El motor de scripts de NGINX utiliza un proceso de dos pasos: primero calcular el tamaño de búfer requerido, luego copiar los datos. El flag is_args se establece en el motor principal cuando un reemplazo de rewrite contiene ?, pero el paso de cálculo de longitud se ejecuta en un submotor recién inicializado a cero. Por lo tanto:
is_args = 0 → devuelve la longitud de captura sin procesar.is_args = 1 → llama a ngx_escape_uri con NGX_ESCAPE_ARGS, expandiendo cada byte escapable a 3 bytes.La copia desborda el búfer de montón de tamaño insuficiente con datos URI controlados por el atacante. La explotación utiliza feng shui de montón entre solicitudes para corromper el puntero cleanup de un ngx_pool_t adyacente (rociado a través de cuerpos POST, ya que los bytes URI no pueden contener bytes nulos), redirigiéndolo a un ngx_pool_cleanup_s falso que invoca system() al destruir el pool.
Lee más sobre este bug en nuestro informe técnico.
| Producto | Afectado | Corregido en |
|---|---|---|
| NGINX Open Source | 0.6.27 – 1.30.0 | 1.31.0, 1.30.1 |
| NGINX Plus | R32 – R36 | R36 P4, R35 P2, R32 P6 |
Aviso completo del proveedor: https://my.f5.com/manage/s/article/K000160932



Esta bifurcación mantiene intacto el PoC de divulgación original, pero agrega una segunda pista de investigación centrada en una pregunta más realista:
¿Se puede explotar el bug contra una máquina virtual x86_64 Linux real con ASLR habilitado, sin depender de desplazamientos fijos de Docker/laboratorio?
La respuesta en esta bifurcación de investigación es sí, con restricciones importantes. Las cadenas funcionales no deshabilitan ASLR y no utilizan las direcciones fijas originales de montón/libc. En su lugar, derivan el estado de ejecución a través de primitivas accesibles por HTTP en el mismo puerto, y luego seleccionan el objetivo de montón final a partir de datos de divulgación obtenidos de forma remota.
Ahora hay dos pistas de exploit con ASLR habilitado, con la ruta coreless tratada como el mejor PoC actual:
nginx_rifter.py: el punto de entrada de evaluación y exploit integrado, limpio y autocontenido. Su método de exploit predeterminado ahora es la cadena coreless /proc/<nginx-worker>/mem.nginx_rifter_core_v2_1.py: la versión conservada heredada de nginx_rifter.py guiada por núcleo. Es útil para reproducir la ruta de investigación anterior de volcado de núcleo probada en VM, pero ya no es el PoC preferido.tools/proc_mem_coreless_exploit.py: el arnés de investigación coreless independiente anterior. Su lógica se ha fusionado en nginx_rifter.py; la herramienta permanece para la reproducción de experimentos sin procesar.La topología objetivo es intencionalmente del mismo puerto:
/api/.../lfi.php?file=.../phpinfo.phpLa ruta actual coreless proc-mem realiza los siguientes pasos de alto nivel:
/proc/<pid>/maps del worker de nginx y el archivo libc mapeado.system() para ese worker./proc/<worker>/mem a través de la primitiva de lectura de archivos.La ruta heredada guiada por núcleo realiza una derivación de dirección base similar, luego fuerza intencionalmente un fallo de un worker, lee el archivo de núcleo generado a través de LFI y extrae ese núcleo en busca de slots de limpieza falsos rociados. Eso fue un puente de investigación útil, pero depende de la política de volcado de núcleo y los permisos del sistema de archivos que son menos comunes en implementaciones predeterminadas.
Esto no es lo mismo que la demostración original determinista de Docker. La ruta de VM x86_64 deja habilitado el ASLR normal de Linux y recalcula las direcciones específicas del proceso en cada ejecución. La ruta Docker coreless también deja ASLR habilitado y elimina el requisito inusual de núcleo legible, pero depende del comportamiento de permisos de procfs que debe verificarse para la clase objetivo.
Esta bifurcación es un laboratorio de investigación controlado. Las cadenas con ASLR habilitado dependen de condiciones sólidas que no son suposiciones universales de producción:
/proc/<pid>/maps, libc mapeado y /proc/<pid>/mem del worker de nginx con el mismo UID en desplazamientos mapeados grandes./proc/<pid>/maps, libc mapeado y el núcleo del worker generado del worker de nginx con el mismo UID.phpinfo() y /proc/<pid>/maps son suficientes para recuperar las direcciones base de PIE/libc, pero no son suficientes por sí solos para recuperar el objeto/ventana de montón exacto necesario para este exploit. La cadena anterior usaba un volcado de núcleo legible para esa divulgación final. La cadena predeterminada actual usa /proc/<worker>/mem en su lugar, que está más cerca de una consecuencia real de lectura arbitraria de archivos en implementaciones con el mismo UID porque expone la memoria del worker en vivo sin cambiar la política de volcado de núcleo.
Límites importantes restantes:
/proc/<pid>/mem está protegido por ptrace. Funcionó en el laboratorio Docker y en una verificación del mismo UID contra el modelo de imagen oficial nginx:stable, pero los procesos de aplicación con diferente UID deberían fallar bajo las protecciones predeterminadas de procfs.El punto de entrada limpio actual es nginx_rifter.py, una herramienta que prioriza la evaluación, diseñada para acercarse a cómo un probador autorizado evaluaría una implementación de nginx vulnerable conocida con una primitiva de lectura de archivos local accesible por HTTP.
En comparación con el ejecutor de demostración inicial, nginx_rifter.py mejora el flujo de trabajo de varias maneras:
--exploit.HOST:PORT, y la primitiva de lectura de archivos es modular a través de --file-read-template./proc/self/status, /proc/self/maps y la accesibilidad de procfs del worker con el mismo UID.system(), IDs de compilación, hashes binarios, detalles del sistema operativo y configuración de proc-mem/núcleo a través de la primitiva remota.rewrite + set vulnerables.nginx_rifter.py; el método predeterminado es coreless proc-mem.El nginx_rifter.py actual es autocontenido. Ya no importa ni llama a versiones anteriores de PoC de demostración ni a tools/proc_mem_coreless_exploit.py para evaluación o explotación.
La implementación anterior de nginx_rifter.py guiada por núcleo se conserva como nginx_rifter_core_v2_1.py.
El archivo más nuevo artifacts/nginx_rifter_v3_coreless_exploit_20260519.gif muestra la ruta de exploit coreless v3 fusionada de nginx_rifter.py. demo4.gif muestra el flujo de evaluación y exploit explícito de la herramienta anterior todo-en-uno guiada por núcleo. El archivo anterior nginx-aslr-demo.gif permanece como la demostración original del exploit con ASLR habilitado.
Probado en Ubuntu 24.04.3 LTS.
Reproducción original con ASLR deshabilitado en Docker:
./setup.sh — construir el contenedor.docker compose -f env/docker-compose.yml up — iniciar el servidor NGINX vulnerable.python3 poc.py --shell — obtener un shell.Para el flujo de reproducción local con Docker, consulta LAB.md.
Cadena heredada guiada por núcleo con ASLR habilitado en VM:
./nginx_rifter_core_v2_1.py --target <target-host>:19321 --exploit --cmd id --fast
Herramienta v3 de evaluación primero:
./nginx_rifter.py --target <target-host>:19321
nginx_rifter.py es el evaluador orientado al mundo real y el punto de entrada integrado del PoC actual. Su modo predeterminado no ejecuta la ruta de exploit que provoca el fallo. Perfila la primitiva de lectura de archivos HTTP, verifica lecturas por rango y binarias, obtiene las huellas del sistema operativo/nginx/libc, descubre los workers de nginx y los mapas relevantes para ASLR, prueba la legibilidad de /proc/<worker>/mem del mismo UID, intenta recuperar las rutas de configuración de nginx a través de lecturas de pid/cmdline/config, marca candidatos de ruta rewrite + set vulnerables e imprime una matriz de viabilidad para la cadena coreless actual.
El nginx_rifter.py actual es autocontenido. Ya no importa ni llama a versiones anteriores de PoC de demostración ni al arnés de investigación proc-mem independiente para evaluación o explotación.
Para una forma personalizada de LFI/descarga:
./nginx_rifter.py --target <target-host>:19321 \
--file-read-template 'http://{host}:{port}/download?path={path_url}{range_query}'
La ejecución del exploit es explícita:
./nginx_rifter.py --target <target-host>:19321 --exploit --cmd id --fast
# Prueba de exploit solo de descubrimiento, sin rociado/sonda
./nginx_rifter.py --target <target-host>:19321 --exploit --derive-only --cmd id
El método de exploit predeterminado es coreless proc-mem. Las siguientes opciones ya están seleccionadas por defecto porque fueron las más confiables para la prueba Docker coreless:
--exploit-method proc-mem
--target-len 6
--max-region 268435456
El modo heredado de núcleo legible aún está disponible para comparación, pero el script versionado es más claro para reproducir esa ruta anterior:
./nginx_rifter_core_v2_1.py --target <target-host>:19321 --exploit --cmd id --fast
Demostración heredada en terminal apta para grabación:
./demo_ctf_exploit_v1_9.py --host <target-host>:19321 --cmd id --clear
demo_ctf_exploit_v1_9.py es el ejecutor anterior orientado al operador para la ruta de laboratorio guiada por núcleo. El punto de entrada PoC preferido actual es nginx_rifter.py.
La primitiva de lectura de archivos predeterminada es la ruta PHP de esta bifurcación:
/lfi.php?file=<path>&offset=<n>&length=<n>
Para una aplicación CTF vulnerable diferente o plataforma de pruebas, el vector de lectura de archivos es modular:
./nginx_rifter.py --target <target-host>:19321 --exploit --cmd id \
--target-profile generic \
--file-read-template 'http://{host}:{port}/download?path={path_url}{range_query}'
La plantilla admite {host}, {port}, {path_url}, {offset}, {length} y {range_query}. El perfil genérico omite las afirmaciones de configuración de nginx específicas de este laboratorio, pero el exploit predeterminado aún necesita las mismas capacidades subyacentes: mapas /proc del worker de nginx legibles, libc legible y /proc/<worker>/mem legible. phpinfo() es opcional; usa --phpinfo-path '' para deshabilitarlo.
Advertencia de realismo: la clase de bug LFI/lectura de archivos y el modelo de implementación de nginx/PHP-FPM en el mismo host son realistas. La cadena proc-mem es más realista que la cadena anterior de volcado de núcleo porque no requiere habilitar ni leer volcados de núcleo del worker. Aún no es una suposición universal de producción predeterminada: el diseño de procesos con el mismo UID, la política de procfs/Yama, la configuración del espacio de nombres del contenedor y la calidad de la primitiva de lectura de archivos determinan si /proc/<worker>/mem es accesible.
Sondas de investigación sin LFI:
python3 tools/non_lfi_leak_probe.py --target <target-host>:19321
python3 tools/non_lfi_active_response_probe.py --target <target-host>:19321
Estas son sondas de investigación negativas, no puntos de entrada de exploit. Ejercitan sumideros de reflexión pasiva y una forma inicial de sobrelectura de respuesta retrasada sin usar LFI, phpinfo, procfs, núcleos, acceso al depurador ni bases ASLR en vivo fijadas.
Notas adicionales del laboratorio y registros de ejecución están en docs/, especialmente:
docs/CTF_PLAN.mddocs/CTF_FINDINGS.mddocs/CTF_TESTS.mddocs/CTF_EXPERIMENT_LOG.mddocs/DEMO_POC_IMPROVEMENTS.mddocs/KNOWN_LAYOUT_PATTERNS.mddocs/VAGRANT_ESXI.mddocs/CORELESS_ASLR_PLAN.mddocs/CORELESS_ASLR_FINDINGS.mddocs/NON_LFI_ASLR_BYPASS_LOG.mddocs/DEMO_RECORDING_WORKFLOW.md