Am I vulnerable?
Affected versions
| Product |
Vulnerable range |
| NGINX Open Source |
0.6.27 through 1.30.0 |
| NGINX Plus |
R32 through R36 (without P-level hotfix) |
| NGINX Ingress Controller |
3.5.0 through 5.4.1 |
| NGINX Gateway Fabric / App Protect WAF / DoS / Instance Manager |
All current builds linking the vulnerable ngx_http_script.c |
| Kubernetes Ingress NGINX (community, retired March 2026) |
Up to and including v1.15.1 — no upstream patch will ship |
Run any of the following to check a host:
- Identify version:
nginx -v 2>&1. Vulnerable if the OSS version is between 0.6.27 and 1.30.0 inclusive, or Plus is R32 / R33 / R34 / R35 / R36 without the P-level hotfix (R32 P6, R35 P2, R36 P4 are the fixed builds).
- Audit the running configuration for the vulnerable directive pattern (an unnamed PCRE capture in a
rewrite whose replacement contains ?, followed by rewrite/if/set in the same scope referencing that capture): nginx -T 2>/dev/null | grep -nE 'rewrite|^\s*(if|set)\s'. nginx -t does NOT flag the vulnerable pattern — syntactic validation is insufficient.
- Package check (Debian/Ubuntu):
dpkg -l 'nginx*' 2>/dev/null | awk '/^ii/ {print $2, $3}'. Vulnerable if any installed nginx* is below 1.30.1 / 1.31.0.
- Package check (RHEL family):
rpm -qa | grep -i nginx. Same threshold.
- Crash-artefact scan (signs of active exploitation already):
grep -E 'worker process .* exited on signal (11|6)|glibc detected|heap corruption' /var/log/nginx/error.log /var/log/syslog 2>/dev/null; dmesg -T | grep -i 'segfault.*nginx'. Rapid PID cycling and SIGSEGV/SIGABRT terminations match the public PoC's observed behavior.
Functional definition: any system running an affected NGINX build AND serving a config that contains the rewrite-with-unnamed-capture-and-? pattern reachable from the internet. The version match alone is not enough — the bug needs the specific directive combination — but HeroDevs notes that this pattern is common enough in production that "you probably have it" is the right starting assumption.
Vulnerability
CVE-2026-42945, named NGINX Rift by Picus Security, is a heap-based buffer overflow (CWE-122) in the ngx_http_rewrite_module. It is reached when a rewrite directive uses an unnamed PCRE capture ($1, $2, ...) whose replacement contains a ?, and a subsequent rewrite, if, or set directive in the same scope references that capture. The bug is a two-pass length/copy contract violation in the script engine: the engine computes the length of one input, then copies a different (longer) input into the allocated buffer.
NVD assigns CVSS v3.1 8.1 along AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H — network-reachable, no privileges, no user interaction, high impact on all three CIA axes. The CVSS v4 score reported by community sources is 9.2.
Successful exploitation typically yields a worker-process crash (denial of service), but the public PoC at github.com/DepthFirstDisclosures/Nginx-Rift (not linked here) is reproducible with a single crafted HTTP request — Orca Security reports three exploit requests kill multiple workers and fail four of five subsequent health checks. Achieving remote code execution from the corruption primitive generally requires ASLR to be disabled or bypassed on the target. VulnCheck telemetry confirms in-the-wild exploitation attempts starting May 16, three days after the patch and PoC dropped; observed activity to date is opportunistic crash attempts consistent with the DoS-first character of the bug.
Threat model
Who would exploit this. Expect three concurrent waves. Opportunistic ransomware affiliates and access brokers will mass-scan the internet for vulnerable NGINX fingerprints within days of a public PoC landing — NGINX's roughly 30-40% market share makes this the highest-EV target on the web right now. State-aligned actors will keep this in their back pocket as one link in a longer chain against specific targets. Insider threat is effectively zero because the bug is reached over the network, not from a local foothold.
Operational goals.
- Initial foothold for ransomware deployment and double-extortion data theft
- Web-shell or reverse-shell drop on the NGINX host for persistent access
- Lateral movement into backend services that sit behind NGINX and trust the reverse proxy implicitly
- Theft of TLS private keys, upstream credentials, and secrets from NGINX config and environment
- Harvesting of session cookies, auth headers, and API tokens transiting the proxy
Attack chain. An attacker fingerprints exposed NGINX instances at internet scale, then sends a crafted HTTP request that triggers the rewrite/if/set evaluation path containing the heap overflow. Successful exploitation yields code execution inside an NGINX worker process, from which the attacker stages a payload, establishes persistence, and pivots — either toward backend applications reachable through the proxy or toward the host itself by abusing residual privileges and on-disk secrets.
Blast radius. A compromised NGINX box is rarely just a web server — it is typically the trust boundary for everything behind it, so attackers immediately gain reach into internal APIs and admin panels that assume the proxy has already authenticated callers, plus any TLS private keys NGINX terminates and any upstream credentials embedded in config. Cookies, bearer tokens, and auth headers transiting the proxy can be silently captured in flight, turning one box into a credential harvester for the entire application estate.
The poolslip follow-on. Patching to 1.31.0 / 1.30.1 closes Rift but lands defenders directly on the version targeted by nginx-poolslip, a 0-day disclosed by NebSec/Vega on May 21, 2026 with an ASLR-bypass primitive that re-enables reliable RCE against the otherwise-hardened code path. No CVE has been assigned, no patch is available, and NebSec is withholding the full technical writeup for 30 days. The usual "just patch" answer is wrong this week. The realistic move is compensating controls in front of NGINX: WAF rules that block the known Rift request shapes, rate-limit and geo-fence the edge, audit nginx.conf for the vulnerable rewrite/if/set patterns and refactor them out, and rotate TLS keys or upstream credentials that would be exposed if a worker is compromised. Hold on the version bump until F5 ships a build that closes both Rift and poolslip; patching twice through an active 0-day window costs more than it buys.
Mitigation
Patch
| Product |
Fixed version |
| NGINX Open Source (stable) |
1.30.1 (F5 K000161019) |
| NGINX Open Source (mainline) |
1.31.0 |
| NGINX Plus R36 |
R36 P4 |
| NGINX Plus R35 |
R35 P2 |
| NGINX Plus R32 |
R32 P6 |
After upgrading, restart NGINX (systemctl restart nginx) so workers actually reload the patched binary. SOC Prime explicitly calls this out: simply reloading the config (nginx -s reload) is not enough. See the poolslip framing in Threat model before committing to the patch timing.
Configuration mitigation
When an immediate upgrade isn't possible, F5's interim workaround is to replace unnamed PCRE captures with named captures in every affected rewrite block. The vulnerable pattern requires all three elements together (unnamed capture, ? in replacement, downstream rewrite/if/set referencing the capture); breaking any one removes the trigger.
Vulnerable pattern — any block matching this shape needs attention:
location ~ ^/api/(.*?)$ {
rewrite ^/api/(.*?)$ /internal?migrated=true last;
set $original_endpoint $1;
}
Workaround — same block rewritten with named captures:
location ~ ^/api/(?<endpoint>.*?)$ {
rewrite ^/api/(?<path>.*?)$ /internal?migrated=true&path=$path last;
set $original_endpoint $endpoint;
}
Validate and reload after applying:
nginx -t && nginx -s reload
Code mitigation
When patches do reach your environment (consider the poolslip framing before pulling the trigger), apply through your package manager rather than ad-hoc binary swaps:
Debian / Ubuntu:
sudo apt update
sudo apt install --only-upgrade nginx
nginx -v # expect 1.30.1 or 1.31.0 (or later)
sudo systemctl restart nginx
RHEL / Rocky / AlmaLinux:
sudo dnf update nginx
nginx -v
sudo systemctl restart nginx
Docker — pin and redeploy:
docker pull nginx:1.30.1
# or
docker pull nginx:1.31.0
docker compose up -d --force-recreate nginx
Kubernetes Ingress NGINX (community project retired March 2026 — no upstream patch coming). Switch to a maintained image or vendor-supported drop-in:
helm repo update
helm upgrade ingress-nginx ingress-nginx/ingress-nginx \
--set controller.image.tag=<patched-tag>
Compensating controls
- WAF signatures: enable FortiGate IPS sig 33817 ("Malicious.HTTP.URI.Requests") and Imperva SecureSphere's "Buffer Overflow Attack Attempt" / "Buffer Overflow Attack Attempt 1" rule pair. Picus tracks the vulnerability as Threat ID 63690.
- Edge controls: rate-limit and geo-fence the NGINX edge; the bug currently presents primarily as DoS via worker kills, so rate-limiting buys real time.
- Key rotation: rotate any TLS private keys and upstream credentials reachable from a worker process — these are the assets most likely to be exfiltrated if a worker is compromised.
- Asset inventory: runZero publishes a copy-pasteable query —
((vendor:="F5" OR vendor:="NGINX") AND (product:="nginx plus" OR product:="nginx" OR product:="nginx ingress controller")) — for finding every affected asset in your environment.
Detection (starter rules — validate before deploying)
These rules are AI-generated starter content. Test against your own telemetry and tune falsepositives before deploying to production. The rules catch the symptoms (worker SIGSEGV crashes, post-exploit webshells / reverse-shells, anomalous NGINX child processes) rather than the exploit payload, which can't be safely encoded without weaponization.
Network and log signals
- Abnormally long request URIs, query strings, or HTTP header values (>4KB) in NGINX access logs — flag any single header or URI exceeding 8192 bytes.
- Repeated requests to the same path from a single source IP within seconds, where each request varies only the length of a header/URI field — classic fuzzing pattern.
error.log entries matching worker process <pid> exited on signal 11 or (core dumped) — especially clusters of 3+ within a 5-minute window.
- Sudden, repeated NGINX worker process restarts visible via
systemd journal or PID churn, without a corresponding config reload event.
- Outbound network connections initiated by the NGINX user (
www-data, nginx, nobody) to non-vendor / non-upstream destinations.
- File writes by the NGINX UID into document root,
/tmp, /var/tmp, /dev/shm, or any path outside the configured cache directory — especially .php, .jsp, .aspx, .sh, .py, or short random names like a.php, cmd.jsp.
- Child processes spawned by an NGINX worker (
sh, bash, python, perl, nc, curl, wget, whoami, id, uname) — NGINX workers should never fork these.
- Core dump files in NGINX's
working_directory (often /var/lib/nginx or /var/crash) named core.nginx.* — correlate timestamps with access log entries from the same second to identify the triggering request.
- Sudden spike in 5xx responses (502/504) without a corresponding upstream backend outage.
YARA
rule CVE_2026_42945_nginx_rift_starter
{
meta:
author = "CVE Brief"
description = "Starter rule — behavioral patterns suggesting post-exploit nginx compromise (webshells in nginx-served paths, suspicious strings in core dumps / dropped files)"
reference = "CVE-2026-42945 NGINX Rift heap buffer overflow in ngx_http_rewrite_module"
date = "2026-05-22"
warning = "AI-generated starter rule - validate in your environment before deploying"
severity = "medium"
strings:
// Common PHP webshell idioms (language-level, not exploit-specific)
$php_shell_1 = "<?php" ascii nocase
$php_eval = /eval\s*\(\s*(\$_(GET|POST|REQUEST|COOKIE|SERVER)|base64_decode|gzinflate|str_rot13)/ ascii nocase
$php_sys_1 = "system($_" ascii nocase
$php_sys_2 = "shell_exec($_" ascii nocase
$php_sys_3 = "passthru($_" ascii nocase
$php_sys_4 = "proc_open($_" ascii nocase
$php_sys_5 = "assert($_" ascii nocase
// Common JSP / generic webshell markers
$jsp_shell_1 = "Runtime.getRuntime().exec" ascii
$jsp_shell_2 = "<%@ page import=\"java.io" ascii
// Generic reverse-shell strings frequently dropped after RCE
$rs_bash = "bash -i >& /dev/tcp/" ascii
$rs_pyt = "socket.socket(socket.AF_INET,socket.SOCK_STREAM)" ascii
$rs_perl = "use Socket;$i=\"" ascii
// nginx-process command-line / environment artifacts that should NOT appear
// in a healthy nginx worker memory image or dropped file
$cli_nginx = "nginx: worker process" ascii
$cli_susp_1 = "/bin/sh -c" ascii
$cli_susp_2 = "/dev/shm/" ascii
$cli_susp_3 = "chmod +x" ascii
condition:
( $php_shell_1 and ( $php_eval or 2 of ($php_sys_*) ) )
or
( all of ($jsp_shell_*) )
or
( any of ($rs_*) )
or
( $cli_nginx and 2 of ($cli_susp_*) )
}
Sigma
title: NGINX Worker Process Segfault — Possible CVE-2026-42945 Exploitation
id: 8a3f2c1e-4d6b-4f2a-9b71-2c4d6a8e1f02
status: experimental
description: |
Detects NGINX worker processes exiting on SIGSEGV (signal 11), which may indicate
exploitation attempts against CVE-2026-42945 ("NGINX Rift") — a heap buffer overflow
in ngx_http_rewrite_module. Clusters of segfaults, especially correlated with
abnormally long request URIs or headers in the access log, warrant immediate triage.
AI-generated starter rule — validate in your environment before deploying.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-42945
author: CVE Brief
date: 2026/05/22
tags:
- attack.initial-access
- attack.t1190
- cve.2026.42945
logsource:
product: nginx
category: errorlog
detection:
selection_segv:
Message|contains:
- 'worker process'
- 'exited on signal 11'
selection_core:
Message|contains:
- 'worker process'
- '(core dumped)'
selection_sigsegv_text:
Message|contains: 'SIGSEGV'
condition: selection_segv or selection_core or selection_sigsegv_text
fields:
- Message
- SourceIp
- RequestUri
falsepositives:
- Genuine application bugs in third-party nginx modules (lua-nginx-module, OpenResty, nginx-module-vts) producing segfaults unrelated to exploitation
- OOM-killer terminating nginx workers under memory pressure (check dmesg / journalctl for oom_reaper)
- Kernel bugs (older 6.x kernels have documented nginx SIGSEGV interactions with HTTPS)
- Hardware faults (bad RAM, failing CPU) causing process crashes across multiple services
- Stale shared-memory zones after an in-place binary upgrade (`nginx -s reload` with ABI changes)
level: medium
Rule notes
The YARA rule targets webshells and reverse-shell idioms commonly dropped after a successful NGINX compromise — it will not detect in-memory-only payloads or attackers who pivot through legitimate upstream backends. The Sigma rule fires on worker SIGSEGV terminations and is best treated as a triage trigger rather than a high-fidelity alert; pair it with the long-URI fuzzing patterns above for higher signal.
References