RestingOwl owl logo RestingOwl
Linux Security / Vulnerability Research

From HTTP Request to Root: How NGINX Rift and Dirty Frag Chain Into a Complete Server Takeover

One unauthenticated HTTP request exploits an 18-year-old NGINX heap overflow and lands a shell. A second kernel-level flaw, present since 2017, escalates that shell straight to root. No credentials. No prior access. Public exploits for all three CVEs. If your servers run NGINX, they are in scope.

Individually, each of these vulnerabilities is serious enough to demand immediate attention. NGINX Rift is a critical remote code execution flaw that has existed in every version of NGINX for 18 years. Dirty Frag is a deterministic local privilege escalation in the Linux kernel that converts any user-level shell into root. Together, they form something more dangerous than the sum of their parts: a complete remote-to-root attack chain targeting the web server infrastructure running a third of the internet.

An attacker starts from the internet with no account and no credentials. A single crafted HTTP request exploits the NGINX flaw and lands code execution as the nginx worker process. From there, the Dirty Frag kernel vulnerability takes that low-privilege shell and escalates it to root in a single deterministic operation. The attacker now owns the server.

The Three CVEs at a Glance

CVECVSSNameTypeRole in the Chain
CVE-2026-429459.2 CriticalNGINX RiftHeap Buffer Overflow (Remote)Entry point: unauthenticated RCE as the nginx worker process via a crafted HTTP request.
CVE-2026-432848.8 HighDirty Frag (ESP)Kernel LPE: xfrm-ESP page-cache writeEscalation: writes 4 bytes into the page cache of a setuid binary, corrupting it in memory.
CVE-2026-435007.8 HighDirty Frag (RxRPC)Kernel LPE: RxRPC page-cache writeEscalation: provides the namespace creation primitive needed to complete the Dirty Frag chain.

Stage One: NGINX Rift (CVE-2026-42945)

NGINX Rift was disclosed on May 13, 2026 by DepthFirst Disclosures and assigned a CVSS score of 9.2. The vulnerability is a heap buffer overflow in NGINX's ngx_http_rewrite_module: the component responsible for processing rewrite, if, and set directives in NGINX configuration files. It has been present in every version of NGINX since 0.6.27, which was released in 2008.

The root cause is a state synchronization failure in NGINX's internal script engine. When a rewrite directive contains a question mark in the replacement string, it permanently sets an internal flag called is_args to 1 on the main engine. A subsequent set directive using a PCRE regex capture variable (such as $1 or $2) then runs a two-pass process: first it calculates how many bytes the output needs, then it copies the data. The length calculation runs on a freshly created sub-engine where is_args is zero, so it allocates a static-sized heap buffer. The actual copy runs on the main engine where the flag is still 1, causing URI-escaping to expand certain characters from one byte into three bytes: writing far more data than the buffer holds.

Because the overflow size is directly controlled by how many escapable characters the attacker provides in the URI, the attacker can precisely control how far beyond the buffer they write and what they overwrite. The heap buffer immediately precedes an ngx_pool_t structure containing a cleanup function pointer. Overwriting that pointer with a value of the attacker's choosing, then triggering pool destruction through normal request handling, calls the attacker's function. Working exploits use Heap Feng Shui: carefully sequencing HTTP connections to position the target pool adjacent to an attacker-controlled pool: and derive the necessary runtime addresses through same-host HTTP-accessible information disclosure primitives, bypassing ASLR without hardcoded addresses.

The outcome is remote code execution as the nginx worker process. On most Linux servers, this is the nginx or www-data user: low-privilege, but with network access and the ability to make system calls. That is enough to start Dirty Frag.

Stage Two: Dirty Frag (CVE-2026-43284 and CVE-2026-43500)

Dirty Frag was disclosed on May 7, 2026, six days before NGINX Rift. It is a local privilege escalation in the Linux kernel that requires no special privileges: only the ability to run code on the target system. The attacker arriving via NGINX Rift has exactly that.

The vulnerability lives in the in-place decryption path of the kernel's esp4, esp6, and rxrpc modules. When the receive path decrypts over paged buffers that are not privately owned by the kernel (such as pipe pages introduced via splice() or sendfile()), unprivileged processes can retain references to the resulting plaintext. This gives an attacker a write primitive into the kernel's page cache: specifically, a controlled 4-byte write into the in-memory representation of any readable file.

CVE-2026-43284 (the esp4/esp6 path) provides that 4-byte write primitive. CVE-2026-43500 (the rxrpc path) provides the ability to create a user namespace: which, when combined with the write primitive, completes the privilege escalation chain. The attacker targets a setuid binary such as /usr/bin/su, writes four bytes at a calculated offset to alter its behavior, and executes it. The modified binary runs as root. Like Copy Fail, the on-disk file is never touched: the write goes only into the page cache, and disk-based integrity monitoring sees nothing unusual.

