Announcement

👇Official Account👇

Welcome to join the group & private message

Article first/tail QR code

Skip to content

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.19.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 中的捕获组缓冲区分配逻辑:

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);  // ← 堆溢出

漏洞触发条件

nginx
# 特定的 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 触发示意(不含完整利用代码)

python
#!/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+(已集成修复补丁)

版本检查命令

bash
# 检查当前 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(强烈推荐)

bash
# 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
# 审查 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 规则过滤

nginx
# 使用 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 模块(极端情况)

bash
# 如果业务不依赖 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. 配置审计

bash
# 查找所有包含 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)

nginx
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. 系统级加固

bash
# 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.conf

4. 监控告警

bash
# 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-20702013UAF → 信息泄露5.8特定代理配置
CVE-2017-75292017整数溢出 → 内存泄露5.0Range 请求
CVE-2021-230172021DNS 解析 off-by-one7.7使用 resolver
CVE-2026-429452026堆溢出 → RCE9.2rewrite + if

CVE-2026-42945 是 NGINX 历史上评分最高、影响范围最广的漏洞。


参考资料


总结:CVE-2026-42945 是近年来 Web 服务器领域影响面最大的漏洞之一。18 年的潜伏意味着绝大多数存量部署都需要立即行动。修复路径非常清晰:升级到 1.26.3+、1.28.2+ 或 1.30.1+。如无法立即升级,应用 WAF 规则 + 重写规则审计 + systemd 沙箱化三件套可在短期内显著降低被利用的风险。

上次更新于: