2026年7月2日 · 深度技术研究
导语
2026年5月13日,安全公司 depthfirst 公开披露了 CVE-2026-42945(代号 NGINX Rift)——一个存在于 NGINX 核心脚本引擎中的堆缓冲区溢出漏洞。该漏洞自 2008 年随 NGINX 0.6.27 引入,潜伏长达 18 年,影响了从 0.6.27 到 1.30.0 的所有开源版本。更令人震惊的是,这个漏洞不是由人类安全研究员发现的,而是由 depthfirst 的自主 AI 分析系统在仅 6 小时的源代码扫描中发现的。
全球约三分之一的 Web 服务器运行 NGINX,这个漏洞的存在意味着大量基础设施可能长期处于风险之中。
一、漏洞技术原理:两阶段引擎的"信任裂痕"
1.1 NGINX 脚本引擎的两阶段模型
NGINX 的 rewrite 模块采用两阶段处理模型来处理包含正则捕获组的 URI 重写:
- 长度计算阶段:遍历所有指令,计算最终字符串所需缓冲区大小,然后一次性分配内存。
- 数据复制阶段:将实际数据写入已分配的缓冲区。
这个设计本身是合理的——预先计算大小可以避免动态扩容带来的性能开销。问题在于,两个阶段对同一个标志位的解读不一致。
1.2 根本原因:is_args 标志的状态漂移
漏洞的核心是一个名为 is_args 的标志位,它指示当前 URI 是否包含查询参数(即是否存在 ?)。
触发条件需要三条规则同时存在:
# 规则1:rewrite 的替换字符串包含 ?
rewrite ^/api/(.*)$ /internal?migrated=true;
# 规则2:后续指令使用未命名正则捕获组($1, $2 等)
set $original_endpoint $1;
# 规则3:再一条 rewrite / if / set 指令
rewrite ^/proxy/(.*)$ http://backend/$original_endpoint break;
漏洞触发链:
- 规则1 中
ngx_http_script_start_args_code函数在主引擎上设置e->is_args = 1 - 规则2 的长度计算阶段创建了一个全新的子引擎
le,le.is_args = 0(全新清零) - 长度计算函数
ngx_http_script_copy_capture_len_code基于le.is_args = 0,返回原始未转义的捕获长度 - 但数据复制阶段运行在主引擎上,
e->is_args仍为 1,触发ngx_escape_uri(..., NGX_ESCAPE_ARGS)URI 转义 +、%、&等字符从 1 字节扩展为 3 字节(如+→%2B)- 实际写入量
raw_size + 2×N远超分配的缓冲区大小raw_size→ 堆缓冲区溢出
1.3 为什么人类审计看不到
单独审查每个函数,逻辑都是"正确的":
start_args_code设置标志是合理的——URI 确实有查询参数copy_capture_len_code不转义也是合理的——子引擎认为没有查询参数copy_capture_code执行转义也是合理的——主引擎知道有查询参数
问题只出现在跨阶段、跨指令的交互中。人类代码审计很难捕捉这种"每个函数都对,但组合起来错"的微妙状态不一致。这是典型的并发/状态机 bug 类别——只是发生在单线程的两阶段处理中,更加隐蔽。
二、从溢出到 RCE:跨请求堆风水的利用链
depthfirst 公开的 PoC 展示了从堆溢出到远程代码执行的完整利用链:
2.1 利用前提
NGINX worker 进程由 master fork 产生,堆布局在每次崩溃后依然确定(因为 fork 创建相同内存布局的子进程)。这为"跨请求堆风水"提供了可预测的基础。
2.2 利用步骤
- 控制堆布局:发送多个精心构造的请求,使受害者连接的内存池(
ngx_pool_t)恰好邻接在攻击者请求池旁边 - 触发溢出:发送包含大量可转义字符(如连续
+)的 URI,使转义后数据溢出堆边界 - 覆盖 cleanup 指针:溢出数据精确覆盖相邻池偏移 64 处的
cleanup指针 - 喷洒伪造结构:通过 POST body 向堆中注入伪造的
ngx_pool_cleanup_s结构,使handler指向system()、data指向命令字符串 - 触发清理:关闭受害者连接,
ngx_destroy_pool遍历 cleanup 链表时执行任意命令
2.3 限制
当前公开的 RCE PoC 针对 ASLR 关闭的系统。在 ASLR 开启的系统上,直接可靠的 RCE 仍具挑战性,但 DoS(worker 进程崩溃重启)在所有受影响配置下均可稳定触发。
三、影响范围:比你想象的大
| 产品 | 受影响版本 |
|---|---|
| NGINX Open Source | 0.6.27 – 1.30.0 |
| NGINX Plus | R32 – R36 |
| NGINX Ingress Controller | 3.5.0 – 3.7.2; 4.0.0 – 4.0.1; 5.0.0 – 5.4.1 |
| NGINX Gateway Fabric | 1.3.0 – 1.6.2; 2.0.0 – 2.5.1 |
| NGINX Instance Manager | 2.16.0 – 2.21.1 |
| NGINX App Protect WAF | 4.9.0 – 4.16.0; 5.1.0 – 5.8.0 |
| F5 WAF for NGINX | 5.9.0 – 5.12.1 |
关键点:触发条件虽然需要特定的 rewrite 规则组合,但这种组合在 API 网关和反向代理场景中极为常见。任何使用 rewrite + 未命名捕获组 + 包含 ? 的替换字符串的配置都可能受影响。
四、修复方案
4.1 升级(推荐)
| 产品 | 修复版本 |
|---|---|
| NGINX Open Source | 1.30.1(稳定版)或 1.31.0(主线版) |
| NGINX Plus R36 | R36 P4 |
| NGINX Plus R32 | R32 P6 |
4.2 临时缓解:将未命名捕获组改为命名捕获组
# 漏洞配置
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1;
# 缓解配置(完全消除触发路径)
rewrite ^/api/(?<path>.*)$ /internal?migrated=true;
set $original_endpoint $path;
这个缓解方案之所以有效,是因为命名捕获组走的是不同的代码路径,不会触发 is_args 状态不一致的问题。
五、AI 发现漏洞的里程碑意义
5.1 六小时 vs 十八年
depthfirst 的 AI 分析系统对 NGINX 源代码进行扫描,仅耗时 6 小时就发现了该漏洞,同时还发现了另外 4 个安全问题。而同一个漏洞,人类安全社区——包括 NGINX 核心开发者、众多安全审计团队、以及多年的模糊测试——在 18 年中从未发现。
5.2 对安全行业的启示
这个案例标志着AI 辅助代码审计正在从"辅助工具"向"独立发现者"演进:
- 规模优势:AI 可以在几小时内审查数百万行 C 代码中的所有执行路径组合,而人类审计员很难追踪跨函数的状态依赖
- 无疲劳:AI 不会因为"这段代码已经存在 10 年,一定是安全的"而产生认知偏差
- 系统化:AI 可以穷举所有指令组合的排列,而人类倾向于只审查"看起来可疑"的路径
但这并不意味着人类审计将被完全取代。depthfirst 的 AI 发现了漏洞,但利用链的分析和 PoC 的编写仍然需要人类安全研究员的深度参与。
六、我的观点:18 年潜伏的三个教训
教训一:"久经考验"不等于"安全"
NGINX 的 rewrite 模块是互联网基础设施中被审查最充分的代码之一。但 18 年的社区审查、企业审计和模糊测试都没有发现这个漏洞。我们必须放弃"老代码 = 安全代码"的假设。
教训二:状态不一致是最危险的 bug 类别
单看每个函数都正确的代码,组合起来可能产生灾难性后果。这与并发编程中的竞态条件类似——只是更难发现,因为它发生在确定性的两阶段处理中。
教训三:AI 正在改变漏洞发现的博弈格局
当 AI 能在 6 小时内发现人类 18 年未发现的漏洞时,防御者需要重新思考代码审计的策略。不是"用 AI 替代人类",而是"用 AI 扩展人类的认知边界"。
免责声明
本文仅供网络安全技术研究和教育目的,所有漏洞信息来源于已公开披露的安全公告(CVE-2026-42945、F5 Advisory K000161019)及安全公司的官方技术报告。本文不包含任何可直接用于非法攻击的原始利用代码或攻击载荷,所有技术描述均以安全防御、漏洞修复和行业分析为导向。读者应遵守所在国家/地区的法律法规,仅将本文内容用于授权的安全测试和防御性安全研究。未经授权对他人系统进行渗透测试或攻击属于违法行为。
参考资料
- depthfirst 官方技术报告:NGINX Rift Technical Details
- depthfirst 完整技术分析:Achieving NGINX RCE via an 18-Year-Old Vulnerability
- Akamai 缓解指南:CVE-2026-42945 Mitigation
- CSA 研究笔记:NGINX Rift: 18-Year-Old Heap Overflow
- CVE Record:CVE-2026-42945
- PoC 代码:github.com/DepthFirstDisclosures/Nginx-Rift
浙公网安备 33010602011771号