NGINX 曝 9.2 分高危漏洞:潜伏 18 年,威胁全球约 1/3 服务器
漏洞概述
科技媒体 cyberkendra 于 5 月 13 日报道,NGINX 被曝一组高危漏洞,已潜伏约 18 年,威胁全球约 三分之一的网络服务器。
本次曝光的具体漏洞编号及评分如下:
| 编号 | 评分 | 等级 |
|---|---|---|
| CVE-2026-42945 | 9.2 | Critical |
| CVE-2026-42946 | 8.3 | High |
| CVE-2026-40701 | 6.3 | Medium |
| CVE-2026-42934 | 6.3 | Medium |
漏洞细节
攻击者无需登录认证,只需发送一条特制 HTTP 请求,就能让 NGINX 工作进程崩溃。在合适的条件下,还可能获得服务器的远程代码执行(RCE)权限。
本次漏洞由安全团队 depthfirst 在扫描 NGINX Codebase(代码库)时发现。其自动化系统在 6 小时内找到 5 个问题,其中 4 个获得 NGINX 官方确认。
最严重的 CVE-2026-42945 可追溯到 2008 年,长期存在于几乎所有标准 NGINX 构建版本中。
技术原理
问题出在 ngx_http_rewrite_module 的处理逻辑中。某个内部标志位在被设置为参数转义状态后未被清除,导致后续长度计算按原始字节数估算,但实际写入时又进行了一次转义,造成缓冲区溢出。
攻击者 URI 中的 +、%、& 等字符会从 1 字节膨胀至 3 字节,原本够用的缓冲区因此溢出。
概念验证
depthfirst 已开发出可运行的概念验证(PoC),在关闭 ASLR 的条件下可实现未认证的远程代码执行。
更值得关注的是,NGINX 的多进程架构为攻击者提供了反复尝试的空间:
- 某个工作进程崩溃后,主进程会拉起新进程
- 新进程的堆布局可能与之前保持一致
- 攻击者可通过重复请求逐步覆盖指针字节,尝试绕过 ASLR
修复方案
版本升级(推荐)
NGINX 官方已发布修复版本:
- NGINX Open Source:升级至 1.31.0 或 1.30.1
- NGINX Plus:升级至 R36 P4 或 R32 P6
升级后需重启服务以加载修复后的二进制文件。
临时缓解措施
若暂时无法升级,官方建议将配置中 rewrite 指令的未命名正则捕获($1、$2 等)替换为命名捕获($name)。命名捕获不会进入有问题的转义路径,从而移除当前攻击面。
漏洞触发的必要条件如下:
- 配置中使用了
rewrite指令,且替换字符串包含问号(?) - 该 rewrite 指令使用了未命名捕获(
$1、$2) - 同一作用域下存在
set、if或另一条rewrite指令
受影响配置示例(存在风险)
location ~ ^/api/(.*)$ {
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1;
}
缓解后配置示例(安全)
使用命名捕获替换 $1、$2 等未命名引用:
location ~ ^/api/(?<path>.*)$ {
rewrite ^/api/(?<path>.*)$ /internal?migrated=true;
set $original_endpoint $path;
}
或者使用 if 替代 set,或调整逻辑避免在 rewrite 后引用捕获组。
排查方法
方式一:导出全部配置后精确匹配
使用 nginx -T 导出所有已加载的配置,通过正则匹配同时包含 rewrite(替换中含 ?)和后续 set/if/rewrite 的段落:
nginx -T 2>/dev/null | grep -Pzo '(?s)rewrite[^;]*\?[^;]*;.*?(set|if|rewrite)\s'
方式二:在配置目录中逐文件检索
直接搜索配置文件中有 rewrite/set 且引用 $1、$2 等未命名捕获的位置:
grep -rn "rewrite\|set " /etc/nginx/conf.d/ -A 2 | grep -B 2 "\\$[0-9]"
两种方式的区别:
方式一(nginx -T) |
方式二(grep 逐文件) |
|
|---|---|---|
| 范围 | 导出 NGINX 实际加载的所有配置(含 include) | 仅在指定目录中搜索 |
| 精度 | 能精确定位同时具备三个触发条件的配置段 | 仅标记出现 rewrite/set 和 $数字 的行,漏报/误报较多 |
| 依赖 | 需在生产环境执行 nginx -T(仅读取,不修改配置) |
普通文本搜索,无需 NGINX 命令 |
| 适用 | 推荐优先使用,结果更可靠 | 备用方案,适合无权执行 nginx -T 的场景 |