
Prueba de concepto para CVE-2026-9256, un desbordamiento de búfer de montón en ngx_http_rewrite_module de NGINX. Demuestra el bloqueo del worker y la denegación de servicio mediante URI manipulada con grupos de captura PCRE superpuestos. Incluye verificación en múltiples etapas y sondeo keep-alive.
Ámbito de aplicación: solo para laboratorios locales, entornos de reproducción autorizados, verificación de vulnerabilidades y análisis de reglas de protección. No lo utilice en objetivos no autorizados. Las ideas del PoC en este artículo solo verifican el comportamiento de caída del worker de NGINX visible de forma remota, no incluyen RCE, elusión de ASLR ni cadenas de explotación estables.
CVE-2026-9256 es una vulnerabilidad de desbordamiento de búfer en el montón (heap buffer overflow) en el módulo ngx_http_rewrite_module de NGINX. El desencadenamiento de la vulnerabilidad no se produce simplemente accediendo a una URI fija, sino que depende de un patrón de configuración de rewrite específico: grupos de captura PCRE superpuestos en la expresión regular de rewrite, y la parte de reemplazo referencia múltiples variables de captura, por ejemplo $1, $2.
Cuando un atacante construye una URI especial que hace que la lógica de rewrite entre en la ruta relevante, NGINX puede presentar una inconsistencia entre el cálculo de longitud y la escritura real al procesar el contenido capturado, concatenar el resultado de rewrite o realizar el escape de URI/parámetros, lo que finalmente provoca la corrupción de la memoria dinámica del proceso worker.
Por lo tanto, la clave de esta vulnerabilidad no es la ruta /api en sí, sino si existe en la configuración de NGINX objetivo una regla de rewrite vulnerable que pueda ser alcanzada por una solicitud. La ruta /api utilizada por defecto en el PoC es solo una ruta de ejemplo en el entorno de reproducción actual. En las pruebas reales, es necesario ajustar la ruta de la solicitud según la regla de rewrite que contenga grupos de captura superpuestos y referencias a múltiples variables de captura en la configuración de NGINX.
El objetivo actual del PoC es verificar el comportamiento de caída del worker / denegación de servicio. No intenta construir un diseño de montón preciso, no intenta sobrescribir la dirección de retorno o punteros de función, ni demuestra la ejecución remota de código. La evidencia estable que se puede observar en el lado remoto es principalmente: la conexión de la solicitud desencadenante se interrumpe anormalmente, luego el servicio NGINX se recupera y responde, y las conexiones keep-alive se interrumpen después del desencadenamiento debido a la caída del worker.
Después de desencadenar esta vulnerabilidad, no siempre se manifiesta como un código de estado HTTP fijo 500, 502 o 400. La razón es que el modelo master-worker de NGINX permite que el proceso worker se cuelgue y luego el master lo reinicie. El fenómeno que ve el atacante en el lado remoto generalmente no es que todo el servicio deje de estar disponible por completo, sino que una conexión se interrumpe repentinamente, se produce un timeout de lectura, la conexión se reinicia, y luego al acceder nuevamente a / se obtiene una respuesta normal.
Por lo tanto, el PoC no puede determinar la existencia de la vulnerabilidad basándose únicamente en el código de estado HTTP de una sola solicitud. Si solo se envía una URI larga y luego se ve que la conexión se interrumpe y se concluye directamente que "la vulnerabilidad existe", el riesgo de falsos positivos es alto. La interrupción de la conexión también puede deberse a fluctuaciones de la red, timeout de proxy, interceptación por dispositivos intermedios, limitación de velocidad del backend o cierre activo de la conexión por parte del servidor.
Por lo tanto, el PoC debe diseñarse como una verificación en múltiples etapas:
Solo cuando aparecen simultáneamente "conexión desencadenante anormal + recuperación del servicio posterior + múltiples caídas de keep-alive", se puede determinar con mayor seguridad la existencia de un comportamiento de caída del worker estilo CVE-2026-9256.
La ruta central de desencadenamiento del PoC actual es:
GET /api/++++++++++++++++++++++++++++++++... HTTP/1.1
Host: 127.0.0.1:19321
Donde /api/ es la ruta de ejemplo utilizada en el laboratorio actual para alcanzar la regla de rewrite, y luego se concatenan una gran cantidad de caracteres +. La cantidad predeterminada es 4096.
Las razones para elegir + son principalmente tres.
Primero, + es un carácter URI合法, y al usar un cliente HTTP normal generalmente no se trunca o reescribe forzosamente como espacios, #, etc. Por lo tanto, el PoC actual no necesita usar raw socket para construir líneas de solicitud ilegales como en algunas vulnerabilidades de elusión de request-target.
Segundo, una gran cantidad de caracteres repetidos permite que los grupos de captura de rewrite tengan una entrada suficientemente larga, ampliando la escala de salida de la concatenación posterior del reemplazo o del procesamiento de escape, lo que facilita desencadenar la inconsistencia entre el cálculo de longitud y la escritura real.
Tercero, la estructura de payload de + repetidos es simple, fácil de observar en capturas de paquetes, registros y reglas IDS, y también facilita el ajuste de longitud para pruebas de umbral.
Sin embargo, hay que tener en cuenta que + no es el único carácter teóricamente capaz de desencadenar la vulnerabilidad. La condición real de desencadenamiento sigue siendo "alcanzar una configuración de rewrite vulnerable + entrada que pueda entrar en los grupos de captura relevantes + el procesamiento de salida de rewrite que desencadene un desbordamiento de montón". En diferentes entornos, la ruta de desencadenamiento, el tipo de carácter y el umbral de longitud pueden necesitar ajustes.
El PoC actual elige por defecto una gran cantidad de + como caracteres desencadenantes, pero esto no significa que solo + pueda desencadenar el problema. + es simplemente el carácter más adecuado para escribir en un PoC genérico, porque es relativamente estable en una URI, fácil de enviar con un cliente HTTP normal y con características claras en la captura de paquetes.
Desde el principio de la vulnerabilidad, siempre que un carácter entre en la lógica de escape NGX_ESCAPE_ARGS durante el procesamiento de rewrite de NGINX y se expanda de 1 byte original a 3 bytes en forma %XX, puede causar una diferencia entre el "valor calculado de longitud" y el "valor real escrito". Es decir, el punto de desencadenamiento no es esencialmente + en sí mismo, sino la "aparición densa de caracteres que pueden ser escapados en modo args".
Además de +, los caracteres que teóricamente deben considerarse con énfasis incluyen:
Espacio: 0x20
#: 0x23
%: 0x25
&: 0x26
?: 0x3F
Caracteres de control: 0x00-0x1F
Bytes altos: 0x7F-0xFF
Si estos caracteres entran en la captura relevante y son tratados como contenido args para escape en el reemplazo de rewrite, todos producirán un efecto de expansión similar. Por ejemplo:
+ -> %2B
& -> %26
% -> %25
# -> %23
? -> %3F
Espacio -> %20