Two bytes to RCE: chaining rift + PoolSlip into an ASLR-independent nginx 1.30.0 exploit

Author: y198 (published on the Verichains blog)
Published: June 6, 2026
Source: https://blog.verichains.io/p/two-bytes-to-rce-chaining-rift-poolslip

Summary

This Verichains writeup chains two separately disclosed nginx rewrite-engine memory-corruption bugs — CVE-2026-42945 (“rift”), a heap-overflow write primitive, and CVE-2026-9256 (“PoolSlip”), a heap over-read leak primitive — into a single remote code execution exploit against nginx 1.30.0 that works with ASLR enabled. The author reports achieving system() execution as the nginx worker user (uid=101) with roughly 90% reliability per fresh worker. Both underlying vulnerabilities have been fixed by upstream; this is a coordinated exploitation study of patched bugs, not a live 0-day drop, and the author states the results are verified against a real target rather than modeled. The write-up’s headline contribution is a technique — a two-byte partial-pointer overwrite — that sidesteps the usual ASLR obstacle even though the write primitive can only emit a restricted set of byte values.

Technical Details

Both bugs share a root cause in nginx’s rewrite module: the engine computes an is_args flag in one pass but consumes it in another, so length calculations and copy operations disagree about whether URL-escaping is included. That mismatch produces out-of-bounds conditions. In PoolSlip, the mismatch applied to the request args causes the args length to be taken from a post-overflow engine position, so the response reflects adjacent heap memory back to the attacker — yielding live libc and heap pointers without any hardcoded addresses. In rift, the mismatch in a rewrite set variable causes a forward heap overflow, but the overflow can only write URL-safe bytes (roughly 79 of 256 possible values), which makes writing a full 48-bit address under ASLR succeed only about 0.9% of the time.

The exploit’s key idea is to avoid writing a full address at all. Using the leaked heap base (whose high bytes are stable and need not be written), it performs a two-byte partial overwrite of the low bytes of an existing nginx pool-cleanup pointer, redirecting it within its own memory block using only the URL-safe bytes the write primitive can produce. At a high level, the chain then: leaks libc and heap bases via PoolSlip; sprays crafted pool-cleanup structures whose handler points at system; grooms connections so a victim request pool sits adjacent to the overflow buffer; triggers rift to rewrite the victim pool’s cleanup pointer; and on connection teardown nginx walks the corrupted cleanup list and invokes the attacker-chosen command. The article documents target-specific tuning (a stock nginx:1.30.0 Debian image, glibc 2.41, stripped release binary, verified under gdb), including that the vulnerable behavior requires a specific and relatively uncommon rewrite-plus-set configuration pattern. Consistent with defensive reporting, this summary omits the exploit’s concrete offsets, spray counts, and grooming recipe; the full PoC and configuration are in the author’s linked repository.

Impact

Where the vulnerable configuration is present, an unauthenticated remote attacker can achieve command execution as the nginx worker account with high reliability and no need to defeat ASLR separately. The author notes the exploit needs no allocator tuning and no nginx restart (the master respawns crashed workers), though a per-source-IP limit_conn ceiling throttles same-IP retries, so attackers would rotate source IPs. The practical exposure is bounded by the trigger condition: the specific rewrite-engine is_args code path is only reached under a particular rewrite/set pattern that the author describes as uncommon in production, so this is a serious but configuration-gated result rather than a blanket “any nginx 1.30.0 is RCE.” Affected versions, per the source: rift affects nginx 0.6.27–1.30.0; PoolSlip affects 0.1.17–1.30.1 (and 1.31.0).

Mitigation

Both vulnerabilities are patched upstream — update nginx to a fixed release. Per the article: rift is fixed in 1.30.1 / 1.31.0, and PoolSlip is fixed in 1.30.2 / 1.31.1. Because 1.30.1 closes rift but is still vulnerable to PoolSlip, the safe targets are nginx 1.30.2 (stable) or 1.31.1 (mainline) or later; do not stop at 1.30.1. As defense-in-depth until patching completes, review rewrite configurations for the rewrite-plus-set pattern that reaches the vulnerable path and constrain or remove it where feasible, keep ASLR enabled, run nginx workers as an unprivileged user (as the default packaging does), and apply rate/connection limiting and WAF rules against anomalous URI/args payloads. Treat the affected-version and fix details above as reported by the source and confirm against the official nginx/F5 advisories before acting.

References

Leave a Comment