漏洞概述
2026 年 5 月 14 日,安全研究团队 DepthFirst 公布了代号为 "NGINX Rift" 的严重漏洞 CVE-2026-42945。这个隐蔽了 18 年的堆缓冲区溢出漏洞位于 NGINX 核心的 ngx_http_rewrite_module 中,CVSS 评分为 9.2(Critical)。
该漏洞影响 NGINX 从 0.6.27(2008 年发布)到 1.30.0 的所有版本。只要使用 rewrite 和 set 指令的配置即可触发,攻击者可实现未经授权的远程代码执行。
更令人震惊的是——这个漏洞是 DepthFirst 的 自动安全分析系统发现的。只需一键接入 NGINX 源码,系统在 6 小时内自动扫描出 4 个内存损坏漏洞,CVE-2026-42945 只是其中最严重的一个。
根因分析:is_args 状态未正确传播
NGINX 脚本引擎的双遍处理机制
要理解这个漏洞,先要知道 NGINX 脚本引擎的工作方式。对于 rewrite 和 set 指令的表达式,NGINX 使用两遍(two-pass)处理:
- 第一遍(长度计算):计算最终字符串需要的总内存大小
- 第二遍(数据拷贝):将实际数据写入之前分配的缓冲区
这种设计避免了多次小内存分配,但前提是两遍之间的引擎状态必须完全一致。正是这个假设被打破了。
is_args 标志的传播错误
当 rewrite 指令的替换字符串包含问号 ? 时,NGINX 会调用 ngx_http_script_start_args_code 函数,将脚本引擎的 e->is_args 标志设为 1:
这个标志在后续的脚本代码求值中永远不会被重置。问题出现在后续 set 指令引用正则捕获组时——它触发了 ngx_http_script_complex_value_code 函数。
le。因为 le.is_args = 0,长度计算函数进入 else 分支,返回未转义的原始长度。而在第二遍拷贝阶段,主引擎的 e->is_args = 1,进入 if 分支,调用 ngx_escape_uri 将每个可转义字符扩展为 3 个字节写入缓冲区。结果:分配的缓冲区太小,写入数据溢出。
具体来说,长度计算函数 ngx_http_script_copy_capture_len_code:
子引擎中 le.is_args = 0 走 else,返回原始长度。但主引擎中 e->is_args = 1 走 if,实际写入的是转义后膨胀的数据。这个差值就是堆溢出。
利用路径:堆风水 + 伪造 cleanup 指针
DepthFirst 团队开发了一套完整的 PoC,原理如下:
- 跨请求堆风水:通过 POST 请求体(body)在堆上布置特定的数据结构。因为 URI 中不能包含空字节,所以利用 body 来注入伪造的
ngx_pool_cleanup_s结构 - 溢出劫持 cleanup 指针:触发 rewrite+set 组合,利用堆溢出破坏相邻的
ngx_pool_t对象的 cleanup 链表指针 - 函数指针重定向:将 cleanup 处理函数指向
system(),参数指向攻击者控制的命令字符串 - 池销毁时触发 RCE:当 NGINX 销毁内存池时,执行伪造的 cleanup handler,调用 system() 执行任意命令
PoC 在 ASLR 关闭的 Ubuntu 24.04 上测试通过。ASLR 开启时复杂度显著增加,但理论可行。
受影响版本与修复
| 产品 | 受影响版本 | 修复版本 |
|---|---|---|
| NGINX Open Source | 0.6.27 – 1.30.0 | 1.31.0, 1.30.1 |
| NGINX Plus | R32 – R36 | R36 P4, R35 P2, R32 P6 |
受影响的版本跨度从 2008 年发布 0.6.27 到 2026 年的 1.30.0,覆盖了 18 年间几乎所有的主流 NGINX 部署。
rewrite + set 组合(带问号的 rewrite 替换串)。详情参阅 F5 官方安全公告 K000160932。
同时发现的其他三个漏洞
DepthFirst 自动系统在同一次扫描中发现了 4 个被确认的内存损坏漏洞,除了 CVE-2026-42945 外还有:
| CVE | 严重级别 | CVSS | 模块 | 问题类型 |
|---|---|---|---|---|
| CVE-2026-42945 | Critical | 9.2 | ngx_http_rewrite_module | 堆缓冲区溢出 → RCE |
| CVE-2026-42946 | High | 8.3 | ngx_http_scgi_module / uwsgi_module | 超大内存分配(~1TB)→ 崩溃 |
| CVE-2026-40701 | Medium | 6.3 | ngx_http_ssl_module | OCSP DNS 解析完成前连接关闭 → UAF |
| CVE-2026-42934 | Medium | 6.3 | ngx_http_charset_module | UTF-8 序列越界读取 |
防御与缓解措施
立即升级(首选)
升级到 NGINX 1.30.1 或 1.31.0(或 NGINX Plus 对应修复版本)。这是最彻底的解决方案。
临时缓解措施
如果无法立即升级,检查你的 NGINX 配置中是否使用 rewrite 和 set 指令。如果使用:
- 确认 rewrite 替换字符串中不包含
?(问号导致 is_args 标志置位) - 考虑用
return+map替代 rewrite 组合 - 用
try_files替代简单的 rewrite 逻辑