Private Nginx Rift ASLR实验室、利用链及演示录屏
针对 CVE-2026-42945 的 RCE 概念验证,这是 NGINX 的 ngx_http_rewrite_module 中一个严重堆缓冲区溢出漏洞,于 2008 年引入。该漏洞使得攻击者能够对使用了 rewrite 和 set 指令的服务器进行未经认证的远程代码执行。
本分支扩展了原始 PoC,引入了一条绕过 ASLR 的攻击链,它将 NGINX 溢出漏洞与常见的同主机 LFI/任意文件读取原语相结合。文件读取原语用于恢复 nginx 工作进程映射、libc 以及实时的 /proc/<worker>/mem,然后远程推导出 system() 地址和可用的堆目标。
该实验室的早期版本会故意让 nginx 工作进程崩溃,使服务写入核心转储文件,然后通过文件读取原语获取并解析该核心转储,以恢复包含 ASLR 敏感信息的进程状态(包括堆目标)。在本仓库中,coreless 仅仅是“无需可读的崩溃核心转储”的简称:当前默认路径用实时 procfs 内存读取替代了崩溃核心依赖,而保留的旧版 core-guided 路径仍然使用生成的工作进程核心转储。
该漏洞——以及另外三个内存损坏问题(CVE-2026-42946、CVE-2026-40701、CVE-2026-42934)——是由 depthfirst 的安全分析系统在单次接入 NGINX 源代码后自主发现的。
想在自己的代码中找出此类问题吗?请在同系统尝试 https://depthfirst.com/open-defense。
NGINX 的脚本引擎采用两阶段处理:首先计算所需的缓冲区大小,然后复制数据。is_args 标志在 rewrite 替换包含 ? 时在主引擎上设置,但长度计算阶段在已清零的子引擎上运行。因此:
is_args = 0 → 返回原始捕获长度。is_args = 1 → 调用带 NGX_ESCAPE_ARGS 参数的 ngx_escape_uri,将每个可转义字节扩展为 3 字节。复制操作会用攻击者控制的 URI 数据溢出过小的堆缓冲区。利用跨请求的堆 Feng Shui 技术,破坏相邻 ngx_pool_t 的 cleanup 指针(通过 POST 请求体喷射,因为 URI 字节不能包含空字节),将其重定向到伪造的 ngx_pool_cleanup_s,从而在池销毁时调用 system()。
更多关于此漏洞的技术细节请阅读我们的 技术分析文章。
| 产品 | 受影响版本 | 修复版本 |
|---|---|---|
| NGINX 开源版 | 0.6.27 – 1.30.0 | 1.31.0, 1.30.1 |
| NGINX Plus | R32 – R36 | R36 P4, R35 P2, R32 P6 |
完整厂商公告:https://my.f5.com/manage/s/article/K000160932



