
Escáner de configuración estática que señala configuraciones de nginx vulnerables al bug complex_value two-pass capture-clobbering (regex map + regex capture → desbordamiento de montón / fuga de información).
Un escáner estático de solo lectura que marca configuraciones de nginx vulnerables a la clase de error de clobbering de capturas en dos pasadas complex_value (aviso de F5/nginx SIRT, julio de 2026). Analiza tu configuración e informa del patrón vulnerable con el motivo y la ubicación. No explota nada ni toca el servidor en ejecución.
Un solo archivo, solo biblioteca estándar, Python 3.6+.
Análisis completo de la vulnerabilidad: https://cyberstan.co.uk/nginx-rce/
nginx construye muchos valores de directivas en dos pasadas. Una pasada LEN mide la longitud y asigna un búfer, y luego una pasada VALUE escribe en él. Las capturas de regex ($1 a $9, o con nombre (?P<name>...)) se leen de un estado compartido por petición. Un map cuya clave de coincidencia es una expresión regular ejecuta una nueva coincidencia PCRE en el momento en que se evalúa su variable, y esa coincidencia sobrescribe el estado de capturas compartido. Si una captura se mide en la pasada LEN y luego se ejecuta un map de regex antes de que la pasada VALUE reescriba esa captura, las dos pasadas no coinciden:
Ambas direcciones son desencadenables de forma remota cuando la entrada del map está influida por el atacante ($request_body, $http_*, $arg_*, $uri, $ssl_preread_server_name, etc.).
El escáner marca una location o un server cuando todo lo siguiente coincide en un mismo búfer de dos pasadas, en el orden explotable:
location ~ de regex, server_name ~, rewrite, if (... ~ ...), o un map de regex con un grupo de captura.map (http o stream) con una clave de coincidencia regex ~ o ~*, referenciado por su variable de salida.return, set, add_header, proxy_method, proxy_pass, rewrite, index, y otras): ambas referencias en el mismo valor.proxy_set_header, proxy_set_body, fastcgi_param, scgi_param, uwsgi_param, grpc_set_header): estas construyen un búfer por petición para toda la familia, por lo que las dos referencias pueden estar en directivas separadas dentro de la misma location.# scan a single config (follows include directives by default)
python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf
# scan a directory (uses nginx.conf if present, else all *.conf)
python3 nginx_capture_clobber_scan.py /etc/nginx/
# scan several roots
python3 nginx_capture_clobber_scan.py site-a.conf site-b.conf
# machine-readable output
python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf --json
# do not expand include directives
python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf --no-includes
| Opción | Efecto |
|---|---|
--json | Emitir un informe JSON en lugar de texto. |
--no-includes | No seguir las directivas include. |
| Código | Significado |
|---|---|
0 | No se encontró ninguna configuración vulnerable. |
1 | Se encontró al menos una configuración vulnerable. |
2 | Error de uso (no se proporcionó ninguna ruta, o no se encontró ninguna). |
Utilizable en CI, ya que una configuración vulnerable sale con un código distinto de cero:
python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf || echo "review needed"
El modo texto imprime, para cada hallazgo: archivo y línea, el ámbito contenedor, la directiva sink, las variables de captura y de mapa involucradas, el mapa que lo desencadena y una razón de una línea. Una sección de descartados lista las coexistencias en orden seguro. --json produce:
{
"vulnerable": true,
"findings": [
{
"file": "/etc/nginx/conf.d/api.conf",
"line": 12,
"scope": "location ~ ^/api/(.+)$",
"directive": "proxy (family buffer)",
"captures": ["$1"],
"map_vars": ["$is_bot"],
"triggers": ["$is_bot <- regex-map on $http_user_agent [nginx.conf:30]"],
"reason": "..."
}
],
"cleared_safe_order": [],
"regex_maps": [],
"missing_includes": []
}
map de regex en la misma ubicación o búfer que una
referencia $1 a $9 o de captura con nombre.(?P<name>...) en múltiples mapas de regex.proxy_set_header o
fastcgi_param.set dinámicas.include ilegibles (por ejemplo, rutas absolutas que no existen
localmente) se reportan en missing_includes, no se omiten silenciosamente. Ejecútelo
en el host donde la configuración se resuelve para una cobertura completa.Análisis de la vulnerabilidad y cadena de explotación: https://cyberstan.co.uk/nginx-rce/