Contents

NGINX Has Had This Bug Since 2008 and One Request Is Enough to Trigger It

 

Want to learn ethical hacking? I built a complete course. Have a look!
Learn penetration testing, web exploitation, network security, and the hacker mindset:
→ Master ethical hacking hands-on
Hacking is not a hobby but a way of life!

 
Contents

NGINX Rift: An 18-year-old memory corruption bug in NGINX, the web server running on roughly one-third of all websites globally, lets an unauthenticated attacker crash a server with a single crafted HTTP request. On systems where ASLR is disabled, that same request achieves remote code execution. The bug has been in every standard build since 2008. It was publicly disclosed yesterday, after being found by an AI system in six hours.

The vulnerability is tracked as CVE-2026-42945 and goes by the name NGINX Rift.

NGINX acts as the gateway between the internet and the website, app, or API sitting behind it, taking every incoming request, processing it, and deciding where it goes. One of the most common things it does is rewrite URLs on the fly, routing traffic from one address to another.

The module that handles this is called ngx_http_rewrite_module, and it is built into every standard NGINX installation. F5 has owned NGINX since 2019 and put out the official warning alongside the public disclosure. Cloudflare’s entire edge infrastructure was originally built on top of NGINX.

When a bug affects this module, it does not just affect one product. It reaches a significant portion of everything on the internet.

That module processes rewrite instructions in two steps. First, it calculates how much memory it needs to store the result. Then it writes the actual data into that allocated space. Those two steps have to agree on the size. If they do not, the write runs past the end of the allocation and overwrites whatever is sitting next to it in memory. That kind of bug is called a heap buffer overflow, which means memory that belongs to one part of the program is being written over by data that has no business being there.

The mismatch comes down to one flag that never gets reset. When a rewrite directive contains a question mark in its replacement string, a function inside NGINX sets an internal flag called e->is_args to 1, signaling that URL arguments follow. That flag is never cleared. When a following set directive runs, the length calculation step uses a fresh internal copy where the flag is zero, so it measures the data as raw bytes and reserves a small block of memory. The actual write step runs on the main engine where the flag is still 1, and expands every +, %, and & character in the attacker’s URL from one byte into three. The write is bigger than the space reserved for it. The overflow happens.

That is the whole bug. One flag, never reset, two steps that stop agreeing on the size.

The trigger is a configuration pattern that thousands of servers use every day:

1
2
3
4
location ~ ^/api/(.*)$ {
    rewrite ^/api/(.*)$ /internal?migrated=true;
    set $original_endpoint $1;
}

The combination that triggers the bug is unnamed capture groups (variables like $1 or $2) together with a question mark in the replacement string, followed by another rewrite, if, or set directive. Named captures written as (?<name>...) take a different path inside NGINX and do not trigger the bug. If a configuration uses $1 or $2 in this pattern, it needs to be fixed now.

Zhenpeng (Leo) Lin, a security researcher at depthfirst, a platform that automatically scans code for security issues, set the depthfirst system loose on the NGINX source code in mid-April. Loading the repository took a single click. According to depthfirst, six hours later the system returned five memory corruption issues. Four were confirmed by NGINX. The most severe is CVE-2026-42945 with a CVSS v4.0 score of 9.2 (Critical) and a CVSS v3.1 score of 8.1 (High). The other three came out of the same scan:

  • CVE-2026-42946 (CVSS 8.3): a state mismatch in the SCGI and uWSGI modules that causes the worker to crash by computing a key length of roughly one terabyte
  • CVE-2026-40701 (CVSS 6.3): a use-after-free in the SSL module, which means memory gets freed before all references to it are gone; when a TLS connection closes before an asynchronous DNS lookup finishes, the context is destroyed while a timer still holds a pointer to it, and that pointer gets used later against freed memory
  • CVE-2026-42934 (CVSS 6.3): an off-by-one read error in the charset module when handling incomplete UTF-8 sequences near the edge of a memory block, causing the code to read two bytes before the start of the allocated buffer

None of these were caught in eighteen years of open source development and review by thousands of engineers and security researchers.

There is a working proof of concept that shows unauthenticated remote code execution on servers where ASLR is turned off. ASLR, which stands for Address Space Layout Randomization, is a protection that shuffles where programs and data sit in memory so an attacker cannot just aim at a fixed spot and fire. With it on, exploitation is a lot harder. With it off, the researchers’ proof of concept runs commands on the server. The researchers also describe a method that could work even with ASLR on, by overwriting one byte of a memory address at a time across multiple requests instead of all at once.

NGINX’s own architecture makes it easier for an attacker to keep trying. NGINX does not run as one big process. It has a main process that manages a set of smaller worker processes, and those workers are what actually handle the incoming traffic. When a worker crashes, the main process immediately starts a new one with a highly similar and predictable memory layout, by design, to keep the server stable under heavy load. On systems without ASLR, that layout is effectively identical each time. When someone is actively trying to exploit this, a failed attempt crashes the worker, and the main process produces an exact replacement. Same memory structure, same positions, same layout. The attacker tries again with the same target. Unlimited retries, no change in attack surface, no cost.

