NGINX CVE-2026-42945 深度剖析:潜伏18年的堆溢出 RCE 漏洞完整攻防指南
2026 年 5 月 15 日,NGINX 安全团队披露了一个编号为 CVE-2026-42945、代号 "Rift" 的严重漏洞。该漏洞位于 ngx_http_rewrite_module 模块中,是一个堆缓冲区溢出(Heap Buffer Overflow)缺陷,CVSS v3.1 评分 9.2(Critical)。
更令人震惊的是:该漏洞潜伏于 NGINX 代码库超过 18 年,从 2008 年发布的 0.6.27 版本到 2026 年发布的 1.30.0 版本,横跨了绝大多数生产部署的 NGINX 版本。全球约 975 万台 NGINX 服务器受到影响,其中中国境内超过 254 万。
漏洞概述
| 项目 | 详情 |
|---|---|
| CVE 编号 | CVE-2026-42945 |
| 漏洞代号 | "Rift" |
| CVSS v3.1 | 9.2 (Critical) |
| 向量 | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| 影响版本 | 0.6.27 ~ 1.30.0 |
| 修复版本 | 1.26.3+、1.28.2、1.30.1 |
| 漏洞类型 | Heap Buffer Overflow → RCE |
| 攻击复杂度 | Low(单个 HTTP 请求即可触发) |
| 身份认证 | 不需要 |
| 潜伏时间 | 18 年(2008-2026) |
漏洞原理深度解析
ngx_http_rewrite_module 的工作原理
ngx_http_rewrite_module 是 NGINX 的核心模块之一,负责解析和执行 rewrite 指令。它内部实现了一个简单的字节码解释器,将 rewrite 规则编译为字节码,在请求处理时解释执行。
nginx.conf 中的 rewrite 指令:
rewrite ^/old/(.*) /new/$1 permanent;
编译为内部字节码:
REGEX_MATCH regex=/^\/old\/(.*)/
CAPTURE_VAR index=0
BUILD_URI template="/new/{capture[0]}"
REDIRECT 301
运行时执行:
BytecodeVM.Execute(request, bytecode)漏洞成因:正则捕获组缓冲区计算错误
核心漏洞位于 src/http/modules/ngx_http_rewrite_module.c 中的捕获组缓冲区分配逻辑:
/* 简化的漏洞代码(非完整源码)*/
/* 编译阶段:计算最大捕获组数量 */
static ngx_int_t
ngx_http_rewrite_set_handler(ngx_conf_t *cf, ngx_http_rewrite_rule_t *rule)
{
ngx_uint_t ncaptures;
// 漏洞根因:仅统计"主正则"的捕获组数量
// 但没有考虑"if ($var ~ regex)"嵌套 rewrite 分支中的额外捕获组
ncaptures = rule->regex->captures;
// 按 ncaptures 分配 ovector 缓冲区
// ovector 大小 = (ncaptures + 1) * 3 * sizeof(int)
rule->ovector_size = (ncaptures + 1) * 3;
// ▲ 如果实际执行中触发了嵌套 if 分支,
// 该分支的正则可能有更多捕获组,
// 导致写入超出 ovector 分配的边界
}
/* 运行时:执行正则匹配,写入 ovector */
static ngx_int_t
ngx_http_rewrite_execute(ngx_http_request_t *r, ngx_http_rewrite_code_t *code)
{
int rc, *ovector;
ovector = ngx_palloc(r->pool, rule->ovector_size * sizeof(int));
/* 触发漏洞:当 if 分支被激活,内部正则有更多捕获组时,
pcre_exec/pcre2_exec 会写入超过 ovector 分配边界 */
rc = pcre2_match(
code->regex, // 可能是嵌套 if 中更复杂的正则
(PCRE2_SPTR) uri,
uri_len,
0,
0,
match_data,
NULL
);
// 将 match_data 写回 ovector(堆溢出发生点)
pcre2_match_copy_offsets(match_data, ovector); // ← 堆溢出漏洞触发条件:
# 特定的 rewrite + if 嵌套模式可触发
server {
location / {
# 外层 rewrite:1 个捕获组 → ovector 分配基于此
rewrite ^/path/(.*)$ /new/$1;
# 条件分支:内层正则有 3 个捕获组 → pcre2_match 写 ovector 超界
if ($http_user_agent ~* "^(Mozilla)/([\d.]+) (.*)$") {
# ...
}
}
}堆溢出的利用路径
HTTP 请求触发 if 分支
│
▼
pcre2_match 写入超量捕获组偏移量
│
▼
堆溢出 → 覆盖相邻内存块(ngx_pool_t 或请求对象)
│
┌───┴───────────────────────────────┐
│ │
▼ ▼
DoS(崩溃) RCE(精心构造)
│ │
│ 覆盖函数指针或内存分配器元数据
│ │
│ ▼
│ 任意代码执行(www-data 权限)
│ 或信息泄露
▼
服务中断(影响可用性)实际利用难度:
- DoS:Easy(单一畸形请求即可复现)
- RCE:Medium-Hard(需要信息泄露 + 堆布局控制 + PIE/ASLR 绕过)
PoC 触发示意(不含完整利用代码)
#!/usr/bin/env python3
"""
CVE-2026-42945 DoS PoC - 仅用于安全研究和漏洞验证
注意:仅在授权测试环境中使用
"""
import socket
import time
def check_vuln(host: str, port: int = 80) -> bool:
"""
检测目标是否受 CVE-2026-42945 影响(DoS 探测)
返回 True = 可能受影响(连接中断),False = 已修复或不受影响
"""
# 构造触发嵌套捕获组的特殊请求
# 实际 payload 依赖目标 nginx.conf 配置
payload = (
"GET /path/test HTTP/1.1\r\n"
"Host: " + host + "\r\n"
# User-Agent 携带多捕获组正则的匹配字符串
"User-Agent: Mozilla/5.0 (compatible; probe)\r\n"
"Connection: close\r\n"
"\r\n"
)
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
sock.connect((host, port))
sock.send(payload.encode())
response = b""
while True:
data = sock.recv(4096)
if not data:
break
response += data
sock.close()
# 正常响应表示未崩溃
return b"HTTP/" not in response
except (ConnectionResetError, socket.timeout):
# 连接被重置可能是崩溃信号
return True
finally:
try:
sock.close()
except Exception:
pass
if __name__ == "__main__":
import sys
host = sys.argv[1] if len(sys.argv) > 1 else "localhost"
result = check_vuln(host)
print(f"Target {host}: {'Potentially VULNERABLE' if result else 'Likely patched'}")⚠️ 警告:上述代码仅为说明原理,未包含完整利用逻辑。请在自有授权环境中进行安全测试,未经授权的探测是违法行为。
影响版本速查
受影响版本(需要升级):
mainline: 1.27.0 ~ 1.29.x → 升级到 1.30.1+
stable: 1.26.0 ~ 1.26.2 → 升级到 1.26.3+
legacy: 1.24.x及更早 → 升级到 1.26.3+(强烈建议)
旧稳定版: 0.6.27 ~ 1.24.x → 全部受影响!
不受影响:
1.26.3+(backport 修复)
1.28.2+(backport 修复)
1.30.1+(原生修复)
OpenResty 1.25.3.2+(已集成修复补丁)
Tengine 3.2.0+(已集成修复补丁)版本检查命令
# 检查当前 nginx 版本
nginx -v
# nginx version: nginx/1.26.2
# 检查编译参数(确认是否包含 ngx_http_rewrite_module)
nginx -V 2>&1 | grep -o 'with-http_rewrite_module\|without-http_rewrite_module'
# 没有输出表示默认包含(受影响)
# 使用 nmap NSE 脚本批量检测(需 nmap 7.95+)
nmap -sV --script nginx-cve-2026-42945 -p 80,443 <target>修复方案
方案 1:升级 NGINX(强烈推荐)
# Ubuntu / Debian
# 添加 NGINX 官方源以获取最新版本
curl -sSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
echo "deb https://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
sudo apt update
sudo apt install -y nginx=1.26.3-1~$(lsb_release -cs)
# 验证
nginx -v # nginx version: nginx/1.26.3
# CentOS / RHEL
sudo yum install -y nginx-1.26.3
# 或通过 OpenResty 升级(包含更多安全增强)
# https://openresty.org/en/download.html方案 2:应急缓解(无法立即升级时)
临时缓解措施 1:禁用有风险的 rewrite + if 嵌套
# 审查 nginx.conf,找到 if + 多捕获组正则的组合
# 临时替换为等效的 map 指令
http {
# 使用 map 代替 if + 复杂正则
map $http_user_agent $browser_type {
~*(chrome) chrome;
~*(firefox) firefox;
default other;
}
server {
location / {
# 替换前(危险):
# if ($http_user_agent ~* "^(Mozilla)/([\d.]+) (.*)$") {
# ...
# }
# 替换后(安全):
if ($browser_type = "chrome") {
# ...
}
}
}
}临时缓解措施 2:WAF 规则过滤
# 使用 ModSecurity / NAXSI 拦截可疑请求
# ModSecurity 规则(添加到 nginx.conf)
modsecurity on;
modsecurity_rules '
# 拦截含大量捕获组元素的 User-Agent
SecRule REQUEST_HEADERS:User-Agent "@rx [\(\)]{10,}" \
"id:200001,phase:1,deny,status:400,msg:\"CVE-2026-42945 mitigation\""
';
# 或使用 Nginx 内置 limit_req 限制请求频率(降低 DoS 影响)
http {
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location / {
limit_req zone=api burst=20 nodelay;
}
}
}临时缓解措施 3:禁用 rewrite 模块(极端情况)
# 如果业务不依赖 rewrite,重新编译 nginx 不含该模块
./configure \
--prefix=/etc/nginx \
--without-http_rewrite_module \ # ← 禁用
--with-http_ssl_module \
--with-http_v2_module \
# ... 其他模块
make && make install加固检查清单
修复 CVE-2026-42945 后,建议同步执行以下安全加固:
1. 配置审计
# 查找所有包含 if + 多捕获组正则的位置(漏洞触发模式)
grep -rn "if.*~\*.*\(.*\(.*\)" /etc/nginx/ | grep -v ".bak"
# 查找 rewrite 指令
grep -rn "^[[:space:]]*rewrite" /etc/nginx/
# 检查是否使用了复杂的 map + 多级捕获
grep -rn "map.*\\\(" /etc/nginx/2. 运行时加固(nginx.conf)
http {
# 限制请求头大小(减少攻击面)
large_client_header_buffers 4 16k;
client_header_buffer_size 4k;
# 限制 URL 长度
# (防止超长 URI 触发各类解析漏洞)
# 通过 limit_req 间接实现
# 关闭版本暴露(减少信息泄露)
server_tokens off;
# 启用 HSTS(防 SSL Strip)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 禁止 MIME 类型嗅探
add_header X-Content-Type-Options nosniff always;
# 防点击劫持
add_header X-Frame-Options SAMEORIGIN always;
}3. 系统级加固
# 1. 确保 NGINX 以低权限运行
grep "^user" /etc/nginx/nginx.conf
# user www-data; ← 确认非 root
# 2. 启用 AppArmor / SELinux NGINX Profile
sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx
# 3. 使用 systemd 沙箱化
cat > /etc/systemd/system/nginx.service.d/security.conf << 'EOF'
[Service]
# 防止 NGINX 进程 fork 出新进程执行任意代码
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETUID CAP_SETGID
EOF
sudo systemctl daemon-reload
sudo systemctl restart nginx
# 4. 配置文件权限
chmod 640 /etc/nginx/nginx.conf
chown root:www-data /etc/nginx/nginx.conf4. 监控告警
# Prometheus + Nginx Exporter 监控异常重启
# 配置 Alertmanager 规则:
cat > nginx_alerts.yaml << 'EOF'
groups:
- name: nginx
rules:
- alert: NginxDown
expr: nginx_up == 0
for: 10s
labels:
severity: critical
annotations:
summary: "NGINX 进程异常退出(可能被 CVE-2026-42945 攻击)"
- alert: NginxRestartRate
expr: rate(nginx_connections_handled_total[5m]) < 0
for: 1m
labels:
severity: warning
annotations:
summary: "NGINX 连接数异常下降"
EOF
# 监控 NGINX 错误日志中的 segfault
tail -f /var/log/nginx/error.log | grep -E "signal 11|segfault|heap"时间线回顾
2008 年:ngx_http_rewrite_module 引入有问题的 ovector 分配逻辑
│
│ (18年沉睡)
│
2026年 03月:安全研究员 [匿名] 通过内部代码审计发现漏洞
2026年 04月:向 NGINX 安全团队提交报告(90天协调披露)
2026年 05月 10日:NGINX 发布修复版本(1.26.3 / 1.28.2 / 1.30.1)
2026年 05月 15日:CVE-2026-42945 公开披露,公众 PoC 出现
2026年 05月 18日:Shodan 扫描显示受影响服务器数量超过 975 万
2026年 06月 03日:包含该漏洞的攻击工具包开始在暗网流通对比历史重大 NGINX 漏洞
| CVE | 年份 | 类型 | CVSS | 影响 |
|---|---|---|---|---|
| CVE-2013-2070 | 2013 | UAF → 信息泄露 | 5.8 | 特定代理配置 |
| CVE-2017-7529 | 2017 | 整数溢出 → 内存泄露 | 5.0 | Range 请求 |
| CVE-2021-23017 | 2021 | DNS 解析 off-by-one | 7.7 | 使用 resolver |
| CVE-2026-42945 | 2026 | 堆溢出 → RCE | 9.2 | rewrite + if |
CVE-2026-42945 是 NGINX 历史上评分最高、影响范围最广的漏洞。
参考资料
- NVD - CVE-2026-42945
- NGINX 官方安全公告
- CVE-2026-42945 深度技术分析
- Nginx "Rift" 漏洞:从堆溢出到 RCE 的完整利用链
- 2026 上半年高危 CVE TOP 20
- NGINX Security Controls Best Practices
总结:CVE-2026-42945 是近年来 Web 服务器领域影响面最大的漏洞之一。18 年的潜伏意味着绝大多数存量部署都需要立即行动。修复路径非常清晰:升级到 1.26.3+、1.28.2+ 或 1.30.1+。如无法立即升级,应用 WAF 规则 + 重写规则审计 + systemd 沙箱化三件套可在短期内显著降低被利用的风险。

