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, 无后门, 静态代码扫描