2026 年 7 月 15 日,nginx 发布 1.30.4(stable)与 1.31.3(mainline),修掉了一个 CVSS 9.2 的堆缓冲区溢出 CVE-2026-42533。攻击者无需任何认证,构造特定 HTTP 请求即可触发;默认配置下的后果是 worker 进程崩溃重启(拒绝服务),在 ASLR 被关闭或可绕过的环境里则有升级为远程代码执行的可能。

触发条件:map + 正则 + 捕获组

根因不在 HTTP 解析器,而在 nginx 的两趟脚本求值机制:算长度的那一趟和真正写值的那一趟共享同一份 PCRE 捕获状态。当一条带正则的 map 指令恰好在两次引用同一个捕获组(比如 $1)之间被求值时,捕获状态被悄悄覆盖,两趟对缓冲区大小的判断随之不一致,于是写越界。

换句话说,不是每台 nginx 都能被打中,但受影响的版本区间宽得离谱:0.9.6 一直到 1.30.3(stable)/ 1.31.2(mainline),也就是 2011 年以来的绝大多数版本。商业版方面 NGINX Plus R33–R36 受影响(修复于 R36 P7),37.0.0.1–37.0.2.1 修复于 37.0.3.1。

为什么现在必须动手

发现者在补丁发布后刻意压了 21 天才公开完整利用细节和 PoC,给管理员留升级窗口——这个窗口早已过去。同一年的另一个例子更能说明速度:2026 年 5 月修复的 CVE-2026-42945(ngx_http_rewrite_module 堆溢出,被称作 "Nginx Rift"),补丁发布约一周内就出现了在野利用;当时估计公网上约有 570 万台 nginx 跑着可能受影响的版本。半年内两个同类问题,说明「装完就不再动」的 Web 服务器是真实风险。

三步自查

  • 查版本,但别只信 nginx -v:Debian/Ubuntu 的发行版包会把安全补丁回合(backport)到旧版本号上,版本号停在 1.24.0 不代表没修。用发行版包的看 apt policy nginx 的包版本尾号、并用 apt changelog nginx 确认是否提到该 CVE;用官方源或自己编译的,才直接和 1.30.4 / 1.31.3 比。
  • 查配置里有没有带正则的 mapgrep -rn "map " /etc/nginx/,重点看匹配项里以 ~ 开头的正则,以及同一条请求链路上多次引用 $1 这类捕获组的写法。没有这种组合,风险面会小很多。
  • 查日志里 worker 是不是在无声重启grep -i "worker process.*exited on signal" /var/log/nginx/error.log。反复出现 signal 11 是典型症状,而在用户那一侧它只表现为「偶发 502」,非常容易被当成网络抖动放过去。

升级动作

发行版包:sudo apt update && sudo apt install --only-upgrade nginx,然后 sudo nginx -t && sudo systemctl reload nginx。官方源或自编译:升到 1.30.4 / 1.31.3 及以上,nginx -t 通过再 reload。reload 不中断现有连接,不必挑维护窗口。顺带一提,这两个版本还一起修掉了 CVE-2026-60005(ngx_http_slice_module 内存泄露)与 CVE-2026-56434(ngx_http_ssi_module 释放后使用),升一次解决三个。

把「能自己打补丁」当成选型条件

应对这类公告的速度,取决于你有没有 root、能不能自己决定什么时候 reload。共享主机上只能等服务商排期,而且你通常看不到完整的 error.log;在自己的 VPS 上,从看到公告到 reload 完成十分钟足够。SharkCloud 的日本、新加坡、香港、美国节点都是独立实例,系统与 Web 服务版本完全由你掌控,安全公告出来当天就能处理完,而不是排进下一个维护窗口。