The attack works by carefully controlling which connections open first to arrange memory in a predictable way. To understand how this works, it helps to know that NGINX uses something called a memory pool for each connection. Instead of asking the operating system for tiny pieces of memory one at a time, it grabs a larger block upfront and carves slices off it as the connection needs them. When the connection closes, the entire block gets destroyed in one go. As part of that cleanup, NGINX walks through a list of tasks it needs to run before closing out. That cleanup list is what the attacker targets.

By opening two connections in a specific order, the attacker arranges their memory block to land directly next to the victim’s block. They then fill their space with a fake entry for that cleanup list, using POST request bodies to get it there, because unlike URIs and headers, POST bodies can carry arbitrary binary data including null bytes. When the overflow changes the address NGINX uses to find that cleanup list and NGINX destroys that connection, it runs whatever is sitting at that new address. This method of deliberately arranging memory layout through connection timing is called heap feng shui.

The attacker does not need a zero-day. They need patience, the right config on the target, and ASLR turned off.

These are the affected versions:

  • → NGINX Open Source 0.6.27 through 1.30.0
  • → NGINX Plus R32 through R36
  • → NGINX Instance Manager 2.16.0 through 2.21.1
  • → NGINX App Protect WAF 4.9.0 through 4.16.0 and 5.1.0 through 5.8.0
  • → NGINX Gateway Fabric 1.3.0 through 1.6.2 and 2.0.0 through 2.5.1
  • → NGINX Ingress Controller 3.5.0 through 3.7.2, 4.0.0 through 4.0.1, and 5.0.0 through 5.4.1

The first thing to check is whether the specific configuration is actually vulnerable. Not every NGINX setup triggers this bug. Three conditions have to be true at the same time: a rewrite directive that uses an unnamed capture group like $1 or $2, a replacement string in that rewrite that contains a question mark, and a second directive directly after it, either another rewrite, a set, or an if. All three together. If any one of those is missing, this specific bug cannot be triggered.

The fastest way to check is to scan the NGINX configuration for rewrite directives that contain a question mark:

1
grep -rn 'rewrite.*[?]' /etc/nginx/

If that returns nothing, the bug cannot be triggered by the current setup. If it does return results, check each match for $1 or $2 in the replacement and a set, if, or rewrite directive directly following it. A configuration that uses named captures like (?<name>...) instead of $1 is not affected.

One important nuance: the other three CVEs from the same research don’t care about rewrite configs at all. CVE-2026-42946 affects the SCGI and uWSGI modules regardless of rewrite configuration. CVE-2026-40701 affects SSL handling. CVE-2026-42934 affects charset processing. Checking the rewrite configuration only tells you about CVE-2026-42945. Upgrading to 1.31.0 or 1.30.1 fixes all six CVEs in this release, including two that are not part of the depthfirst research: CVE-2026-42926 (HTTP/2 request injection in the proxy module) and CVE-2026-40460 (address spoofing in HTTP/3).

The fix is nginx 1.31.0 (mainline) or nginx 1.30.1 (stable). Worth knowing: for the oldest affected branch, versions 0.6.27 through 0.9.7, no patch is being released. Those installations need to upgrade to a newer supported version entirely. Check the version running on the system, then restart NGINX after upgrading so all workers come back up on the new version:

1
nginx -v

If upgrading immediately is not an option, converting unnamed capture groups in rewrite directives to named ones removes the attack surface without changing the binary:

1
2
3
4
5
6
7
# Vulnerable: uses unnamed capture $1
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1;

# Not vulnerable: uses named capture (?<endpoint>...)
rewrite ^/api/(?<endpoint>.*)$ /internal?migrated=true;
set $original_endpoint $endpoint;

That is a workaround, not a permanent solution. Upgrade as soon as possible.

Eighteen years of code review, and an AI system found four memory corruption issues in one afternoon. depthfirst was founded in 2024 and raised $40 million in Series A funding in January 2026, backed by Accel. In the months since launching their product, their platform has already flagged issues in the Linux kernel, Chrome, and Apache HTTP Server. Some are still not public yet. The gap between what an automated system finds in hours and what thousands of human eyes missed for years is not narrowing. It is widening, in the wrong direction.

Learning how these attacks work at a technical level, how an attacker gets initial access, escalates privileges, establishes persistence, and moves through a network without being noticed, is exactly what my ethical hacking course covers from start to finish:

Join my complete ethical hacking course

Hacking is not a hobby but a way of life. 🎯

Sources: depthfirst | F5 Advisory | NGINX Security Advisories

 

→ Stay updated!

Get the latest posts in your inbox every week. Ethical hacking, security news, tutorials, and everything that catches my attention. If that sounds useful, drop your email below.

By Bulls Eye

Jolanda de koff • emaildonate

My name is Jolanda de Koff and on the internet, I'm also known as Bulls Eye. Ethical Hacker, Penetration tester, Researcher, Programmer, Self Learner, and forever n00b. Not necessarily in that order. Like to make my own hacking tools and I sometimes share them with you. "You can create art & beauty with a computer and Hacking is not a hobby but a way of life ...

I ♥ open-source and Linux