Private Nginx Rift ASLR lab, exploit chain, and demo recordings
RCE Proof of concept for CVE-2026-42945, a critical heap buffer overflow in NGINX's ngx_http_rewrite_module introduced in 2008. The bug enables unauthenticated remote code execution against servers using rewrite and set directives.
This fork extends the original PoC with an ASLR-bypass chain that combines the NGINX overflow with a common same-host LFI/arbitrary-file-read primitive. The file-read primitive is used to recover nginx worker maps, libc, and live /proc/<worker>/mem, then derive the system() address and usable heap targets remotely.
Earlier versions of this lab intentionally crashed an nginx worker to make the service write a core dump, then fetched and parsed that core dump through the file-read primitive to recover ASLR-sensitive process state, including heap targets. In this repo, coreless is only shorthand for "without a readable crash core dump": the current default path replaces that crash-core dependency with live procfs memory reads, while the preserved legacy core-guided path still uses the generated worker core dump.
This vulnerability — along with three other memory corruption issues (CVE-2026-42946, CVE-2026-40701, CVE-2026-42934) — was autonomously discovered by depthfirst's security analysis system after a single click of onboarding the NGINX source.
Want to find issues like this in your own code? Try the same system at https://depthfirst.com/open-defense.
NGINX's script engine uses a two-pass process: first compute the required buffer size, then copy data in. 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. So:
is_args = 0 → returns raw capture length.is_args = 1 → calls ngx_escape_uri with NGX_ESCAPE_ARGS, expanding each escapable byte to 3 bytes.The copy overflows the undersized heap buffer with attacker-controlled URI data. Exploitation uses cross-request heap feng shui to corrupt an adjacent ngx_pool_t's cleanup pointer (sprayed via POST bodies, since URI bytes can't contain null bytes), redirecting it to a fake ngx_pool_cleanup_s invoking system() on pool destruction.
Read more about this bug in our technical write-up.
| Product | Affected | Fixed in |
|---|---|---|
| NGINX Open Source | 0.6.27 – 1.30.0 | 1.31.0, 1.30.1 |
| NGINX Plus | R32 – R36 | R36 P4, R35 P2, R32 P6 |
Full vendor advisory: https://my.f5.com/manage/s/article/K000160932



This fork keeps the original disclosure PoC intact, but adds a second research track focused on a more realistic question:
Can the bug be exploited against a real x86_64 Linux VM with ASLR enabled, without relying on hardcoded Docker/lab offsets?
The answer in this research fork is yes, with important constraints. The working chains do not disable ASLR and do not use the original hardcoded heap/libc addresses. Instead, they derive runtime state through same-port HTTP-accessible primitives, then select the final heap target from remotely obtained disclosure data.
There are now two ASLR-enabled exploit tracks, with the coreless path treated as the current best PoC:
nginx_rifter.py: the clean, self-contained assessment and integrated exploit entry point. Its default exploit method is now the coreless /proc/<nginx-worker>/mem chain.nginx_rifter_core_v2_1.py: the preserved legacy core-guided version of nginx_rifter.py. It is useful for reproducing the older VM-tested crash-core research path, but it is no longer the preferred PoC.tools/proc_mem_coreless_exploit.py: the earlier standalone coreless research harness. Its logic has been merged into nginx_rifter.py; the tool remains for raw experiment replay.The target topology is intentionally same-port:
/api/.../lfi.php?file=.../phpinfo.phpThe current coreless proc-mem path performs the following high-level steps:
/proc/<pid>/maps, and the mapped libc file.system() address for that worker./proc/<worker>/mem through the file-read primitive.The legacy core-guided path performs a similar base-address derivation, then intentionally crashes a worker, reads the generated core file over LFI, and mines that core for sprayed fake-cleanup slots. That was a useful research bridge, but it depends on core-dump policy and filesystem permissions that are less common in default deployments.
This is not the same as the original deterministic Docker demo. The x86_64 VM path leaves normal Linux ASLR enabled and recomputes process-specific addresses on each run. The Docker coreless path also leaves ASLR enabled and removes the unusual readable-core requirement, but it depends on procfs permission behavior that must be verified for the target class.
This fork is a controlled research lab. The ASLR-enabled chains rely on strong conditions that are not universal production assumptions:
/proc/<pid>/maps, mapped libc, and /proc/<pid>/mem at large mapped offsets./proc/<pid>/maps, mapped libc, and the generated worker core.phpinfo() and /proc/<pid>/maps are enough to recover PIE/libc base addresses, but they are not enough by themselves to recover the exact heap object/window needed for this exploit. The old chain used a readable crash core for that final disclosure. The current default chain uses /proc/<worker>/mem instead, which is closer to a real arbitrary-file-read consequence in same-UID deployments because it exposes live worker memory without changing core-dump policy.
Important remaining limits: