
Scanner de configuration statique qui signale les configurations nginx vulnérables au bug complex_value two-pass capture-clobbering (regex map + regex capture → heap overflow / info leak).
Un scanner statique en lecture seule qui signale les configurations nginx vulnérables à la classe de bugs de capture-clobbering à deux passes complex_value (avis F5/nginx SIRT, juillet 2026). Il analyse votre configuration et signale le motif vulnérable avec la raison et l'emplacement. Il n'exploite rien et ne touche pas au serveur en cours d'exécution.
Fichier unique, bibliothèque standard uniquement, Python 3.6+.
Analyse complète de la vulnérabilité : https://cyberstan.co.uk/nginx-rce/
nginx construit de nombreuses valeurs de directives en deux passes. Une passe LEN mesure la longueur et alloue un tampon, puis une passe VALUE y écrit. Les captures regex ($1 à $9, ou nommées (?P<name>...)) sont lues depuis un état partagé par requête. Un map dont la clé de correspondance est une expression régulière exécute une nouvelle correspondance PCRE au moment où sa variable est évaluée, et cette correspondance écrase l'état de capture partagé. Si une capture est mesurée dans la passe LEN puis qu'un map regex s'exécute avant que la passe VALUE ne réécrive cette capture, les deux passes divergent :
Les deux directions sont déclenchables à distance lorsque l'entrée du map est influencée par l'attaquant ($request_body, $http_*, $arg_*, $uri, $ssl_preread_server_name, etc.).
Le scanner signale un emplacement ou un serveur lorsque tous ces éléments aboutissent dans un même tampon à deux passes, dans l'ordre exploitable :
location ~ regex, server_name ~, rewrite, if (... ~ ...), ou un map regex avec un groupe de capture.map (http ou stream) avec une clé de correspondance regex ~ ou ~*, référencé par sa variable de sortie.return, set, add_header, proxy_method, proxy_pass, rewrite, index, et autres) : les deux références dans la même valeur.proxy_set_header, proxy_set_body, fastcgi_param, scgi_param, uwsgi_param, grpc_set_header) : celles-ci construisent un tampon par requête pour toute la famille, donc les deux références peuvent se trouver dans des directives séparées au sein du même emplacement.# 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
| Option | Effet |
|---|---|
--json | Émet un rapport JSON au lieu de texte. |
--no-includes | Ne pas suivre les directives include. |
| Code | Signification |
|---|---|
0 | Aucune configuration vulnérable trouvée. |
1 | Au moins une configuration vulnérable trouvée. |
2 | Erreur d'utilisation (aucun chemin fourni, ou aucun trouvé). |
Utilisable en CI, puisqu'une configuration vulnérable renvoie un code non nul :
python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf || echo "review needed"
Le mode texte affiche, pour chaque résultat : le fichier et la ligne, la portée englobante, la directive de sink, les variables de capture et de map impliquées, la map déclencheuse, et une raison sur une ligne. Une section effacée liste les coexistences en ordre sûr. --json produit :
{
"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": []
}
ngx_http_script_check_length()) qui empêche la passe VALUE d'écrire au-delà du tampon alloué, et calcule la longueur de la chaîne renvoyée à partir des octets réellement écrits plutôt que de la mesure de la passe LEN, fermant ainsi à la fois la direction du débordement et celle de la fuite d'informations.map de type regex dans la même location ou le même tampon qu'une
référence $1 à $9 ou à une capture nommée.(?P<name>...) à travers plusieurs maps regex.proxy_set_header ou
fastcgi_param.set.include illisibles (par exemple des chemins absolus qui n'existent pas
localement) sont signalées sous missing_includes, et non ignorées silencieusement. Exécutez-le
sur l'hôte où la configuration se résout pour une couverture complète.Analyse de la vulnérabilité et chaîne d'exploitation : https://cyberstan.co.uk/nginx-rce/