本分支保留原始披露 PoC 完整不变,但新增了一条侧重于更现实问题的研究路径:
该漏洞能否在启用了 ASLR 的真实 x86_64 Linux 虚拟机上被利用,而不依赖硬编码的 Docker/实验室偏移地址?
本研究分支的答案是 是,但存在重要限制。有效的攻击链并未禁用 ASLR,也未使用原始硬编码的堆/libc 地址。相反,它们通过同一端口可访问的 HTTP 原语推导出运行时状态,然后从远程获取的泄露数据中选择最终的堆目标。
现在有两条支持 ASLR 的利用路径,其中无核心路径被视为当前最佳的 PoC:
nginx_rifter.py:简洁、独立的评估与集成利用入口点。其默认利用方法现在是基于 /proc/<nginx-worker>/mem 的无核心链。nginx_rifter_core_v2_1.py:保留的旧版 nginx_rifter.py 核心指导版本。适用于复现先前经虚拟机测试的崩溃核心研究路径,但不再是首选 PoC。tools/proc_mem_coreless_exploit.py:早期独立无核心研究工具。其逻辑已合并到 nginx_rifter.py 中;该工具保留用于原始实验回放。目标拓扑故意保持为同一端口:
/api/.../lfi.php?file=.../phpinfo.php当前无核心 proc-mem 路径执行以下高级步骤:
/proc/<pid>/maps 以及映射的 libc 文件。system() 地址。/proc/<worker>/mem 读取映射区域。旧版核心指导路径执行类似的基址推导,然后故意使工作进程崩溃,通过 LFI 读取生成的核心文件,并从该核心中挖掘喷射的伪清理槽。这是一个有用的研究桥梁,但依赖于核心转储策略和文件系统权限,这在默认部署中不太常见。
这与原始的确定性 Docker 演示不同。x86_64 虚拟机路径保留了正常的 Linux ASLR,并在每次运行时重新计算特定于进程的地址。Docker 无核心路径也保留了 ASLR,并移除了不常见的可读核心要求,但它依赖于必须针对目标类别验证的 procfs 权限行为。
本分支是受控的研究实验室。支持 ASLR 的链依赖于并非通用生产环境假设的强条件:
/proc/<pid>/maps、映射的 libc 以及大映射偏移处的 /proc/<pid>/mem。/proc/<pid>/maps、映射的 libc 以及生成的工作进程核心。phpinfo() 和 /proc/<pid>/maps 足以恢复 PIE/libc 基址,但不足以单独恢复此利用所需的精确堆对象/窗口。旧链使用可读的崩溃核心进行最终泄露。当前的默认链改为使用 /proc/<worker>/mem,这更接近于同一 UID 部署中真实任意文件读取的结果,因为它暴露了实时工作进程内存,而无需更改核心转储策略。
仍然存在的重要限制:
/proc/<pid>/mem 受 ptrace 限制。它在 Docker 实验室中以及针对官方 nginx:stable 镜像模型的同一 UID 检查中有效,但不同 UID 的应用程序进程在默认 procfs 保护下应当失败。当前清晰的入口点是 nginx_rifter.py,这是一个以评估为先的工具,旨在更接近授权测试人员评估已知存在漏洞的 nginx 部署(带有 HTTP 可访问的本地文件读取原语)时的实际工作方式。
与最初的演示运行器相比,nginx_rifter.py 在多个方面改进了工作流程:
--exploit,否则不会运行崩溃利用。HOST:PORT 形式提供,文件读取原语通过 --file-read-template 模块化。/proc/self/status、/proc/self/maps 以及同一 UID 工作进程 procfs 的可达性。system()、构建 ID、二进制哈希、操作系统详情以及 proc-mem/核心设置。rewrite + set 路由候选。nginx_rifter.py 中;默认方法是无核心 proc-mem。当前的 nginx_rifter.py 是独立的。它不再导入或调用先前的演示 PoC 版本或 tools/proc_mem_coreless_exploit.py 来进行评估或利用。
旧版核心指导的 nginx_rifter.py 实现被保留为 nginx_rifter_core_v2_1.py。
较新的 artifacts/nginx_rifter_v3_coreless_exploit_20260519.gif 展示了合并后的 v3 nginx_rifter.py 无核心利用路径。demo4.gif 展示了来自较早一体化核心指导工具的评估和显式利用流程。较早的 nginx-aslr-demo.gif 仍然是原始的 ASLR 启用利用演示。
已在 Ubuntu 24.04.3 LTS 上测试。
原始 ASLR 禁用的 Docker 复现:
./setup.sh — 构建容器。docker compose -f env/docker-compose.yml up — 启动存在漏洞的 NGINX 服务器。python3 poc.py --shell — 获取 Shell。关于本地 Docker 复现流程,请参阅 LAB.md。
旧版支持 ASLR 的虚拟机核心指导链:
./nginx_rifter_core_v2_1.py --target <target-host>:19321 --exploit --cmd id --fast
评估优先的 v3 工具:
./nginx_rifter.py --target <target-host>:19321
nginx_rifter.py 是当前面向实际环境的评估器和集成 PoC 入口点。其默认模式不运行崩溃利用路径。它会分析 HTTP 文件读取原语,检查范围和二进制读取,识别操作系统/nginx/libc 指纹,发现 nginx 工作进程和 ASLR 相关映射,测试同一 UID 下 /proc/<worker>/mem 的可读性,尝试通过 pid/cmdline/config 读取恢复 nginx 配置路径,标记存在漏洞的 rewrite + set 路由候选,并打印当前无核心链的可行性矩阵。
当前的 nginx_rifter.py 是独立的。它不再导入或调用先前的演示 PoC 版本或独立的 proc-mem 研究工具来进行评估或利用。
对于自定义的 LFI/下载形状:
./nginx_rifter.py --target <target-host>:19321 \
--file-read-template 'http://{host}:{port}/download?path={path_url}{range_query}'
利用执行是显式的:
./nginx_rifter.py --target <target-host>:19321 --exploit --cmd id --fast
# 仅用于发现目的的利用冒烟测试,不进行喷射/探测
./nginx_rifter.py --target <target-host>:19321 --exploit --derive-only --cmd id
默认利用方法是无核心 proc-mem。以下选项已默认选定,因为它们在无核心 Docker 验证中最为可靠:
--exploit-method proc-mem
--target-len 6
--max-region 268435456
旧版可读核心模式仍可用于比较,但带版本号的脚本在复现旧路径时更清晰:
./nginx_rifter_core_v2_1.py --target <target-host>:19321 --exploit --cmd id --fast
旧版录制友好的终端演示:
./demo_ctf_exploit_v1_9.py --host <target-host>:19321 --cmd id --clear
demo_ctf_exploit_v1_9.py 是较旧的面向操作者的核心指导实验室路径运行器。当前首选的 PoC 入口点是 nginx_rifter.py。
默认的文件读取原语是本分支的 PHP 路径:
/lfi.php?file=<path>&offset=<n>&length=<n>
对于其他已知存在漏洞的 CTF 应用或测试平台,文件读取向量是模块化的:
./nginx_rifter.py --target <target-host>:19321 --exploit --cmd id \
--target-profile generic \
--file-read-template 'http://{host}:{port}/download?path={path_url}{range_query}'
模板支持 {host}、{port}、{path_url}、{offset}、{length} 和 {range_query}。通用配置文件会跳过本分支实验室特有的 nginx 配置断言,但默认利用仍然需要相同的底层能力:可读的 nginx 工作进程 /proc 映射、可读的 libc 以及可读的 /proc/<worker>/mem。phpinfo() 是可选的;使用 --phpinfo-path '' 禁用它。
现实性说明:LFI/文件读取漏洞类别以及同主机 nginx/PHP-FPM 部署模型是现实的。与之前的崩溃核心链相比,proc-mem 链更现实,因为它不需要启用或读取工作进程核心转储。它仍然不是一个通用的默认生产环境假设:同一 UID 进程布局、procfs/Yama 策略、容器命名空间设置以及文件读取原语的质量决定了 /proc/<worker>/mem 是否可达。
无 LFI 的研究探测:
python3 tools/non_lfi_leak_probe.py --target <target-host>:19321
python3 tools/non_lfi_active_response_probe.py --target <target-host>:19321
这些是负向研究探测,而非利用入口点。它们在不使用 LFI、phpinfo、procfs、核心、调试器访问或硬编码实时 ASLR 基址的情况下,练习被动反射接收端和初始延迟响应过度读取形状。
其他实验室说明和运行日志位于 docs/ 目录下,特别是:
docs/CTF_PLAN.mddocs/CTF_FINDINGS.mddocs/CTF_TESTS.mddocs/CTF_EXPERIMENT_LOG.mddocs/DEMO_POC_IMPROVEMENTS.mddocs/KNOWN_LAYOUT_PATTERNS.mddocs/VAGRANT_ESXI.mddocs/CORELESS_ASLR_PLAN.mddocs/CORELESS_ASLR_FINDINGS.mddocs/NON_LFI_ASLR_BYPASS_LOG.mddocs/DEMO_RECORDING_WORKFLOW.md