F2u0a0d3/CVE-2026-42945-nginx-rift-poc
GitHub: F2u0a0d3/CVE-2026-42945-nginx-rift-poc
Stars: 0 | Forks: 0
# NGINX Rift — CVE-2026-42945
RCE proof-of-concept for **CVE-2026-42945**, a critical heap buffer overflow in NGINX's `ngx_http_rewrite_module` introduced in 2008. Enables unauthenticated remote code execution against servers using `rewrite ... ?...` + `set` capture combinations.
Original vulnerability disclosure: [depthfirst](https://depthfirst.com/research/nginx-rift-achieving-nginx-rce-via-an-18-year-old-vulnerability) — found alongside CVE-2026-42946, CVE-2026-40701, CVE-2026-42934 via their autonomous source-audit system.
## Layout
poc-CVE-2026-42945/
├── exploit.py — improved PoC (3 modes: --check / --probe / --exploit)
├── poc.py.orig — original depthfirst PoC (reference)
├── env/ — dual-fixture Docker lab
│ ├── Dockerfile (vuln: nginx commit 98fc3bb78)
│ ├── Dockerfile.patched (patched: release-1.31.0)
│ ├── docker-compose.yml (both services)
│ ├── nginx.conf (vulnerable rewrite + set config)
│ ├── entrypoint.sh (runs under setarch -R — ASLR off)
│ └── server.py (backend stub)
├── discover-addresses.sh — extract HEAP_BASE / LIBC_BASE / system() offset from running container
├── verify.sh — dual-fixture reproducer (exploit vuln, prove patched blocks)
├── setup.sh — build helper (legacy single-image)
├── references.md — full bug mechanics, exploitation strategy, mitigations
└── README.md — this file
## The Bug (TL;DR)
Two-pass script engine, `is_args` flag desync:
- **Length pass** sees `is_args = 0` → allocates raw capture length
- **Copy pass** sees `is_args = 1` → `ngx_escape_uri(NGX_ESCAPE_ARGS)` 3x expansion → heap overflow
Exploitation: heap feng shui via POST `/spray` body (NUL bytes permitted in body, planted fake `ngx_pool_cleanup_s`) + URI overflow corrupting adjacent `ngx_pool_t.cleanup` head. Pool destruction → `system(cmd)`.
Full mechanics + exploitation strategy in [references.md](references.md).
## Affected & Fixed
| Product | Affected | Fixed |
|-------------------|------------------|--------------------------|
| NGINX Open Source | 0.6.27 – 1.30.0 | 1.30.1, 1.31.0 |
| NGINX Plus | R32 – R36 | R36 P4, R35 P2, R32 P6 |
Vendor advisory:
## Quick Start
# Build both fixtures
docker compose -f env/docker-compose.yml build
# Start lab (vuln=:19321, patched=:19421)
docker compose -f env/docker-compose.yml up -d
# Detect-only (no overflow trigger)
python3 exploit.py --check --host 127.0.0.1 --port 19321
# Full exploit
python3 exploit.py --exploit --host 127.0.0.1 --port 19321 \
--cmd 'echo pwned > /tmp/rift'
docker exec nginx-rift-vuln cat /tmp/rift
# Dual-fixture verify (exploit vuln + confirm patched blocks)
./verify.sh
# Teardown
docker compose -f env/docker-compose.yml down
## Modes
| Mode | Use case | Side effect |
|---|---|---|
| `--check` | Detect rewrite surface presence | None — sends small probe URIs only |
| `--probe` | Enumerate spray-landing offsets for THIS build | Crashes worker(s) during search; no exec |
| `--exploit` | Full RCE chain | Worker crash + `system()` call with `--cmd` |
Non-localhost targets require `--i-have-tested-this` flag (acknowledgment that hardcoded offsets match the deployed build).
## Address Discovery
Default `--heap-base` / `--libc-base` / `--system-offset` are the bundled lab's values (Ubuntu 22.04 / glibc 2.35 / nginx commit 98fc3bb78 / ASLR off). For a fresh build or different libc:
docker compose -f env/docker-compose.yml up -d nginx-vuln
./discover-addresses.sh
# Copy values into exploit.py invocation
## Caveats
- **Lab-only.** Hardcoded offsets are stable only inside the bundled fixture. Production exploitation requires per-target offset derivation (info leak + offset enumeration).
- **ASLR.** Lab disables ASLR via `setarch -R`. Real targets have ASLR enabled — additional info-leak primitive required.
- **Config dependency.** Vulnerable surface requires `rewrite ... ?` + `set $X $N` combination in the deployed nginx.conf. Many real configs lack this.