Security Research · 广州翊柯信息技术有限公司

NGINX 15 年隐患曝光:CVE-2026-42533 为何能从一次正则匹配演变成堆溢出

影响 0.9.6 至 1.31.2,满足特定配置时可能导致拒绝服务、内存泄露甚至远程代码执行。

广州翊柯信息技术有限公司2026-07-21
“NGINX 计算缓冲区大小时看到的是一份数据,真正写入时看到的却可能是另一份数据。” — 技术分析

漏洞概述

2026 年 7 月 15 日,NGINX 发布 1.30.4 稳定版和 1.31.3 主线版,修复编号为 CVE-2026-42533 的堆缓冲区溢出漏洞。

该问题影响 NGINX Open Source 0.9.6 至 1.31.2。NGINX 官方将其评为 Major,F5 给出的 CVSS v4.0 评分为 9.2。攻击者无需登录,但服务器必须存在特定的正则map、捕获变量和求值顺序,才可能进入危险路径。

这不是“所有旧版 NGINX 都能被直接接管”,但也绝不只是一个普通的配置错误。风险核心在于:长度计算阶段和实际写入阶段可能读取到不同的变量内容。

漏洞信息

项目内容
漏洞编号CVE-2026-42533
漏洞类型堆缓冲区溢出
官方评级Major
CVSS v4.09.2
影响版本NGINX 0.9.6 至 1.31.2
修复版本1.30.4+、1.31.3+
攻击条件无需认证,但依赖特定配置
可能后果Worker 崩溃、拒绝服务、内存泄露、潜在代码执行

NGINX 官方将漏洞描述为使用map和正则表达式时发生缓冲区溢出;F5 表示该问题可能造成拒绝服务,并可能进一步触发代码执行。

一次 map 正则,为什么会影响内存安全

NGINX 在生成包含变量的字符串时,通常分成长度计算和实际写入两个阶段。

读取变量 ↓ 计算最终字符串长度 ↓ 申请对应大小的缓冲区 ↓ 再次读取变量并复制内容

正常情况下,两次读取的变量应该完全相同。问题在于,正则捕获结果并不是永久绑定在某一条location或rewrite上,而是保存在请求的共享捕获状态中。

例如,正则location先产生$1:

