InSEKurity of the Week (CW20/2026): NGINX Rift -- 18-Year-Old Rewrite Module Heap Overflow, Unauthenticated DoS & Potential RCE (CVE-2026-42945)
A size-mismatch bug in the NGINX rewrite module lets a remote, unauthenticated attacker overflow the heap with a single crafted HTTP request -- reliable worker crashes for everyone, potential RCE where ASLR is off. CVSS 4.0 9.2, public PoC, exploited in the wild since 2026-05-16, ~5.7M exposed servers
This week in our InSEKurity of the Week series: a bug that has been quietly riding along in the world’s most-deployed web server for eighteen years. CVE-2026-42945, nicknamed “NGINX Rift”, is a heap-based buffer overflow in ngx_http_rewrite_module. A remote, unauthenticated attacker can send a single crafted HTTP request that makes NGINX compute a destination buffer with one escaping rule and then write into it with a different, more expansive one — so characters like +, %, and & triple in size and the write runs off the end of the allocation. The corruption is attacker-shaped because the overflowing bytes come straight from the request URI. For the vast majority of vulnerable configurations the practical outcome is a reliable, repeatable worker-process crash (DoS); on hosts where ASLR is disabled, multiple analyses agree it crosses into remote code execution. CVSS 4.0 9.2 (Critical). The flaw was disclosed by depthfirst on 2026-05-13 with a working PoC published to GitHub the same day, and VulnCheck’s canary systems flagged in-the-wild exploitation by 2026-05-16 — three days later. With roughly 5.7 million internet-exposed NGINX servers running a potentially vulnerable build, this is the patch-now bug of the week for anyone who runs NGINX anywhere near a rewrite rule.
📋 Summary
- CVE ID: CVE-2026-42945 (“NGINX Rift”)
- CVSS 4.0 Score: 9.2 (Critical)
- CVSS 4.0 Vector:
CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - CVSS 3.1 Score: 8.1 (High) —
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - CWE: CWE-122 (Heap-based Buffer Overflow)
- Affected Software: NGINX Open Source 0.6.27 through 1.30.0; NGINX Plus R32 through R36; F5 products bundling the engine — NGINX Ingress Controller, F5 WAF for NGINX, NGINX Instance Manager, NGINX Gateway Fabric, NGINX App Protect DoS
- Configuration Prerequisite: a
rewritedirective whose replacement contains a?, uses an unnamed PCRE capture ($1,$2, …), and is followed by anotherrewrite,if, orsetdirective - Attack Vector: Network — a single crafted HTTP request to any vulnerable virtual host
- Authentication Required: No — fully pre-auth
- User Interaction: None
- Impact: Heap buffer overflow in the NGINX worker. Practically: reliable Denial of Service (worker crash/restart) for essentially all vulnerable configs; potential unauthenticated Remote Code Execution where ASLR is disabled
- Patch Status: Fixed in NGINX Open Source 1.30.1 and 1.31.0; NGINX Plus R32 P6, R36 P4, and 37.0.0. Distro packages from AlmaLinux, Debian, and Ubuntu.
- Published: NVD entry / public disclosure 2026-05-13; F5 advisory K000161019 (2026-05-14)
- Exploitation Status: Public PoC on GitHub since 2026-05-13; in-the-wild exploitation attempts flagged by VulnCheck canaries on 2026-05-16, publicly confirmed 2026-05-18
- CISA KEV: Not listed at time of writing
🧩 What is NGINX (and the rewrite module)?
NGINX is, by a wide margin, the most widely deployed web server and reverse proxy on the internet. It fronts roughly a third of all websites, terminates TLS for an enormous fraction of the world’s HTTPS traffic, and runs as the ingress data plane in a huge slice of Kubernetes clusters (NGINX Ingress Controller). NGINX comes in two editions that share the same core: NGINX Open Source (the free, ubiquitous build that ships in essentially every Linux distribution) and NGINX Plus (F5’s commercial edition with extra load-balancing, observability, and API-management features). Either way, the request-handling core — including the module at the center of this bug — is the same code.
The ngx_http_rewrite_module is one of the most-used modules in real-world NGINX configurations. It implements the rewrite, if, set, return, and break directives that administrators reach for constantly: rewriting legacy URLs to new ones, normalising paths, stripping or rebuilding query strings, doing conditional routing, and preserving the original request path for an upstream. If you have ever written rewrite ^/old/(.*)$ /new/$1 ...;, you have used the exact code path that “NGINX Rift” lives in.
Typical Use Cases (i.e. who is exposed)
- Reverse proxies / API gateways that rewrite inbound paths before forwarding to upstreams.
- Legacy URL migration — permanent/temporary redirects and internal rewrites that preserve captured path segments.
- Query-string manipulation — rules that append, strip, or rebuild
?key=valuearguments (this is where the?-triggered code path lives). - Multi-tenant hosting — per-vhost rewrite rules generated from templates, where one risky pattern propagates across thousands of sites.
- Kubernetes ingress — NGINX Ingress Controller renders
rewrite-targetannotations into the very directives in scope here. - CDN / WAF edge tiers — NGINX-based edge nodes that normalise requests before origin.
The exposed population is genuinely internet-scale. Public scan data puts roughly 5.7 million internet-facing NGINX servers on a potentially vulnerable version. The truly exploitable subset is smaller — it requires the specific rewrite pattern below — but that pattern is common enough, and templated config is widespread enough, that nobody should assume they are out of scope without checking.
🔬 Technical Analysis
Vulnerability Description
CVE-2026-42945 is a heap-based buffer overflow (CWE-122) in the NGINX rewrite module’s handling of the replacement string in a rewrite directive. NGINX builds the rewritten URI in two distinct passes: a length pass that computes how big the destination buffer needs to be, and a copy pass that actually writes the bytes. The bug is a state mismatch between those two passes: under a specific (and common) directive arrangement, the length pass under-counts the size, the allocation is therefore too small, and the copy pass writes past the end of it. Because the overflowing bytes are derived directly from the attacker’s request URI, the heap corruption is shaped by the attacker, not random — which is what separates “guaranteed crash” from “potential code execution”.
Root Cause Analysis
- A
?in the rewrite replacement flips an internalis_argsflag. When arewritedirective’s replacement string contains a question mark, NGINX records that everything after it is a query string and sets the internalis_argsstate to1. Crucially, that state is sticky for the rest of the rewrite phase when the directive is followed by anotherrewrite,if, orsetdirective. - The length pass uses a fresh sub-engine where
is_args == 0. It returns the raw, unescaped length of each unnamed PCRE capture ($1,$2, …). No escaping is accounted for, so the computed size is the “small” number. - The copy pass uses the main engine where
is_args == 1. This causes it to callngx_escape_uri()with theNGX_ESCAPE_ARGStable while emitting the captured group. Under that table, characters that are legal in a path but must be percent-encoded in a query string — notably+,%, and&— each expand from 1 byte to 3 bytes (%2B,%25,%26). - Small allocation, large write. The destination buffer was sized for the unescaped capture (step 2) but the copy pass writes the escaped, expanded capture (step 3). Every
+,%, or&the attacker stuffs into the capture group adds two extra bytes to the write but zero extra bytes to the allocation. The write runs off the end of the heap chunk. - Unnamed captures only. The mismatch hinges on the unnamed-capture code path (
$1,$2, …). Named captures ((?<name>...)) take a different, correctly-sized path — which is the basis for the official workaround. - Eighteen years of dormancy. The defective length/copy split has been in
ngx_http_rewrite_modulesince roughly 2008 (NGINX 0.6.27), making every release up to and including 1.30.0 vulnerable. It survived this long because the trigger requires a precise combination (unnamed capture +?in replacement + a followingrewrite/if/set) that is common in production but rarely hit by fuzzers pointed at default configs.
Vulnerable Configuration Pattern
The bug only manifests when the configuration matches the trigger shape. A minimal vulnerable block:
# VULNERABLE: unnamed capture ($1) + '?' in the replacement +
# a following 'set' directive that references the rewrite phase.
location ~ ^/api/(.*)$ {
rewrite ^/api/(.*)$ /internal?migrated=true; # '?' sets is_args
set $original_endpoint $1; # following directive
proxy_pass http://backend;
}
# SAFE: named capture takes a different, correctly-sized code path.
location ~ ^/api/(?<rest>.*)$ {
rewrite ^/api/(?<rest>.*)$ /internal?migrated=true;
set $original_endpoint $rest;
proxy_pass http://backend;
}
Attack Vector
The end-to-end path is trivial: find a vulnerable virtual host, send one request whose path lands in the captured group and is padded with characters that expand under query-string escaping. The snippet below is illustrative only and intentionally non-weaponised — it shows the shape defenders should recognise, not a working exploit.
# Step 1: Fingerprint NGINX and a version that is potentially in range.
# (Server header is often present; absence does not mean "safe".)
curl -sI https://target.example.com/ | grep -i '^server:'
# Server: nginx/1.28.0 <-- in the 0.6.27 - 1.30.0 vulnerable range
# Step 2: Identify a route that hits a 'rewrite' with an unnamed
# capture. Path-segment rewrites that preserve the tail are the
# typical candidates (legacy migration, API path stripping, etc.).
# Step 3: Send ONE crafted request. The captured group is padded
# with characters (+ % &) that expand 1 -> 3 bytes during the
# query-string re-escape, so the write overruns the buffer that
# was sized for the *unescaped* length.
#
# *** ILLUSTRATIVE ONLY - NOT A WORKING EXPLOIT ***
PAD=$(python3 -c 'print("%2B" "+++%%%&&&" * 512)')
curl -sk "https://target.example.com/api/${PAD}"
# Practical result for almost every vulnerable config:
# -> NGINX worker process heap overflow -> crash -> restart (DoS)
# Where ASLR is disabled on the host:
# -> attacker-shaped heap corruption -> potential RCE
A simplified view of the size mismatch:
ngx_http_rewrite_module
------------------------
LENGTH PASS (fresh sub-engine, is_args = 0)
capture "$1" measured RAW/unescaped -> len = N
malloc(N) ............................ buffer too small
|
v
COPY PASS (main engine, is_args = 1)
'?' in replacement made is_args sticky
ngx_escape_uri(..., NGX_ESCAPE_ARGS)
'+' -> "%2B" (1 byte -> 3 bytes)
'%' -> "%25" (1 byte -> 3 bytes)
'&' -> "%26" (1 byte -> 3 bytes)
writes M bytes, where M >> N
|
v
+------------------ heap chunk (N) ------------+##########
| written URI ................................| OVERFLOW
+----------------------------------------------+##########
^
attacker-controlled bytes from URI
Exploitation in the Wild
- 2026-05-13 — depthfirst publicly discloses the bug and publishes a working PoC to GitHub. NVD entry goes live; AlmaLinux/Debian/Ubuntu begin shipping patched packages.
- 2026-05-14 — F5 publishes advisory K000161019 and patched NGINX Open Source / Plus builds.
- 2026-05-16 — VulnCheck’s canary/honeypot systems flag exploitation attempts — only three days after the PoC dropped.
- 2026-05-18 — VulnCheck’s Patrick Garrity publicly confirms active exploitation; reporting estimates ~5.7 million internet-exposed NGINX servers on potentially vulnerable versions.
The realistic threat today is mass, opportunistic DoS: the crash primitive is reliable and the PoC is public, so spraying crafted requests at NGINX fleets to knock workers over is cheap and repeatable. The RCE path is real but conditional — the public PoC achieved code execution against a deliberately vulnerable, ASLR-disabled target and does not demonstrate reliable execution against hardened, ASLR-enabled production hosts. Treat “DoS now, RCE where you were sloppy about hardening” as the working model.
Post-Exploitation Impact
- Service outage at the edge. NGINX usually is the front door — crashing workers means dropped TLS, dropped APIs, and dropped ingress for everything behind it.
- Repeatable, low-cost denial of service. One request per crash, no auth, no session — trivially scriptable against many vhosts at once.
- Ingress-wide blast radius in Kubernetes. Taking down NGINX Ingress Controller pods can sever access to every service routed through them.
- Code execution where ASLR is off. Embedded appliances, minimal containers, and misconfigured hosts with ASLR disabled are the realistic RCE population — and on those, the worker often runs with enough privilege to pivot.
- Heap-grooming research will improve. An 18-year-old, attacker-shaped overflow with a public PoC tends to attract follow-on exploitation engineering; the RCE reliability bar may drop over time.
💥 Impact Assessment
Immediate Impact
- Internet-scale exposure: ~5.7M internet-facing NGINX servers on a potentially vulnerable build define the upper-bound population.
- Pre-auth, single request, no user interaction: the cheapest possible trigger conditions.
- Public PoC + confirmed in-the-wild activity within 3 days: the window for “patch before it’s exploited” has already closed — assume it is being sprayed.
- Reliable DoS for nearly all vulnerable configs: this is not a theoretical edge case; the crash is the common case.
- Conditional RCE: ASLR-disabled hosts (appliances, stripped containers) are the meaningful code-execution risk.
Affected Versions
| Component | Vulnerable Range | Fixed In |
|---|---|---|
| NGINX Open Source | 0.6.27 through 1.30.0 | 1.30.1, 1.31.0 |
| NGINX Plus | R32 through R36 | R32 P6, R36 P4, 37.0.0 |
| NGINX Open Source 0.6.27–0.9.7 | Vulnerable | No fix planned (EOL) |
| NGINX Ingress Controller / F5 WAF for NGINX / Instance Manager / Gateway Fabric / App Protect DoS | Builds bundling a vulnerable engine | Vendor-updated builds — see K000161019 |
Check the actual running build, not the package name. Many distros backport;
nginx -vplus your distro’s changelog is the source of truth. A “1.28.0” that has the distro patch applied is fine; an unpatched 1.30.0 is not.
Affected Environments
- Internet-facing reverse proxies and API gateways with path-rewriting rules.
- Kubernetes clusters running NGINX Ingress Controller with
rewrite-targetannotations. - Multi-tenant / templated hosting where one risky rewrite snippet is rendered across many vhosts.
- CDN / WAF edge tiers built on NGINX.
- Appliances and embedded devices that bundle NGINX — disproportionately likely to ship with ASLR disabled, i.e. the RCE-relevant population.
Attacker Profiles
- Opportunistic disruptors / botnets: a reliable, scriptable, unauthenticated crash against the most common web server is ideal mass-DoS material.
- Hacktivists: high-visibility outages against recognisable targets with a one-line trigger.
- Initial-access actors (selective): focused RCE attempts against ASLR-disabled appliance fleets.
- Extortion / “booter” services: monetising a no-auth crash primitive at scale.
- Red teams / authorized testers: a clean availability-impact test case for any NGINX-fronted scope this month.
🛡️ Mitigation Strategies
Immediate Actions (Priority 1)
- Inventory and version-check every NGINX instance, including the ones bundled inside appliances, containers, and ingress controllers.
# Direct hosts nginx -v 2>&1 # e.g. nginx version: nginx/1.30.0 # Containers / Kubernetes ingress kubectl get pods -A -o jsonpath='{range .items[*]}{.spec.containers[*].image}{"\n"}{end}' \ | grep -i nginx | sort -u # Fleet sweep over the Server header (indicative, not authoritative) for h in $(cat hosts.txt); do printf '%s ' "$h"; curl -sI "https://$h/" | awk -F': ' 'tolower($1)=="server"{print $2}' done - Patch to a fixed build. NGINX Open Source 1.30.1 / 1.31.0; NGINX Plus R32 P6 / R36 P4 / 37.0.0; or your distro’s patched package (AlmaLinux/Debian/Ubuntu have shipped them).
# Debian/Ubuntu sudo apt update && sudo apt install --only-upgrade nginx # RHEL/AlmaLinux sudo dnf upgrade nginx # Reload after upgrade (graceful, keeps connections) sudo nginx -t && sudo systemctl reload nginx - Apply the official workaround until you can patch: convert unnamed captures to named captures in any
rewritedirective whose replacement contains?and is followed byrewrite/if/set.# Before (vulnerable) rewrite ^/api/(.*)$ /internal?migrated=true; set $original_endpoint $1; # After (safe) -- named capture avoids the mismatched code path rewrite ^/api/(?<rest>.*)$ /internal?migrated=true; set $original_endpoint $rest; - Audit configs for the trigger pattern so you know your real exposure rather than guessing.
# Flag rewrite directives that use an unnamed capture AND a '?' grep -RInE 'rewrite\s+\S+\s+\S*\?\S*' /etc/nginx/ | grep -E '\$[0-9]' # Then manually confirm a following rewrite/if/set in the same block. - Confirm ASLR is enabled everywhere NGINX runs — this is the single control that keeps the bug at “DoS” instead of “RCE”.
cat /proc/sys/kernel/randomize_va_space # must be 2 (full ASLR) # If 0/1: set kernel.randomize_va_space=2 in /etc/sysctl.d and apply.
Detection Measures
# (a) Worker crash/restart signal -- the reliable DoS fingerprint.
journalctl -u nginx --since "2026-05-13" | \
grep -Ei 'worker process .* exited on signal|SIGSEGV|signal 11|.*core dumped'
grep -Ei 'worker process [0-9]+ exited on signal (6|11)' /var/log/nginx/error.log
# (b) Inbound trigger shape -- heavily query-escapable padding in the
# captured path segment (lots of +, %, & or %2B/%25/%26 runs).
grep -E '"[A-Z]+ /[^ ]*(%2[B5]|%26|[+%&]){20,}' /var/log/nginx/access.log
# (c) Crash storms -- many worker restarts in a short window from the
# same source are an exploitation/DoS indicator, not noise.
grep -c 'exited on signal' /var/log/nginx/error.log
title: NGINX Rift (CVE-2026-42945) Trigger Pattern / Worker Crash
status: experimental
logsource:
product: nginx
detection:
uri_pattern:
cs-uri-stem|re: '(%2[Bb5]|%26|[+%&]){20,}'
worker_crash|re: 'worker process [0-9]+ exited on signal (6|11)'
condition: uri_pattern or worker_crash
level: high
tags:
- cve.2026.42945
- attack.impact
- attack.t1499 # Endpoint Denial of Service
- attack.t1190 # Exploit Public-Facing Application
Long-term Security Improvements
- Treat the reverse proxy as Tier-0. The thing that terminates all your TLS and fronts all your apps deserves the same patch SLA and monitoring discipline as a domain controller.
- Pin and track the running NGINX build, not just the package name — backports make
Server:headers and version strings lie. Maintain an SBOM that includes bundled engines inside appliances and ingress controllers. - Prefer named captures by policy. Lint your NGINX configs in CI: ban unnamed-capture rewrites that also contain
?. This bug is fixed, but the readability/safety argument for named captures is permanent. - Keep ASLR mandatory. A surprising number of appliances and minimal containers ship with it weakened. ASLR is the difference between this CVE being an availability nuisance and a remote shell.
- Rate-limit and bound request size at the edge.
limit_req,large_client_header_buffers, and upstream WAF rules raise the cost of crash-spraying even before a patch lands. - Aggressive advisory SLAs for edge software. Public PoC plus confirmed in-the-wild within 72 hours (as happened here) means a 7-day patch window is too slow for internet-facing NGINX — target 24-72h.
⚠️ Why is this Critical?
- The most-deployed web server on earth — a third of the web sits behind NGINX, and the bug is in one of its most-used modules.
- Pre-auth, single crafted request, no user interaction — minimal attacker prerequisites.
- Public PoC the day of disclosure, in-the-wild activity within three days — the patch-before-exploited window is already gone.
- Reliable DoS is the common case, not the edge case — nearly every vulnerable config can be crashed on demand.
- Conditional RCE on ASLR-disabled hosts — appliances and stripped containers are exactly where ASLR is most often off.
- 18 years dormant — enormous installed base of long-lived, rarely-touched NGINX instances that nobody is watching.
- Templated config amplifies blast radius — one risky rewrite snippet rendered across thousands of vhosts is one mistake, thousands of targets.
🗓️ Timeline and Disclosure
- ~2008 — The length/copy escaping mismatch is introduced in
ngx_http_rewrite_module(NGINX 0.6.27). - 2026-04-21 — depthfirst reports the vulnerability to F5 under coordinated disclosure.
- 2026-05-13 — Public disclosure; depthfirst publishes a working PoC to GitHub; NVD entry live; AlmaLinux/Debian/Ubuntu ship patched packages.
- 2026-05-14 — F5 publishes advisory K000161019 and patched NGINX Open Source / Plus builds.
- 2026-05-16 — VulnCheck canary systems flag the first in-the-wild exploitation attempts.
- 2026-05-18 — VulnCheck publicly confirms active exploitation; ~5.7M exposed servers reported.
🔗 Resources and References
- CVE: CVE-2026-42945 — MITRE
- NVD: CVE-2026-42945 — NVD Detail
- Vendor Advisory: K000161019 — NGINX ngx_http_rewrite_module vulnerability (F5)
- CWE: CWE-122: Heap-based Buffer Overflow — MITRE
- CISA KEV: Known Exploited Vulnerabilities Catalog (not listed at time of writing)
🤝 SEKurity Supports You
A buffer overflow that hid in the world’s most popular web server for eighteen years — and went from “PoC published” to “exploited in the wild” in three days — is a clean illustration of why edge software is Tier-0 and why “we run a well-known, mature project” is not a security control. We help organizations measure their real exposure to this class of bug: enumerating every NGINX build that is actually running (including the ones quietly bundled inside appliances and ingress controllers), auditing rewrite configurations for the dangerous pattern, confirming ASLR is genuinely enabled on the hosts that matter, and stress-testing whether your detection content would actually catch a crash-spray or a targeted RCE attempt before your customers notice the outage.
Our Services
- Penetration Testing: Web applications, mobile apps (Android & iOS), SAP systems, Active Directory
- Large-Scale Attacks: Perimeter testing, IT infrastructure testing, Red Team engagements
- Security Awareness: Phishing campaigns, hacking demonstrations
Act now — before attackers do.
Contact:
Website: www.sekurity.de
Inquiries: www.sekurity.de/kontakt
LinkedIn: SEKurity GmbH
Your SEKurity Team — Your Trusted Adversaries
The security of your web edge is our drive.
Sources
- CVE-2026-42945 — NVD Detail
- K000161019: NGINX ngx_http_rewrite_module vulnerability — F5
- 18-Year-Old NGINX Rewrite Module Flaw Enables Unauthenticated RCE — The Hacker News
- NGINX CVE-2026-42945 Exploited in the Wild, Causing Worker Crashes and Possible RCE — The Hacker News
- 18-year-old NGINX vulnerability allows DoS, potential RCE — BleepingComputer
- Attackers are exploiting critical NGINX vulnerability (CVE-2026-42945) — Help Net Security
- NGINX Rift: CVE-2026-42945 Critical Heap Buffer Overflow Vulnerability Explained — Picus Security
- CVE-2026-42945: NGINX Rewrite Heap Overflow Enables Remote DoS & Potential RCE — SOCRadar
- NGINX Rift (CVE-2026-42945) Patches Released — AlmaLinux
- F5 Nginx Remote Code Execution Vulnerability (CVE-2026-42945) — Qualys ThreatPROTECT
- NGINX Rift: an 18-year-old flaw in the world’s most deployed web server — Security Affairs
- Nginx-Rift PoC (CVE-2026-42945) — DepthFirstDisclosures, GitHub
- CWE-122: Heap-based Buffer Overflow — MITRE
About the Author
SEKurity Team
Offensive Security Experts
The SEKurity GmbH team consists of experienced penetration testers, security researchers, and cybersecurity consultants. Under the motto 'Your Trusted Adversaries', we support organizations in evaluating their IT security from an attacker's perspective and improving it.
Related Articles
InSEKurity of the Week (CW04/2026): Cisco Unified Communications Manager Zero-Day (CVE-2026-20045)
Critical zero-day vulnerability in Cisco Unified Communications Manager and Webex actively exploited - Root access via code injection possible
InSEKurity of the Week (CW06/2026): OpenClaw AI Agent 1-Click RCE (CVE-2026-25253)
Critical vulnerability in OpenClaw AI Agent enables Remote Code Execution with just one click - Authentication token exfiltration through manipulated URLs
InSEKurity of the Week (CW16/2026): Windows IKE Extensions RCE (CVE-2026-33824)
Critical pre-auth double free in the Windows IKE Service Extensions (IKEEXT.dll) lets remote attackers reach SYSTEM over UDP/500 and UDP/4500 -- wormable, public PoC already online