NGINX Rift (CVE-2026-42945): Un desbordamiento de montón de 18 años en el módulo de reescritura
NGINX Rift (CVE-2026-42945, CVSS 9.2): Un desbordamiento crítico de búfer en el montón en el módulo de reescritura de NGINX, descubierto autónomamente por el sistema de análisis de IA de depthfirst. Introducido en 2008 y afectando 18 años de versiones de NGINX, permite a un atacante no autenticado lograr ejecución remota de código con una sola solicitud HTTP manipulada.
La Vulnerabilidad Que Estaba Oculta a Plena Vista
El 13 de mayo de 2026, F5 y depthfirst divulgaron conjuntamente CVE-2026-42945 — un desbordamiento crítico de búfer en el montón en ngx_http_rewrite_module de NGINX. La vulnerabilidad había estado en el código fuente desde 2008, introducida en NGINX 0.6.27, afectando cada versión posterior hasta 1.30.0.
Lo que hace que este descubrimiento sea particularmente notable es cómo se encontró: no por un investigador humano auditando código manualmente, sino por el sistema autónomo de análisis de vulnerabilidades de depthfirst. El sistema de IA fue dirigido al código fuente de NGINX, y en seis horas marcó el problema de desbordamiento de montón que había eludido la detección humana durante 18 años.
| Métrica | Valor |
|---|---|
| CVE | CVE-2026-42945 |
| CVSS v4.0 | 9.2 (Crítico) |
| Descubierto por | depthfirst (análisis autónomo de IA) |
| Introducido | 2008 (NGINX 0.6.27) |
| Oculto durante | 18 años |
| Tipo de vulnerabilidad | Desbordamiento de búfer en montón (discrepancia de longitud en dos pasos) |
| Autenticación requerida | Ninguna |
| Impacto | Ejecución remota de código (RCE) o caída del worker (DoS) |
| Versión corregida | NGINX 1.31.0 / 1.30.1 |
Versiones Afectadas
La vulnerabilidad abarca casi todas las líneas de productos de NGINX:
| Producto | Versiones Afectadas |
|---|---|
| NGINX Open Source | 0.6.27 hasta 1.30.0 |
| NGINX Plus | R32 hasta R36 |
| NGINX Instance Manager | 2.16.0 hasta 2.21.1 |
| F5 NGINX App Protect WAF | 4.9.0–4.16.0, 5.1.0–5.8.0 |
| NGINX Ingress Controller | 3.5.0–3.7.2, 4.0.0–4.0.1, 5.0.0–5.4.1 |
| NGINX Gateway Fabric | 1.3.0–1.6.2, 2.0.0–2.5.1 |
Dado que NGINX impulsa aproximadamente un tercio de todos los sitios web a nivel mundial, el radio de explosión de esta vulnerabilidad es enorme.
Inmersión Técnica Profunda
El Diseño de Dos Pasos
Para entender el bug, necesitas entender el motor de scripts de NGINX. Cuando NGINX evalúa una directiva rewrite o set, opera en dos pasos:
- Paso de longitud (
ngx_http_script_len_code): Calcula el tamaño total del búfer necesario para contener la salida final - Paso de copia (
ngx_http_script_run/ngx_http_script_copy_code): Asigna un búfer de ese tamaño y escribe los datos reales
El contrato es simple: el paso 1 te dice exactamente cuántos bytes asignar, el paso 2 escribe exactamente esa cantidad de bytes. Si los dos no coinciden — obtienes un desbordamiento de montón.
Causa Raíz: La Bandera is_args Huérfana
La vulnerabilidad vive en src/http/ngx_http_script.c. Cuando la cadena de reemplazo de una directiva rewrite contiene un signo de interrogación (?), la función ngx_http_script_start_args_code establece una bandera en el motor de scripts:
e->is_args = 1;
Esta bandera señala que los componentes URI subsiguientes deben tratarse como argumentos de consulta y escaparse URI (ej. + → %2B, & → %26).
El problema: esta bandera nunca se restablece. Permanece establecida en el motor de scripts principal (e) durante el resto del procesamiento de la solicitud.
La Discrepancia
Cuando una directiva set subsiguiente referencia un grupo de captura de regex (ej. $1), el motor de scripts lo evalúa. Durante el paso de longitud, ngx_http_script_complex_value_code crea un submotor fresco puesto a cero (le):
ngx_http_script_len_code_ctx_t le;
ngx_memzero(&le, sizeof(ngx_http_script_len_code_ctx_t));
Dado que le.ip y le.is_args son ambos cero, la función de cálculo de longitud ngx_http_script_copy_capture_len_code toma la rama else — devuelve la longitud de captura cruda, sin escapar.
Durante el paso de copia, el código se ejecuta en el motor principal (e), donde e->is_args sigue siendo 1. La función de copia ngx_http_script_copy_capture_code entra en una rama diferente:
if (e->is_args) {
// Escapa la URI: expande + % & de 1 byte a 3 bytes
n = ngx_escape_uri(NULL, src, len, NGX_ESCAPE_ARGS);
// ...asigna y escribe la versión escapada
}
Cada carácter escapable en la URI controlada por el atacante (+, %, &) se expande de 1 byte a 3 bytes. El búfer se dimensionó para la longitud cruda (sin escapar) — la escritura sobrepasa la asignación.
// Paso de longitud mide: raw_len bytes
// Paso de copia escribe: raw_len + 2*N bytes (donde N = caracteres escapables)
// ↑↑↑ DESBORDAMIENTO DE MONTÓN
Esta es una violación clásica del contrato de dos pasos, posible porque el estado is_args fue establecido por una directiva rewrite completamente no relacionada y nunca se limpió.
Explotación
Los investigadores de depthfirst desarrollaron una prueba de concepto funcional que demuestra RCE no autenticada contra NGINX con ASLR desactivado. Las propiedades clave que hacen práctica la explotación:
| Propiedad | Detalle |
|---|---|
| Tamaño del desbordamiento | Totalmente controlado por el atacante (número de +, &, % en URI) |
| Datos del desbordamiento | Controlados por el atacante (contenido URI escapado) |
| Reproducibilidad | Determinista — la misma solicitud siempre desborda de la misma manera |
| Presupuesto de reintentos | Infinito — los workers caídos se regeneran con el mismo diseño de montón |
| Autenticación | Ninguna requerida — accesible desde internet público |
El presupuesto infinito de reintentos es particularmente importante para eludir ASLR. La explotación moderna contra ASLR típicamente requiere fuga de información o fuerza bruta. Debido a que NGINX genera workers de reemplazo con un diseño de montón idéntico después de cada caída, un atacante puede hacer intentos ilimitados sin costo.
Los investigadores describen una técnica teórica: sobrescribiendo progresivamente bytes de puntero a través de solicitudes repetidas, un atacante puede redirigir el flujo de ejecución a un payload controlado, derrotando a ASLR sin un paso explícito de fuga de información.
Condición de Disparo: ¿Estás Afectado?
La vulnerabilidad solo es alcanzable si tu configuración de NGINX contiene un patrón específico:
# Patrón vulnerable:
# 1. Un rewrite con ? en reemplazo Y grupos de captura sin nombre
# 2. Seguido de otro rewrite, if, o set en el mismo ámbito
rewrite ^/users/([0-9]+)/profile/(.*)$ /profile.php?id=$1&tab=$2 last;
El ? en /profile.php?id=$1&tab=$2 establece is_args = 1. Las capturas sin nombre $1, $2 activan la ruta de código vulnerable cuando una directiva subsiguiente las evalúa.
Verifica Tu Configuración
grep -rn 'rewrite.*\?.*\$[0-9]' /etc/nginx/
Si esto devuelve alguna coincidencia, tu configuración está afectada.
Mitigación
Inmediato: Actualizar
| Versión | Acción |
|---|---|
| NGINX Open Source | Actualizar a 1.31.0 o 1.30.1 |
| NGINX Plus R36 | Aplicar R36 P4 |
| NGINX Plus R32 | Aplicar R32 P6 |
Solución Alternativa: Grupos de Captura Nombrados
Si no puedes actualizar inmediatamente, reemplaza las capturas sin nombre con capturas nombradas en cada directiva rewrite afectada:
# Vulnerable — capturas sin nombre con ? en reemplazo
rewrite ^/users/([0-9]+)/profile/(.*)$ /profile.php?id=$1&tab=$2 last;
# Mitigado — capturas nombradas evitan la ruta de código vulnerable
rewrite ^/users/(?<user_id>[0-9]+)/profile/(?<section>.*)$ /profile.php?id=$user_id&tab=$section last;
Las capturas nombradas ((?<name>...)) no pasan por la lógica de escape vulnerable, porque la función ngx_http_script_copy_capture_code solo aplica escape URI a capturas sin nombre. Este cambio de configuración elimina la superficie de ataque sin una actualización binaria.
Verificar la Corrección
# Verificar versión
nginx -v
# Después de actualizar, verificar: debe ser 1.31.0 o 1.30.1+
nginx -v 2>&1 | grep -E '1\.31\.0|1\.30\.[1-9]'
Línea de Tiempo
| Fecha | Evento |
|---|---|
| 2008 | Vulnerabilidad introducida en NGINX 0.6.27 (commit de inicialización del módulo de reescritura) |
| 2026-04 | Sistema autónomo de depthfirst escanea código fuente de NGINX, marca desbordamiento de montón en 6 horas |
| 2026-04-24 | F5 confirma el problema y coordina la divulgación |
| 2026-05-13 | F5 publica NGINX 1.31.0 / 1.30.1 con corrección; CVE-2026-42945 publicado |
| 2026-05-14 | Este artículo publicado |
Implicaciones Más Amplias: Vulnerabilidades Descubiertas por IA
CVE-2026-42945 es notable no solo por su gravedad, sino por cómo fue descubierto. Un sistema de IA autónomo encontró un bug en un código fuente que ha sido auditado por miles de ingenieros, investigadores de seguridad y contribuyentes de código abierto durante 18 años — en seis horas.
Esto sigue un patrón que hemos visto acelerarse en 2026:
| Vulnerabilidad | Descubierto por | Tiempo en encontrar |
|---|---|---|
| Copy Fail (LPE kernel Linux) | Xint Code (IA) | ~1 hora |
| Dirty Frag (LPE kernel Linux) | Humano (Hyunwoo Kim) | Auditoría manual |
| CVE-2026-42945 (NGINX Rift) | depthfirst (IA autónoma) | 6 horas |
| CVE-2026-42946 (sobrelectura NGINX) | depthfirst (IA autónoma) | Mismo escaneo |
La brecha entre lo que un sistema de IA determinado puede encontrar y lo que los revisores humanos han capturado históricamente está creciendo rápidamente. Para los mantenedores de infraestructura crítica, esto significa:
- Asume que hay más bugs sin descubrir en tus dependencias — los encontrados hasta ahora son solo lo que la generación actual de herramientas de IA puede capturar
- Minimiza la superficie de ataque — elimina módulos no utilizados, desactiva características innecesarias, usa el principio de mínima funcionalidad
- Defensa en profundidad — incluso si un componente se compromete, otras capas deberían limitar el radio de explosión
NGINX mismo es un caso interesante: es conocido por su código fuente limpio y su sólido historial de seguridad. Y sin embargo, un RCE crítico de 18 años estaba oculto a plena vista. Si NGINX no está a salvo de esta clase de bug, ningún código fuente en C lo está.
Conclusión
CVE-2026-42945 (NGINX Rift) es un desbordamiento crítico de montón en uno de los proyectos de software más ampliamente desplegados en internet. No requiere autenticación, puede ser activado desde internet público, y le da a un atacante ejecución completa de código en el proceso worker de NGINX.
Si ejecutas NGINX, asume que estás afectado — a menos que hayas verificado que tu configuración no contiene el patrón de rewrite vulnerable, o que hayas actualizado a 1.31.0 / 1.30.1.
La vida útil de 18 años de este bug es un recordatorio contundente: nuestra infraestructura se sostiene con código que nunca ha sido auditado exhaustivamente por herramientas modernas. La era de IA del descubrimiento de vulnerabilidades apenas comienza, y deberíamos esperar más revelaciones como esta — no menos.
Referencias
- Investigación de depthfirst NGINX Rift: https://depthfirst.com/research/nginx-rift-achieving-nginx-rce-via-an-18-year-old-vulnerability
- Página de aterrizaje de depthfirst: https://depthfirst.com/nginx-rift
- Aviso de seguridad F5 K000161019: https://my.f5.com/manage/s/article/K000161019
- Avisos de seguridad de NGINX: https://nginx.org/en/security_advisories.html
- Registro de cambios de NGINX (1.31.0): https://nginx.org/en/CHANGES
Infografía
Figura 1: NGINX Rift — cómo la discrepancia de longitud del búfer de dos pasos produce un desbordamiento de montón