NGINX Rift — Heap Buffer Overflow RCE (CVE-2026-42945)
by depthfirst · 2026-05-14
- Severity
- Critical
- CVE
- CVE-2026-42945
- Category
- web
- Affected product
- NGINX Open Source / NGINX Plus
- Affected versions
- NGINX 0.6.27 – 1.30.0; NGINX Plus R32 – R36
- Disclosed
- 2026-05-14
- Patch status
- unpatched
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-05-14 |
| Author / Researcher | depthfirst |
| CVE / Advisory | CVE-2026-42945 |
| Category | web |
| Severity | Critical |
| CVSS Score | 9.8 (CVSSv3) |
| Status | Weaponized |
| Tags | RCE, unauthenticated, nginx, heap-overflow, buffer-overflow, rewrite |
Affected Target
| Field | Value |
|---|---|
| Software / System | NGINX Open Source / NGINX Plus |
| Versions Affected | NGINX 0.6.27 – 1.30.0; NGINX Plus R32 – R36 |
| Language / Platform | C / Linux x86-64 |
| Authentication Required | No |
| Network Access Required | Yes |
Summary
CVE-2026-42945 is a critical heap buffer overflow in NGINX’s ngx_http_rewrite_module that has existed since 2008. When a server configuration combines a rewrite rule containing ? with a set directive, NGINX’s two-pass script engine allocates an undersized buffer (based on the raw capture length) but then copies data with URI escape expansion — overflowing the heap with attacker-controlled URI bytes. An unauthenticated remote attacker can exploit this via heap feng shui to achieve arbitrary Remote Code Execution as the NGINX worker process user.
Vulnerability Details
Root Cause
NGINX’s script engine uses a two-pass process: first compute the required buffer size, then copy data. The is_args flag is set on the main engine when a rewrite replacement contains ?, but the length-calculation pass runs on a freshly zeroed sub-engine. As a result:
- Length pass sees
is_args = 0→ returns the raw URI capture length. - Copy pass sees
is_args = 1→ callsngx_escape_uriwithNGX_ESCAPE_ARGS, expanding each escapable byte to 3 bytes (%XX).
The copy therefore overflows the undersized heap buffer by up to 3× the number of escapable bytes in the attacker-supplied URI segment.
Attack Vector
An unauthenticated attacker sends a crafted HTTP GET request to the vulnerable /api/<payload> location. The payload contains URI bytes (+ chars) that are safe to transmit but are expanded during the copy pass. Concurrent POST requests to a /spray location are used to perform heap feng shui — spraying fake ngx_pool_cleanup_s structs into adjacent heap memory containing a pointer to system() and a pointer to an attacker-controlled command string. When the overflowed ngx_pool_t’s cleanup pointer is redirected to this fake struct and the pool is destroyed, system() is called with the attacker’s command.
Impact
Remote Code Execution as the NGINX worker process user (typically www-data or nginx). The exploit as implemented achieves a reverse shell. Requires ASLR to be disabled (or bypassed separately); the provided PoC targets a deterministic lab environment.
Environment / Lab Setup
OS: Ubuntu 22.04 LTS (24.04.3 LTS also tested)
Target: NGINX built from source at commit 98fc3bb78 (covers 0.6.27 – 1.30.0)
Docker container with ASLR disabled via setarch -R
Attacker: Same host / LAN
Tools: Python 3, Docker, Docker Compose, netcat
Setup Steps
| |
Proof of Concept
Step-by-Step Reproduction
Build the container — compile NGINX at the vulnerable commit with ASLR disabled.
1 2./setup.sh docker compose -f env/docker-compose.yml up -dSpray heap — the exploit sends N_SPRAY=20 concurrent POST requests to
/spraywith 4 KB bodies containing a fakengx_pool_cleanup_sstruct ({system_addr, data_addr, 0}) followed by the shell command string. These POST bodies are stored in worker pool memory adjacent to future allocations.Trigger overflow — a GET request to
/api/<349×'A'><969×'+'><6-byte addr>is sent. The 969+chars each expand to%2B(3 bytes) during the copy pass, overflowing the 969-byte allocation by ~1938 bytes and corrupting an adjacentngx_pool_t’scleanuppointer with the pre-sprayed fake cleanup struct address.Execute command — a second connection causes the corrupted worker’s pool to be destroyed, invoking
system(cmd).1python3 poc.py --cmd 'id > /tmp/pwned'
Exploit Code
See
poc.pyin this folder.
| |
Expected Output
[*] Waiting for nginx on 127.0.0.1:19321...
[+] Connected.
[+] try 1/10 crashed — system("echo hello from depthfirst > /tmp/pwned") executed
[+] Done.
Screenshots / Evidence
screenshots/— add evidence of successful exploitation here
Detection & Indicators of Compromise
"GET /api/AAAA...++++...%XX HTTP/1.1" 499
"POST /spray HTTP/1.1" 200
SIEM / IDS Rule (example):
alert http any any -> $HTTP_SERVERS any (msg:"Possible nginx-rift exploit attempt"; \
content:"/api/"; http_uri; pcre:"/\/api\/[^?]{300,}/U"; sid:9000002; rev:1;)
Remediation
| Action | Detail |
|---|---|
| Patch | Upgrade NGINX Open Source to 1.31.0 or 1.30.1; NGINX Plus to R36 P4, R35 P2, or R32 P6 |
| Workaround | Remove or refactor rewrite … ? + set directive combinations from server config |
| Config Hardening | Restrict URI character sets with valid_referers / WAF rules; enable ASLR on production hosts |
References
- CVE-2026-42945
- F5 / NGINX Vendor Advisory K000160932
- Source Repository — DepthFirstDisclosures/Nginx-Rift
- Technical Write-up — depthfirst.com
Notes
Auto-ingested from https://github.com/DepthFirstDisclosures/Nginx-Rift on 2026-05-14.
Three related memory-corruption CVEs were reported alongside this issue: CVE-2026-42946, CVE-2026-40701, CVE-2026-42934. The exploit requires ASLR to be disabled; exploitation against ASLR-hardened targets would require an additional information leak primitive.
| |