导语:你以为NGINX很安全?15年的洞了解一下。近日,安全研究员Stan Shaw披露了一个藏在NGINX脚本引擎深处的严重漏洞——攻击者只需发一个HTTP请求,就能在特定配置下实现预认证远程代码执行。更可怕的是,这个洞从2011年就存在了,一直没被发现。
漏洞概述
CVE-2026-42533,由F5官方及NGINX团队于2026年7月15日发布安全公告并释出修复补丁。
漏洞本质:NGINX的脚本引擎在处理带有正则匹配的map指令时,未能在”两步走”(LEN长度计算与VALUE赋值)评估过程中保存和恢复捕获状态(r->captures)。攻击者通过构造特定长度和内容的请求,可引发堆缓冲区溢出或内存信息泄露,两相结合可在绕过ASLR后实现远程代码执行。
受影响的版本从NGINX 0.9.6(2011年3月21日map指令引入正则支持)一直延续到1.30.3稳定版 / 1.31.2主线版,长达15年。
漏洞原理:两步走评估模型的致命缺陷
引擎的两遍式评估
NGINX的脚本引擎在编译包含变量引用的表达式时,采用”两步走”评估模式。以ngx_http_complex_value()函数为例(src/http/ngx_http_script.c):
第一步(LEN Pass):遍历操作码序列,累加每个片段的字符长度,据此分配精确大小的缓冲区。
第二步(VALUE Pass):用完全相同的操作码序列,向已分配的缓冲区写入实际内容。
这个设计的隐含假设是:每个操作码在两步中产生的长度完全一致。如果LEN阶段认为某个片段占3字节,VALUE阶段却写入了200字节——缓冲区就溢出了。
捕获状态被污染的根因
当一个location块使用正则匹配时,匹配结果(捕获组的偏移量和指向匹配字符串的指针)存储在请求对象的r->captures和r->captures_data中。表达式中的$1引用编译成操作码,通过读取这些字段找到捕获子串的偏移和长度。
问题来了——这些字段是共享的可变状态。任何后续的正则匹配都会直接覆盖它们,不会保存和恢复原有的捕获上下文。
当map指令使用正则模式时,评估map变量会触发ngx_http_regex_exec(),将结果直接写入请求的捕获状态,覆盖掉原始location匹配的捕获数据。而ngx_http_complex_value()和ngx_http_map_find()都没有在任何时间点保存或恢复捕获状态。
用一个表达式来说明:
"$1=$map_var=$1" # 假设 $map_var 是带正则的map变量
LEN阶段:
- 第一个读取原始捕获:3字节(URI路径”abc”)
map_varr->captures- 第二个读取被污染的捕获:200字节(map输入字符串)
- LEN总长度:3 + 1 + 6 + 1 + 200 = → 分配211字节缓冲区
VALUE阶段:
- 第一个读取被污染的捕获:写入200字节
map_var- 第二个读取被污染的捕获:再写入200字节
- VALUE总写入:200 + 1 + 6 + 1 + 200 = → 写入211字节缓冲区
结果:197字节的堆溢出,溢出内容完全由攻击者通过POST body控制。

信息泄露:ASLR绕过的单次请求方案
同样的漏洞机制,反过来用则构成信息泄露。
如果map的输入比原始捕获更短,捕获状态被污染后,$1在VALUE阶段会比LEN阶段更小。缓冲区按LEN的长度分配,但只写入少量字节,缓冲区尾部保留的是堆内存残留数据。
用8160字节的URI路径配合1字节的header触发map regex,可分配8161字节的缓冲区但只初始化2字节。剩余8159字节是nginx池分配器的残留内存,其中可靠地包含libc指针和堆指针,足以在一次未认证GET请求内计算出ASLR基址。
影响范围:13个调用点,横跨HTTP和Stream模块
该漏洞并非只影响某一个函数。”两步走”LEN/VALUE模式在NGINX代码中有至少13个独立的调用点,分布在9个源文件中。每个站点都有自己独立的LEN循环、分配和VALUE循环,都通过相同的操作码(copy_capture_len_code和copy_capture_code)读取捕获,且没有任何一个在两次遍历之间保存或恢复r->captures。
受影响的核心位置包括:
跨指令触发:最常见的利用场景
捕获引用和map变量不需要出现在同一个指令中。proxy、fastcgi、scgi、uwsgi、grpc等模块各自有独立的两遍循环来构建上游请求,这个循环在location块内的所有指令上运行,使用单一缓冲区分配。
一个完全合法的常见配置就是天然漏洞:
location ~ "^/api/(.+)$" { proxy_set_header X-Path "$1"; proxy_set_header X-Check "$map_var"; # map_var是带正则的map变量 proxy_pass http://backend;}
X-Path中的$1先被添加到LEN/VALUE循环中,X-Check中的map_var在LEN阶段触发regex匹配并污染捕获状态,导致后续$1在VALUE阶段写入的内容超过LEN阶段测量的大小,形成溢出。
漏洞危害评估
| 维度 | 评估 |
|---|---|
| 利用前提 | 无需认证,无需客户端证书,仅需发送特定构造的HTTP请求 |
| 利用难度 | 信息泄露可在单次GET请求内完成ASLR绕过;溢出触发可靠率100%(10/10测试) |
| 影响范围 | 预认证远程代码执行,可完全接管NGINX服务器 |
| 触发条件 | 配置中同时存在:①location/reWrite/server_name正则捕获(产生$1等引用);②正则map变量(在同一表达式或同一location块后续指令中被评估) |
| 历史跨度 | 2011年3月21日至2026年7月15日(约15年) |
修复方案
开源版NGINX:
商业版NGINX Plus:
立即行动:
- 升级NGINX
- 使用配置扫描工具检查是否存在漏洞配置:https://github.com/0xCyberstan/CVE-2026-42533-Config-Scanner
- 如果无法立即升级,审查配置中是否同时存在正则捕获和正则map变量的组合,考虑重构以避免该模式
重要提示:近期发布的其他NGINX相关CVE(CVE-2026-42945、CVE-2026-9256、CVE-2026-42055、CVE-2026-48142)均不修复此漏洞,必须升级到上述指定版本。
总结
CVE-2026-42533是一个教科书级别的设计级漏洞——NGINX的脚本引擎在设计之初没有考虑到共享可变状态(r->captures)会在两次评估遍历之间被污染,而这个污染在特定配置下可以转化为精确控制的堆溢出和内存泄露,最终实现预认证RCE。
15年,13个调用点,一条HTTP请求就能打穿。对于手里握着NGINX的企业来说,这大概是今年最需要紧急打补丁的一个漏洞了。



seo优化_前端开发_渗透技术








