rheodev/CVE-2026-42945

GitHub: rheodev/CVE-2026-42945

对 NGINX Rift(CVE-2026-42945)这一潜伏 18 年的堆缓冲区溢出漏洞进行完整根因分析,并提供 Docker 复现环境和 DoS PoC 脚本。

Stars: 17 | Forks: 4

# CVE-2026-42945 - NGINX Rift 漏洞分析与复现 ## 概述 CVE-2026-42945(代号 "NGINX Rift")是一个存在于 NGINX `ngx_http_rewrite_module` 中的**堆缓冲区溢出**漏洞,CVSS v4 评分 **9.2(Critical)**。 该漏洞由 depthfirst 安全研究团队于 2026 年 4 月发现,自 2008 年引入 NGINX 0.6.27 版本以来已潜伏 **18 年**。 ## 影响范围 - NGINX Open Source 0.6.27 ~ 1.30.0 - NGINX Plus R32 ~ R36 - NGINX Instance Manager 2.16.0 ~ 2.21.1 - F5 WAF for NGINX 5.9.0 ~ 5.12.1 - NGINX App Protect WAF 4.9.0 ~ 4.16.0 和 5.1.0 ~ 5.8.0 - NGINX Gateway Fabric 1.3.0 ~ 1.6.2 和 2.0.0 ~ 2.5.1 - NGINX Ingress Controller 3.5.0 ~ 3.7.2, 4.0.0 ~ 4.0.1, 5.0.0 ~ 5.4.1 ## 修复版本 - NGINX 1.31.0(2026年5月13日发布) ## 触发条件 漏洞需要以下 NGINX 配置模式才能触发: location ~ ^/api/(.*)$ { rewrite ^/api/(.*)$ /internal?migrated=true; set $original_endpoint $1; } 关键条件: 1. `rewrite` 指令的替换字符串中包含 `?`(问号) 2. 后续 `set` 指令引用了正则表达式捕获组(如 `$1`) 3. 请求 URI 中包含可转义字符(如 `+`, `&`, `%` 等) ## 根因分析 ### 脚本引擎的两阶段处理 NGINX 的脚本引擎使用**两阶段处理**来执行 rewrite/set 指令: 1. **第一阶段(长度计算)**:计算最终字符串所需的内存大小 2. **第二阶段(数据拷贝)**:将实际数据写入分配的缓冲区 ### 状态不一致导致溢出 漏洞的核心在于两个阶段之间的**引擎状态不一致**: #### 阶段 1:`rewrite` 设置 `is_args` 标志 当 `rewrite` 指令的替换字符串包含 `?` 时,`ngx_http_script_start_args_code` 函数会设置: void ngx_http_script_start_args_code(ngx_http_script_engine_t *e) { e->is_args = 1; // 永久设置,从不重置! e->args = e->pos; e->ip += sizeof(uintptr_t); } #### 阶段 2:`set` 指令的长度计算使用全新子引擎 当后续 `set` 指令引用捕获组时,`ngx_http_script_complex_value_code` 创建一个**全零的子引擎**: void ngx_http_script_complex_value_code(ngx_http_script_engine_t *e) { ngx_http_script_engine_t le; // ... ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); // le.is_args = 0 le.ip = code->lengths->elts; #### 阶段 3:长度计算 vs 实际拷贝的分歧 **长度计算**(使用子引擎 `le`,`is_args=0`): // ngx_http_script_copy_capture_len_code if ((e->is_args || e->quote) && (e->request->quoted_uri || e->request->plus_in_uri)) { // is_args=0,条件为 false,走 else 分支 return cap[n + 1] - cap[n]; // 返回原始长度(未转义) } **实际拷贝**(使用主引擎 `e`,`is_args=1`): // ngx_http_script_copy_capture_code if ((e->is_args || e->quote) && (e->request->quoted_uri || e->request->plus_in_uri)) { // is_args=1,条件为 true,走 if 分支 e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]], cap[n + 1] - cap[n], NGX_ESCAPE_ARGS); // 每个可转义字符从 1 字节扩展为 3 字节! } ### 溢出大小 - 分配的缓冲区大小:`raw_size`(原始捕获长度) - 实际写入大小:`raw_size + 2 * N`(N = 可转义字符数量) - **溢出量 = 2 * N 字节** 例如,如果 URI 中有 100 个 `+` 号,溢出量为 200 字节。 ## 利用方式 ### 1. DoS(拒绝服务) 最简单的利用方式 - 发送包含大量可转义字符的请求即可导致 worker 进程崩溃: GET /api/+++++++++++++++++++++++++++++++++++ HTTP/1.1 Host: target.com ### 2. RCE(远程代码执行) 完整的 RCE 利用链(需要 ASLR 关闭或已绕过): 1. **堆布局控制**:通过连接顺序控制 `ngx_pool_t` 的堆布局 2. **溢出覆盖 `cleanup` 指针**:溢出到相邻的内存池结构 3. **喷射伪造的 cleanup 结构**:通过 POST 请求体注入包含 `system()` 地址的伪造结构 4. **触发执行**:关闭受害连接,触发 `ngx_destroy_pool` 遍历 cleanup 链表 NGINX 的多进程架构使得利用更加可靠 - worker 崩溃后 master 会 fork 出内存布局完全相同的新 worker。 ## 文件说明 - `README.md` - 本文件,漏洞分析文档 - `Dockerfile` - 构建易受攻击的 NGINX 环境 - `nginx.conf` - 触发漏洞的 NGINX 配置 - `poc_crash.py` - DoS PoC(触发 worker 崩溃) - `docker-compose.yml` - 一键启动测试环境 ## 快速复现 # 1. 构建并启动易受攻击的 NGINX docker-compose up -d # 2. 运行 DoS PoC python3 poc_crash.py # 3. 查看 NGINX 错误日志确认崩溃 docker-compose logs nginx ## 参考资料 - [NGINX 官方 CHANGES](https://nginx.org/en/CHANGES) - 修复公告 - [depthfirst 研究报告](https://depthfirst.com/research/nginx-rift-achieving-nginx-rce-via-an-18-year-old-vulnerability) - 原始漏洞发现者的技术分析 - [F5 安全公告 K000160932](https://my.f5.com/manage/s/article/K000160932) - 官方安全公告 ## 免责声明 本材料仅用于安全研究和教育目的。请勿将此信息用于未经授权的攻击行为。
标签:0day漏洞, C/C++, CISA项目, CVE-2026-42945, F5 WAF, HTTP请求走私, NGINX, NGINX Rift, Web安全, Web报告查看器, 事务性I/O, 云资产清单, 内存安全, 堆缓冲区溢出, 安全更新, 数据展示, 漏洞分析, 漏洞复现, 红队, 网络安全, 蓝队分析, 请求拦截, 负责任AI, 路径探测, 软件漏洞, 逆向工具, 逆向工程, 隐私保护