0xCyberstan/CVE-2026-42533-Config-Scanner

GitHub: 0xCyberstan/CVE-2026-42533-Config-Scanner

一个纯静态、只读的 nginx 配置扫描器,用于检测 complex_value 两遍解析导致的 capture-clobber 漏洞(堆溢出/信息泄露)。

Stars: 6 | Forks: 1

# nginx capture-clobber 扫描器 一个只读的静态扫描器,用于标记存在以下漏洞的 nginx 配置: `complex_value` 两遍解析 capture-clobber 漏洞类(F5/nginx SERT 公告, 2026 年 7 月)。它会解析你的配置,并报告存在漏洞的模式以及 原因和位置。它不会利用漏洞,也不会触碰正在运行的 服务器。 单文件,仅使用标准库,支持 Python 3.6+。 完整的漏洞分析报告: https://cyberstan.co.uk/nginx-rce/ ## 漏洞详情 nginx 分两遍构建许多指令的值。第一遍 LEN 用于测量长度 并分配缓冲区,然后第二遍 VALUE 将数据写入其中。正则表达式 capture(`$1` 到 `$9`,或命名的 `(?P...)`)从每个请求的共享状态中读取。如果 `map` 的匹配键是正则表达式,则在其变量被求值的那一刻, 会运行一次新的 PCRE 匹配,并且该匹配会覆盖共享的 capture 状态。 如果在 LEN 遍中测量了某个 capture,然后正则表达式 `map` 在 VALUE 遍重写该 capture 之前运行,这两遍的数据就会产生不一致: - 覆盖导致实际值长于测量的值:堆缓冲区溢出 (攻击者可控的越界写入) - 覆盖导致实际值短于测量的值:未初始化的堆数据被返回给 客户端(libc/堆指针的信息泄露) 当 map 的输入受 攻击者影响时(`$request_body`, `$http_*`, `$arg_*`, `$uri`, `$ssl_preread_server_name` 等),这两个方向都可以被远程触发。 ## 什么样的情况属于漏洞 如果以下所有条件同时出现在一个两遍解析缓冲区中,并且符合 可利用的顺序,扫描器就会标记该 location 或 server: 1. Capture 源:带有 capture group 的正则表达式 `location ~`、`server_name ~`、`rewrite`、 `if (... ~ ...)`,或正则表达式 `map`。 2. 覆盖触发器:带有 `~` 或 `~*` 正则表达式匹配键的 `map`(http 或 stream),且被其输出变量引用。 3. 使用了 capture 引用和正则表达式 map 变量的两遍解析 sink: - 单值指令(`return`, `set`, `add_header`, `proxy_method`, `proxy_pass`, `rewrite`, `index` 等):两个引用在同一个值中。 - 参数/标头系列(`proxy_set_header`, `proxy_set_body`, `fastcgi_param`, `scgi_param`, `uwsgi_param`, `grpc_set_header`):这些 指令会为整个系列在每个请求中构建一个缓冲区,因此这两个引用可以 位于同一个 location 下的不同指令中。 4. 顺序:capture 必须在正则表达式 map 之前被求值。正则表达式 map 运行 一次并缓存,因此 map-before-capture(先 map 后 capture)读取到的是一致的状态,不存在 漏洞。扫描器会将这些情况报告为已解除风险(安全但脆弱,请勿 重新排序)。 ## 用法 ``` # 扫描单个 config (默认遵循 include 指令) python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf # 扫描目录 (如果存在 nginx.conf 则使用,否则使用所有 *.conf) python3 nginx_capture_clobber_scan.py /etc/nginx/ # 扫描多个 roots python3 nginx_capture_clobber_scan.py site-a.conf site-b.conf # machine-readable 输出 python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf --json # 不展开 include 指令 python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf --no-includes ``` ### 选项 | 选项 | 效果 | |-----------------|---------------------------------------| | `--json` | 输出 JSON 报告而不是文本。 | | `--no-includes` | 不遵循 `include` 指令。 | ### 退出码 | 代码 | 含义 | |------|----------------------------------------------| | `0` | 未发现易受攻击的配置。 | | `1` | 发现至少一个易受攻击的配置。 | | `2` | 使用错误(未指定路径,或未找到路径)。 | 可用于 CI,因为存在漏洞的配置会以非零状态退出: ``` python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf || echo "review needed" ``` ## 输出 文本模式会为每个发现打印以下信息:文件和行号、所属作用域、sink 指令、涉及的 capture 和 map 变量、触发 map 的指令,以及 单行原因。已解除风险的部分列出了安全顺序的共存情况。`--json` 会产生: ``` { "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": [] } ``` ## 修复发现的漏洞 1. 应用官方补丁(nginx 1.30.4 stable / 1.31.3 mainline,NGINX Plus R36 P7 / 37.0.3.1)。这是唯一完整的修复方案。该补丁添加了一个边界防护(ngx_http_script_check_length()),防止 VALUE 遍写入超出已分配缓冲区的范围,并根据实际写入的字节数计算返回的字符串长度,而不是使用 LEN 遍的测量值,从而堵住了溢出和信息泄露两个方向的漏洞。 2. 过渡期的配置加固(纵深防御,不能替代官方补丁): - 不要在同一个 location 或缓冲区中引用正则表达式 `map` 变量以及 `$1` 到 `$9` 或命名 capture 引用。 - 不要在多个正则表达式 map 中重复使用同一个 `(?P...)` group。 - 不要将 capture 引用和正则表达式 map 引用放在同一个 `proxy_set_header` 或 `fastcgi_param` 系列中。 ## 限制 ## 参考 漏洞分析报告与利用链: https://cyberstan.co.uk/nginx-rce/
标签:Nginx, Python, 无后门, 静态代码扫描