Unlike Dirty Pipe (CVE-2022-0847), which required a race condition, Dirty Frag is a deterministic logic flaw. It succeeds every time with no retry loop and no timing sensitivity.

The Complete Chain

1
Initial Access via CVE-2026-42945

The attacker identifies an internet-exposed NGINX instance using a rewrite and set directive combination with PCRE captures and a query string in the replacement. They send a single crafted HTTP request with a URI containing a controlled number of + characters. The heap overflow overwrites the pool cleanup pointer. When NGINX processes the pool teardown, it calls the attacker's function: landing a shell as the nginx or www-data user.

2
Privilege Escalation via CVE-2026-43284 and CVE-2026-43500

From the nginx worker shell, the attacker loads the exploit for Dirty Frag. They use splice() to feed page cache pages of a setuid binary (/usr/bin/su) into an IPsec ESP socket. The in-place decryption path writes four controlled bytes into those pages in memory, corrupting the binary's in-memory representation. CVE-2026-43500 provides the required user namespace creation. The on-disk binary remains untouched.

3
Root Access

The attacker executes the now-corrupted in-memory /usr/bin/su. Because it is a setuid binary and its in-memory code now includes the attacker's payload, it runs with root privileges. The attacker has full root access on the server. No credentials were used at any point in the chain. The entire sequence begins and ends with a standard HTTP connection.

Kubernetes Clusters Are Directly Exposed

The NGINX Ingress Controller and NGINX Gateway Fabric, both widely deployed in Kubernetes environments, are confirmed as affected products. NGINX Ingress Controller runs an NGINX process inside a pod with a configuration that frequently includes rewrite and set directives: the exact trigger conditions for this vulnerability.

An attacker who reaches the ingress controller can use NGINX Rift to execute code inside the ingress pod. From there, Dirty Frag requires access to the host kernel: and because the Linux kernel is shared between the host and all containers on the same node, the LPE operates against the node's kernel regardless of pod isolation. A successful chain against an ingress controller pod results in root on the underlying Kubernetes node, with access to node credentials, mounted secrets, and potentially the ability to move laterally across the cluster.

What You Need to Do

Security Checklist: CVE-2026-42945, CVE-2026-43284, CVE-2026-43500
  1. 1Update NGINX immediately: NGINX Open Source 1.30.1 (stable) or 1.31.0 (mainline) fix CVE-2026-42945. Both were released May 13, 2026. Run nginx -v to check your current version.
  2. 2If you deploy NGINX Ingress Controller or NGINX Gateway Fabric: update to the latest patched release from F5/NGINX. Check your Kubernetes ingress pods specifically.
  3. 3Audit your NGINX configuration for the trigger pattern: any rewrite directive whose replacement contains a ?, combined with a subsequent set or if directive using a PCRE capture variable ($1, $2). If you have this pattern and cannot patch immediately, restructure the config to remove the combination.
  4. 4Apply distribution kernel patches for Dirty Frag (CVE-2026-43284 and CVE-2026-43500). These are separate from the NGINX patches and require a kernel update and reboot.
  5. 5If kernel patching is temporarily blocked: disable the vulnerable kernel modules as a stop-gap: printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf && rmmod esp4 esp6 rxrpc 2>/dev/null; true
  6. 6Review NGINX access logs for requests with URIs containing unusually large numbers of + characters targeting paths covered by rewrite rules: this is the behavioral signature of NGINX Rift exploitation attempts.
  7. 7After patching the kernel: drop the page cache to clear any in-memory corruption: echo 3 > /proc/sys/vm/drop_caches.
🛡️
Action Required: Update NGINX and Patch Your Kernel
Two separate actions are required. First, update NGINX to 1.30.1 or 1.31.0 to close the remote entry point. Second, apply your distribution's kernel patches for Dirty Frag to close the privilege escalation path. Neither action alone is sufficient to break the chain: an attacker who reaches a low-privilege shell through another vector can still use Dirty Frag to reach root on an unpatched kernel. Do both.

References

  1. 1NGINX Rift: Achieving NGINX RCE via an 18-Year-Old Vulnerability (DepthFirst)
  2. 2Dirty Frag (CVE-2026-43284, CVE-2026-43500): FAQ (Tenable)
  3. 3NGINX Rift (CVE-2026-42945): Critical Heap Buffer Overflow Explained (Picus Security)
  4. 4Dirty Frag Linux kernel local privilege escalation vulnerability mitigations (Ubuntu)
Copied!