location ~ ^/api/(.+)$ { # $1 保存路径捕获内容 }

后续如果求值一个使用正则表达式的map,新的正则匹配可能覆盖此前保存的捕获结果:

map $http_user_agent $client_type { ~*(.+) matched; default normal; }

于是可能出现长度按捕获 A 计算、内存按 A 申请,但真正写入时已经读取捕获 B 的情况。如果 B 比 A 长,写入可能越过缓冲区边界;如果 B 比 A 短,未被覆盖的尾部内存可能被错误返回,形成信息泄露。

这个问题其实早有迹象

2014 年,NGINX Trac 工单 #564 就记录过类似现象:正则map被求值后,原本由rewrite产生的$1被覆盖,导致跳转地址出现错误。

当时它表现为配置结果错误。现在暴露出的危险在于:当捕获状态变化发生在“长度计算”和“实际写入”之间,逻辑错误就会升级为内存安全漏洞。

单独看,map 改变 $1 似乎只是配置行为;进入两阶段缓冲区处理后,它才真正变成堆溢出。

哪些配置需要重点排查

风险通常不是由某一个关键词单独产生,而是多个条件组合。

存在正则捕获来源

location ~ ... server_name ~ ... rewrite ... if ($variable ~ ...) ...

这些规则可能产生$1、$2或命名捕获变量。

存在正则 map

map $request_uri $route_type { ~^/api/(.+)$ api; default normal; }

普通字符串匹配的map不等于正则map,重点是以~或~*开头的匹配规则。

捕获变量和 map 输出共同参与请求构造

map $http_user_agent $client_type { ~*(.+) matched; default normal; } location ~ ^/api/(.+)$ { proxy_set_header X-Path "$1"; proxy_set_header X-Client-Type "$client_type"; proxy_pass http://backend; }

关键不在于两者是否写在同一行,而在于它们是否最终进入同一个两阶段缓冲区,以及捕获变量是否先于 map 输出变量求值。

官方补丁为什么不只修改 map

官方 PR #1561 没有简单地保存和恢复$1,而是直接加强整个脚本执行过程。

  • 增加缓冲区结束边界:脚本引擎新增e->end,记录已分配缓冲区的真实结束位置。
  • 每次写入前检查空间:固定文本、普通变量和捕获变量复制前,都必须确认缓冲区仍有足够空间。
  • 按实际写入长度返回结果:实际内容较短时,结果字符串按真实写入量截断,不再把未初始化的尾部内存一起返回。

相关保护还被加入 proxy、FastCGI、SCGI、uWSGI、gRPC、index 和 try_files 等直接脚本求值路径。这是针对两阶段脚本执行模型的整体加固。

是否真的能够远程代码执行

F5 的官方结论是,攻击者可以远程、无需认证地触发漏洞;利用需要服务器满足特定配置条件;漏洞可能导致 NGINX Worker 崩溃和拒绝服务;在 ASLR 被关闭或能够被绕过时,可能进一步执行代码。

漏洞报告者 Stan Shaw 则表示,已经构造出信息泄露和堆溢出两种攻击原语,并在特定 Linux 环境中将其组合为预认证远程代码执行链。

更准确的结论不是“所有旧版 NGINX 都能直接 RCE”,而是:该漏洞已经具备远程代码执行所需的内存破坏能力,但实际利用仍取决于 NGINX 配置、运行环境及内存防护条件。

如何快速排查

查看版本和编译信息

nginx -v nginx -V readlink -f "/proc/$(cat /run/nginx.pid)/exe"

导出完整配置

nginx -T > /tmp/nginx-full-config.txt 2>&1

查找正则 map

grep -nE '^[[:space:]]*map[[:space:]]' \ /tmp/nginx-full-config.txt

检查对应map中是否存在~或~*正则规则。

查找捕获变量和常见来源

grep -nE '\$[1-9]|\(\?<[^>]+>|\(\?P<[^>]+>' \ /tmp/nginx-full-config.txt grep -nE 'location[[:space:]]+~|server_name[[:space:]]+~|rewrite[[:space:]]|if[[:space:]]*\(.*~' \ /tmp/nginx-full-config.txt

这些命令只能找出候选配置,不能判断变量是否进入同一个缓冲区,也不能还原真实的求值顺序。简单搜索到$1和map,不能直接判定服务器已经可利用。

修复方法与验证

NGINX Open Source 应升级至稳定版 1.30.4 或更高、主线版 1.31.3 或更高。配置排查只能帮助确定处置优先级,不能代替升级。

升级前备份

BACKUP_DIR="/root/nginx-backup-$(date +%Y%m%d-%H%M%S)" mkdir -p "$BACKUP_DIR" cp -a /etc/nginx "$BACKUP_DIR/" nginx -T > "$BACKUP_DIR/nginx-full-config.txt" 2>&1 nginx -V > "$BACKUP_DIR/nginx-build.txt" 2>&1

升级后验证

nginx -v nginx -t systemctl reload nginx systemctl status nginx --no-pager journalctl -u nginx --since "24 hours ago" \ | grep -Ei 'segfault|core dumped|worker process exited|signal'

容器环境必须进入实际运行的容器确认版本。更新宿主机不会自动替换容器中的旧 NGINX。

与 CVE-2026-42945 有什么区别

对比项CVE-2026-42945CVE-2026-42533
披露时间2026 年 5 月2026 年 7 月
官方评级MediumMajor
主要位置rewrite 模块正则 map 与脚本求值路径
影响版本0.6.27 至 1.30.00.9.6 至 1.31.2
修复版本1.30.1、1.31.01.30.4、1.31.3
核心问题rewrite 长度处理异常两阶段之间变量或捕获状态变化

此前升级到 1.30.1、1.30.2、1.30.3、1.31.0、1.31.1 或 1.31.2,仍不能修复 CVE-2026-42533。

结论

CVE-2026-42533 影响范围很广,但风险判断不能只看版本号。真正需要确认的是是否存在正则map、是否使用编号或命名捕获、捕获变量和 map 输出是否进入同一缓冲区、变量求值顺序是否满足危险关系,以及当前运行的二进制是否已经包含修复。

预先计算出来的缓冲区长度,并不一定等于真正写入时需要的长度。

NGINX 官方最终没有继续相信这个假设,而是在写入阶段增加了真正的边界保护。对于仍运行受影响版本的服务器,应优先升级并完成配置与运行状态验证。

参考来源

  1. NGINX 官方安全公告
  2. NGINX 1.30.4 与 1.31.3 发布记录
  3. F5 安全通告 K000162097
  4. NGINX 官方修复 PR #1561
  5. NGINX Trac 历史工单 #564
  6. 漏洞报告者 Stan Shaw 的技术分析