F5 NGINX CVE-2026-42530 / CVE-2026-42055 — Critical Unauthenticated RCE
Executive Summary
On approximately 17–18 June 2026, F5 issued out-of-band patches for two critical (CVSS v4 9.2) NGINX vulnerabilities, both exploitable by a remote, unauthenticated attacker against the HTTP request path:
- CVE-2026-42530 — use-after-free in
ngx_http_v3_module. When NGINX is configured with the HTTP/3 / QUIC module, a specially crafted HTTP/3 session that reopens a QPACK encoder stream triggers a UAF in the NGINX worker. The reliable outcome is a repeated worker crash (DoS); arbitrary code execution is possible on systems where ASLR is disabled or can be bypassed. - CVE-2026-42055 — heap-based buffer overflow in
ngx_http_proxy_v2_moduleandngx_http_grpc_module. Triggered when NGINX proxies HTTP/2 upstream (proxy_http_version 2orgrpc_pass) withignore_invalid_headers offandlarge_client_header_bufferssized above 2 MB. Heap corruption again yields DoS and potential code execution under the same ASLR caveat.
Affected products span NGINX Open Source, NGINX Plus, NGINX Gateway Fabric, NGINX Ingress Controller, NGINX Instance Manager, and the NGINX App Protect / F5 WAF & DoS lines. Fixed builds: NGINX OSS 1.31.2 and 1.30.3, NGINX Gateway Fabric 2.6.4, NGINX Plus R36 P6 / 37.0.2.1. F5 advisories: K000161616 (CVE-2026-42530) and K000161584 (CVE-2026-42055).
As of publication, there is no public proof-of-concept and no confirmed in-the-wild exploitation. F5 / NGINX appliances have, however, a strong history of rapid weaponization, so the window is short. This pack hunts endpoints (Linux hosts and containers) that run Falcon. The memory corruption itself happens in-process inside the NGINX worker and is largely invisible to EDR, so the durable, high-fidelity signal is what the worker does next: an nginx worker spawning a shell / interpreter / download tool, a new ELF written under a web root, an unexpected listener post-exploit, or beaconing to new infrastructure. The pack pairs those behavioral hunts with a vulnerable-version inventory hunt — the patch is the fix.
quic from listen) and remove ignore_invalid_headers off / reduce large_client_header_buffers below 2 MB. (3) The highest-fidelity hunt is Q1 — an nginx worker spawning sh/bash/python/perl/curl/wget. There is almost no benign reason for an NGINX worker to parent a shell. Escalate any hit and pivot to Q3 (web-root ELF write), Q4 (new listener) and Q5 (rare egress) on the same host.Source Review & Web Hunter Notes
| Tier | Source | Key Finding | Carry |
|---|---|---|---|
| 1 · Vendor | F5 advisory K000161616 (CVE-2026-42530) & K000161584 (CVE-2026-42055) | Authoritative affected/fixed version matrix; trigger conditions; mitigations (disable HTTP/3; remove ignore_invalid_headers off / shrink buffers) | yes |
| 1 · News of record | The Hacker News — "F5 Patches Two Critical NGINX Open Source Flaws Enabling RCE" | Both CVSS v4 9.2; remote unauth; UAF in HTTP/3 QUIC (QPACK encoder reopen) and heap overflow in HTTP/2 proxy/gRPC; RCE only where ASLR disabled/bypassed; full affected-product list; fixed builds | yes |
| 2 · Vendor research | SecurityWeek — "F5 Patches Critical, High-Severity NGINX Vulnerabilities" | Two criticals plus high-sev NGF config-injection bugs (CVE-2026-11311 / -50107, authenticated); affected product families; mitigation framing | yes |
| 2 · News | BleepingComputer — "F5 issues out-of-band patches for critical NGINX vulnerabilities" | Out-of-band release dated 18 Jun 2026; no active exploitation reported; mitigations (remove quic from listen); notes F5's history of being targeted | yes |
| 2 · News | Security Affairs / Cyber Security News / GBHackers | DoS via repeated worker crash is the reliable outcome; RCE conditional on ASLR; impact = service restart loops or code execution; patch-now guidance; no IOCs | yes |
Decisions: No atomic IOCs (hashes / domains / IPs), no public PoC, and no confirmed in-the-wild exploitation were published, so the pack is behavior-keyed, not IOC-keyed — anchor on NGINX-worker-parented anomalous execution, ELF/webshell writes under web roots, unexpected post-exploit listeners, and rare egress, plus a worker-crash-loop proxy for exploitation attempts. Lead with the patch (the fix) and a version-inventory hunt. The QUIC/QPACK and HTTP/2 heap primitives are in-process inside the worker and invisible to EDR by design, so we hunt the consequences of a successful chain on the endpoint. Scope is Linux hosts and containers running NGINX (OSS/Plus/Gateway Fabric/Ingress/App Protect).
Hunt Brief & Attack Chain
Working hypothesis: An unauthenticated attacker reaches an internet- or internally-exposed NGINX listener and sends a crafted request. For CVE-2026-42530 that is an HTTP/3 (QUIC) session that reopens a QPACK encoder stream, corrupting freed memory in the worker; for CVE-2026-42055 it is oversized/invalid HTTP/2 headers proxied upstream that overflow a heap buffer. The reliable result is a worker crash → master respawn loop (DoS). Where ASLR is disabled or bypassed, the attacker pivots the corruption into code execution inside the NGINX worker and then lands post-exploitation tooling on the host. EDR telemetry begins where the worker interacts with the OS — child processes, file writes, new listeners, and network egress.
| Step | Behavior | Telemetry | Hunt Angle |
|---|---|---|---|
| 1 · Recon / delivery | Attacker reaches an exposed NGINX HTTP/3 or HTTP/2-proxy listener and sends a crafted request | NetworkConnectIP4, NetworkListenIP4, gateway/WAF logs | N4 (perimeter logs); Q5 (egress) for callbacks |
| 2 · Memory-corruption trigger | QPACK encoder-stream reopen (UAF) or oversized HTTP/2 headers (heap overflow) in the worker (in-process) | – (largely invisible to EDR) | GAP in-worker; watch for worker crash/respawn loops (Q6 / N2) |
| 3 · DoS (reliable) | Worker crashes; master respawns it repeatedly | ProcessRollup2 (nginx worker churn), syslog/journald | Q6 worker respawn storm; N2 crash logs |
| 4 · In-worker RCE (ASLR off/bypassed) | Arbitrary code in the worker context → shell / interpreter / LOLBin launch | ProcessRollup2 | Q1 nginx→shell; Q2 nginx→recon/download tool |
| 5 · Payload / webshell to disk | Worker writes an ELF or script under a web root / tmp path | ElfFileWritten, NewExecutableWritten, file-write events | Q3 |
| Post · C2 / listener / persist | Reverse shell or bind listener; beacon to attacker infra; cron / unit persistence | NetworkListenIP4, NetworkConnectIP4 | Q4 new listener; Q5 rare egress; Containment §14 |
Hunt hypotheses (fidelity-ordered)
- H1 (high): An
nginxworker directly spawns an interactive shell or interpreter → Q1. Near-zero benign baseline. - H2 (high): An
nginxworker spawns a download / recon tool (curl,wget,id,whoami,uname) → Q2. Workers serve content; they do not run recon. - H3 (high): An
nginxworker writes an ELF / script under a web root or tmp path then it executes → Q3 (webshell / dropped payload). - H4 (high): A new network listener appears on an NGINX host whose owning process is not
nginx→ Q4 (bind shell / tunnel). - H5 (medium): An
nginxworker makes an outbound connection to newly-seen / rare external infrastructure → Q5 (reverse shell / C2). - H6 (medium): Repeated short-lived
nginxworker respawns on a host in a tight window → Q6 (crash-loop = exploitation attempt, success or failure / DoS). - H7 (high): Hosts still running an NGINX build below the fixed version → Q7 (inventory hunt; patch is the fix).
Consolidated IOC Table
| Type | Value | Conf | Action | Context |
|---|---|---|---|---|
| Version | NGINX OSS < 1.31.2 (and 1.30.x < 1.30.3) | high | detect | Vulnerable build — patch closes both flaws |
| Version | NGF < 2.6.4 · NGINX Plus < R36 P6 / < 37.0.2.1 | high | detect | Same engine — inherits the flaws |
| Hunt artifact | nginx worker → sh / bash / dash / python / perl / php | high | hunt | Post-exploit shell/interpreter from a worker parent |
| Hunt artifact | nginx worker → curl / wget / nc / ncat / id / whoami / uname | high | hunt | Download / recon follow-on after worker RCE |
| Hunt artifact | nginx worker writing an ELF / script under web root or /tmp then exec | high | hunt | Dropped payload / webshell from the worker chain |
| Hunt artifact | New non-nginx network listener on an NGINX host | medium | hunt | Bind shell / tunnel post-exploit |
| Hunt artifact | nginx worker crash / respawn storm (short-lived workers) | medium | hunt | Exploitation attempt indicator (success or DoS) |
| CVE (companion) | CVE-2026-11311 / CVE-2026-50107 (NGF config injection, authenticated) | medium | enrich | High-sev NGF bugs patched in the same release; same patch hygiene |
Affected Surface & Telemetry Matrix
| Surface | Required Telemetry | Priority | Gap Risk |
|---|---|---|---|
| Hosts / containers running an NGINX build below the fixed version | Process/version inventory (ProcessRollup2 nginx CommandLine / package feed) | Critical | Low-Med — version often only in nginx -v banner / package metadata |
| NGINX worker process lineage (RCE follow-on) | Process tree + parent context (ProcessRollup2 / SyntheticProcessRollup2, ParentBaseFileName) | High | Low — standard Linux sensor |
| Worker-dropped ELF / webshell | File write w/ writing-process context (ElfFileWritten / NewExecutableWritten) | High | Med — interpreted webshells (.php/.py) may not be PE/ELF events |
| Post-exploit listener (bind shell / tunnel) | Listening sockets w/ process context (NetworkListenIP4) | High | Low-Med — needs listen telemetry enabled |
| Post-exploit egress / reverse shell / C2 | Outbound IP w/ process context (NetworkConnectIP4) | Medium | Med — needs newness/rarity scoping; workers rarely egress |
| QUIC/QPACK & HTTP/2 heap primitive (in-worker) | None — in-process worker memory corruption | N/A | GAP — invisible to EDR; rely on consequences + crash loop + patch |
ATT&CK Mapping
| Tactic | Technique | Observed Behavior | Query / Control |
|---|---|---|---|
| Initial Access | T1190 — Exploit Public-Facing Application | Crafted HTTP/3 or HTTP/2-proxy request triggers worker memory corruption | N4; patch (Q7/N1) |
| Execution | T1203 — Exploitation for Client Execution | UAF / heap overflow → code execution in the NGINX worker | Q6; patch (Q7/N1) |
| Execution | T1059.004 — Unix Shell | Worker parent spawns sh/bash/dash or an interpreter | Q1, Q2 |
| Impact | T1499.004 — Endpoint DoS: Application Exhaustion Flood | Repeated worker crash → master respawn loop (DoS) | Q6; N2 |
| Persistence | T1505.003 — Server Software Component: Web Shell | Worker writes a webshell / ELF under a web root | Q3; Containment §14 |
| Command & Control | T1071.001 — Application Layer Protocol: Web | Worker-parented beacon / reverse shell to attacker infra | Q5 |
| Command & Control | T1571 — Non-Standard Port (bind listener) | New non-nginx listener opened post-exploit | Q4 |
| Discovery | T1082 / T1033 — System / Owner Discovery | Worker spawns id / whoami / uname | Q2 |
Native Audit-Log Hunts
| Hunt | Source | Logic | Response |
|---|---|---|---|
| N1 · NGINX version inventory | Package manager (dpkg -l / rpm -q nginx), nginx -v, container image tags, Ansible facts | Enumerate NGINX OSS/Plus/NGF/Ingress builds; flag any below 1.31.2 (or 1.30.x below 1.30.3), NGF below 2.6.4, Plus below R36 P6 / 37.0.2.1 | Patch; the definitive fix (mirrors Q7) |
| N2 · Worker crash loop | journald / syslog (nginx "worker process exited on signal 11/6"), core dumps, systemd restart counters | Repeated worker SIGSEGV/SIGABRT and master respawns on a host within a short window | Possible exploit attempt / DoS; collect core, correlate Q6 |
| N3 · Persistence after compromise | cron (/etc/cron*, user crontabs), systemd units/timers, ~/.ssh/authorized_keys, web-root file diffs | New cron/unit/timer/authorized_keys or web-root file created shortly after a worker RCE indicator | Investigate; pairs with Q1–Q3 on same host |
| N4 · Exploit traffic at the edge | Reverse proxy / WAF / LB access logs, QUIC/UDP 443 flow records | Anomalous HTTP/3 sessions, malformed HTTP/2 header floods, or oversized header requests preceding worker instability | Block source; enrich Q5/Q6 hits |
| N5 · NGINX config exposure audit | nginx -T config dump | Confirm whether http3/quic listeners, proxy_http_version 2/grpc_pass, ignore_invalid_headers off, and large_client_header_buffers > 2 MB are present (the trigger conditions) | Apply mitigations (§12); prioritize patch on matching hosts |
CrowdStrike LogScale CQL Hunt Queries
SyntheticProcessRollup2. These are Linux hunts (NGINX runs on Linux hosts/containers). The QUIC/QPACK and HTTP/2 heap primitives are invisible to EDR — these hunt the post-exploitation consequences on the endpoint plus a vulnerable-version inventory. Once NGINX is confirmed ≥ the fixed builds fleet-wide (Q7/N1), keep Q1–Q4 as durable defense-in-depth for any web-server-exploit chain.Looks for: an nginx process as the direct parent of a shell or scripting interpreter. Accomplishes: catches the highest-fidelity post-exploit signal — NGINX workers serve content and have almost no benign reason to spawn an interactive shell.
// HUNT: NGINX worker spawning a shell / interpreter (CVE-2026-42530 / -42055 post-exploit) // MITRE: T1190, T1203, T1059.004 | CONF: high FP: low COST: low // REQUIRES: ProcessRollup2 (Linux) with ParentBaseFileName // FALSE POSITIVES: CGI / FastCGI setups, custom perl/lua handlers, ops scripts that legitimately run under nginx // TUNING: allow-list known FastCGI wrappers per host; pair any hit with Q3/Q4/Q5 on the same aid #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | event_platform=Lin | ParentBaseFileName=/^nginx$/i | FileName=/^(sh|bash|dash|zsh|ksh|python[0-9.]*|perl|ruby|php|php-cgi|lua)$/i | table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, SHA256HashData], limit=200) | sort(@timestamp, order=desc)
Looks for: an nginx parent spawning a download utility or host-discovery binary. Accomplishes: catches the recon / payload-pull stage that follows worker RCE. FP: some images use curl/wget in entrypoint health checks — scope to interactive/anomalous invocations.
// HUNT: NGINX worker spawning a download / recon tool (post-exploit discovery / payload pull) // MITRE: T1203, T1059.004, T1082, T1033, T1105 | CONF: high FP: low-med COST: low // REQUIRES: ProcessRollup2 (Linux) with ParentBaseFileName // FALSE POSITIVES: container entrypoint/health-check curl/wget; monitoring agents // TUNING: allow-list known health-check command lines; rank by rare command lines per image #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | event_platform=Lin | ParentBaseFileName=/^nginx$/i | FileName=/^(curl|wget|nc|ncat|netcat|socat|id|whoami|uname|hostname|ifconfig|ip|crontab|chmod|base64)$/i | table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, SHA256HashData], limit=200) | sort(@timestamp, order=desc)
Looks for: an nginx process writing an ELF or script to a web root, upload dir, or tmp path. Accomplishes: catches dropped payloads and webshells. FP: legitimate upload features write user content — scope to executable/script extensions and correlate with Q1/Q2 on the same host.
// HUNT: NGINX worker writing an ELF / webshell under a web root or tmp path (dropped payload) // MITRE: T1505.003, T1105, T1203 | CONF: high FP: medium COST: low // REQUIRES: ElfFileWritten / NewExecutableWritten with ContextBaseFileName + TargetFileName // FALSE POSITIVES: legitimate file-upload features writing user content into web roots // TUNING: scope to script/exec extensions; correlate to a Q1/Q2 hit on the same aid before alerting #event_simpleName=/ELFFileWritten|NewExecutableWritten/ | event_platform=Lin | ContextBaseFileName=/^nginx$/i | TargetFileName=/\/(www|html|public_html|webroot|sites|uploads|tmp|dev\/shm|var\/tmp)\/.+(\.(php|phtml|py|pl|sh|jsp|cgi|elf|so|bin)|[^.\/]+)$/i | table([@timestamp, ComputerName, UserName, ContextBaseFileName, TargetFileName, SHA256HashData], limit=200) | sort(@timestamp, order=desc)
Looks for: a host that runs nginx opening a new listening socket whose owning process is NOT nginx. Accomplishes: surfaces bind shells / tunnels stood up after worker RCE. FP: co-located services (sshd, monitoring agents) — allow-list known daemons per host role.
// HUNT: New non-nginx listener on a host that also runs nginx (bind shell / tunnel post-exploit) // MITRE: T1571, T1059.004 | CONF: high FP: medium COST: low // REQUIRES: NetworkListenIP4 with ContextBaseFileName; nginx present on the same aid // FALSE POSITIVES: co-located daemons (sshd, node_exporter, app servers) legitimately listening // TUNING: allow-list known service binaries per host role; focus on shells/interpreters as the listener #event_simpleName=NetworkListenIP4 | event_platform=Lin | nginxHosts := if(ContextBaseFileName=/^nginx$/i, then=aid, else="") | ContextBaseFileName=/^(sh|bash|dash|python[0-9.]*|perl|ruby|php|nc|ncat|netcat|socat)$/i | groupBy([aid, ComputerName, ContextBaseFileName, LocalPort], function=([count(as=listen_events), collect([CommandLine])])) | sort(listen_events, order=desc)
Looks for: outbound connections initiated by an nginx process to external IPs, surfaced by rarity (least-common destinations across the fleet). Accomplishes: NGINX workers terminate inbound traffic and rarely originate egress — outbound from a worker to rare infra is a strong reverse-shell / C2 pivot. FP: upstream proxying / auth subrequests — scope by rarity and exclude known upstreams.
// HUNT: Rare external egress from an nginx process (post-exploit reverse shell / C2) // MITRE: T1071.001 | CONF: medium FP: medium COST: medium // REQUIRES: NetworkConnectIP4 with ContextBaseFileName + RemoteAddressIP4 // FALSE POSITIVES: legitimate upstreams / auth subrequests; package mirrors // TUNING: exclude RFC1918 + known upstream IPs; rank by rarity (distinct hosts per RemoteAddressIP4) #event_simpleName=NetworkConnectIP4 | event_platform=Lin | ContextBaseFileName=/^nginx$/i | RemoteAddressIP4!=/^(10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[0-1])\.|127\.|169\.254\.)/ | groupBy([RemoteAddressIP4, RemotePort], function=([count(ComputerName, distinct=true, as=hosts), count(aid, as=conns), collect([ComputerName])])) | sort(hosts, order=asc, limit=200)
Looks for: a host with many short-lived nginx worker launches in a tight window — consistent with the master repeatedly respawning crashed workers (the reliable outcome of both CVEs). FP: reloads (nginx -s reload), config pushes, or autoscaling also churn workers — triage by burst tightness and pair with Q1–Q5.
// HUNT: NGINX worker respawn storm on a single host (UAF/heap crash loop = exploit attempt or DoS) // MITRE: T1203, T1499.004 | CONF: medium FP: medium COST: low // REQUIRES: ProcessRollup2 (Linux) nginx worker launches // FALSE POSITIVES: nginx -s reload, config deploys, container/pod autoscaling churn // TUNING: raise the per-host threshold; correlate the burst with Q1-Q5 and N2 crash logs on same aid #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | event_platform=Lin | FileName=/^nginx$/i | ParentBaseFileName=/^nginx$/i | timeChart(span=5m, function=count(), series=ComputerName) | sort(_count, order=desc)
Looks for: NGINX builds reporting a version below the fixed release. Accomplishes: the inventory hunt — patching is the definitive control. Note: NGINX rarely runs with -v on the serving command line, so this leans on version-banner launches (startup checks, nginx -v in entrypoints). Pair with N1 (package-manager inventory) for full coverage and validate the version-field source in your tenant.
// HUNT: Inventory NGINX builds below the fixed release (CVE-2026-42530 / -42055) // MITRE: T1190 / T1203 (mitigation/visibility) | CONF: high FP: low COST: low // REQUIRES: ProcessRollup2 (Linux) nginx launches whose CommandLine carries a version banner // VERIFY: nginx version rarely appears in the serving cmdline; pair with N1 package inventory // Fixed: OSS >= 1.31.2 (or 1.30.x >= 1.30.3); flag anything below #event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/ | event_platform=Lin | FileName=/^nginx$/i | CommandLine=/nginx\/(?<maj>\d+)\.(?<min>\d+)\.(?<patch>\d+)/i | maj:=parseInt(maj) | min:=parseInt(min) | patch:=parseInt(patch) | test(maj < 1 or (maj = 1 and min < 30) or (maj = 1 and min = 30 and patch < 3) or (maj = 1 and min = 31 and patch < 2)) | groupBy([ComputerName, maj, min, patch], function=count(as=hits)) | sort([maj, min, patch], order=asc)
CrowdStrike Custom IOA Recommendations
| IOA Name | Field Patterns | Benign Exclusions | Deployment Path |
|---|---|---|---|
| NGINX worker spawns shell/interpreter | Platform Linux; Parent Image */nginx; Child sh/bash/dash/python*/perl/ruby/php | Allow-list any sanctioned FastCGI/CGI wrapper images per host | Endpoint Security → Custom IOA → Process Creation (Detect+Block) |
| NGINX worker spawns recon/download tool | Platform Linux; Parent Image */nginx; Child curl/wget/nc/ncat/socat/id/whoami/uname | Exclude known entrypoint/health-check command lines | Custom IOA → Process Creation (Detect, then Block after baseline) |
| NGINX worker writes executable/webshell | Platform Linux; Writing Image */nginx; Target */www/* | */html/* | */uploads/* | */tmp/* with exec/script extension | Exclude sanctioned upload dirs; correlate with the two IOAs above | Custom IOA → File Write (Detect / hunt) |
Machine-Readable IOC Appendix
Grouped IOC Quick-Copy
No atomic IOCs were published — these are behavioral hunt artifacts, a version/patch audit (the fix), and the config-mitigation set, NOT threat-intel atomics. Use the CSV with REPLACE_WITH_ placeholders only if your IR turns up campaign atomics.
type,value,action,severity,expiration,description,tags sha256,REPLACE_WITH_PAYLOAD_SHA256,prevent,critical,2027-06-19,CVE-2026-42530/-42055 nginx-dropped payload,campaign:F5-NGINX-RCE domain,REPLACE_WITH_C2_DOMAIN,detect,high,2026-09-19,CVE-2026-42530/-42055 post-exploit C2,campaign:F5-NGINX-RCE ipv4,REPLACE_WITH_C2_IP,detect,high,2026-09-19,CVE-2026-42530/-42055 post-exploit C2,campaign:F5-NGINX-RCE
nginx worker spawns sh/bash/dash/zsh/python/perl/ruby/php/php-cgi/lua nginx worker spawns curl/wget/nc/ncat/socat/id/whoami/uname/hostname/crontab/chmod/base64 nginx worker writes an ELF/script under a web root, uploads dir, or /tmp /dev/shm /var/tmp then it executes New non-nginx listener (sh/bash/python/nc/socat) on a host that also runs nginx nginx process makes an outbound connection to rare/newly-seen external infrastructure nginx worker crash/respawn storm on a single host in a tight window (UAF/heap crash loop = exploit attempt or DoS)
# Fixed builds (CVE-2026-42530 / CVE-2026-42055): # NGINX Open Source 1.31.2 (and 1.30.x line: 1.30.3) # NGINX Gateway Fabric 2.6.4 # NGINX Plus R36 P6 / 37.0.2.1 # Check installed version (Linux): nginx -v # prints: nginx version: nginx/1.31.x dpkg -l | grep -i nginx # Debian/Ubuntu rpm -q nginx # RHEL/CentOS/Rocky # Vulnerable if < 1.31.2 (or 1.30.x < 1.30.3) for OSS; < 2.6.4 for NGF; < R36 P6 for Plus # Patch via package manager / Helm chart / container image bump, then reload: nginx -s reload
CVE-2026-42530 # UAF in ngx_http_v3_module (HTTP/3 QUIC, QPACK encoder reopen) - CVSS v4 9.2 - F5 K000161616 CVE-2026-42055 # heap overflow in ngx_http_proxy_v2_module + ngx_http_grpc_module - CVSS v4 9.2 - F5 K000161584 CVE-2026-11311 # NGF config injection (authenticated, high) - patched same release CVE-2026-50107 # NGF config injection (authenticated, high) - patched same release # Interim mitigations if you cannot patch immediately: # -42530: disable HTTP/3 — remove the 'quic' parameter from all 'listen' directives (and reuseport/http3 on) # -42055: remove 'ignore_invalid_headers off;' AND/OR set large_client_header_buffers below 2 MB # Keep ASLR enabled (kernel.randomize_va_space=2) - RCE requires ASLR disabled or bypassed # Defense-in-depth: terminate untrusted HTTP/3 at a patched edge; restrict who can reach NGINX listeners
Detection Validation Gates
| Gate | Check | Pass Criteria |
|---|---|---|
| Telemetry ready | Confirm Linux ProcessRollup2 retains ParentBaseFileName, and ElfFileWritten / NetworkListenIP4 carry ContextBaseFileName on NGINX hosts | Fields populated fleet-wide for nginx processes |
| Benign baseline | Run Q1/Q2 over a 30-day lookback in a clean environment | Zero hits after FastCGI/CGI and health-check exclusions — promote to IOA |
| Positive test | Lab: launch id / bash with nginx as the real parent via a benign harness (never the live exploit) | Q1/Q2 fire; lineage and CommandLine captured correctly |
| Inventory accuracy | Cross-check Q7 / N1 output against ground-truth nginx -v on a sample of hosts | Version parsing correct; vulnerable builds flagged, patched builds not |
| Promotion | Move Q1 to Custom IOA Detect+Block; Q2/Q3 to Detect | FP rate < 1/week sustained before Block mode |
Hardening — Tiered & Deployable
This is patchable — updating NGINX is the fix. The config mitigations below remove the trigger conditions for hosts that cannot patch immediately; everything else is defense-in-depth against web-server-exploit chains generally. Platforms touched: Linux hosts and containers, NGINX config, Kubernetes (NGF / Ingress), and the perimeter (LB / WAF).
- Update NGINX to ≥ 1.31.2 (or 1.30.3 on the 1.30.x line) / NGF 2.6.4 / Plus R36 P6 / 37.0.2.1 fleet-wide — M1051 (Update Software). Bump packages, Helm charts, and container base images; then
nginx -s reloador roll pods. The new binary is not effective until the worker restarts. - If you cannot patch immediately, disable HTTP/3 — M1042 (Disable or Remove Feature). Remove the
quicparameter from alllistendirectives (andhttp3 on;) to close CVE-2026-42530's trigger. - Neutralize the HTTP/2-proxy trigger — M1042. Remove
ignore_invalid_headers off;and/or setlarge_client_header_buffersbelow 2 MB to close CVE-2026-42055. - Keep ASLR enabled — M1050 (Exploit Protection). Confirm
kernel.randomize_va_space=2; RCE for both CVEs requires ASLR disabled or bypassed, so this is a meaningful backstop. Keep Falcon prevention on (M1040).
- Terminate untrusted HTTP/3 / HTTP/2 at a patched edge — M1037 (Filter Network Traffic). Front exposed NGINX with a patched LB / CDN that rejects malformed QUIC/QPACK and oversized HTTP/2 headers.
- Restrict who can reach NGINX listeners — M1030 (Network Segmentation). Limit UDP/443 (QUIC) and the gRPC/HTTP-2 upstream paths to required clients; firewall management/admin ports.
- Run NGINX as an unprivileged user in a confined sandbox — M1026 / M1048. Enforce
NoNewPrivileges, seccomp, and a read-only root FS via systemd / container security context so worker RCE has minimal blast radius. - Egress-filter web tiers — M1037. NGINX hosts rarely need arbitrary outbound; default-deny egress breaks reverse shells / payload pulls (improves Q5 fidelity).
- Read-only web roots + file-integrity monitoring — M1022 (Restrict File and Directory Permissions). Mount served content read-only and alert on any write to a web root (stops webshell drops even if the chain succeeds; backs Q3).
- Application allowlisting on web tiers — M1038 (Execution Prevention). Constrain which binaries can run on NGINX hosts so a dropped ELF cannot execute.
- Continuous NGINX version & config-drift monitoring — M1051. Alert fleet-wide when a build falls below the fixed version or when
quic/ignore_invalid_headers off/ oversized buffers reappear in config (N5).
Deployable Playbooks
Playbook A · Report installed NGINX version & flag vulnerable hosts (Linux, shell)
# 1. Print the running NGINX version
nginx -v 2>&1 # nginx version: nginx/1.31.x
dpkg -l | grep -i '^ii.*nginx' 2>/dev/null || rpm -q nginx 2>/dev/null
# 2. Flag vulnerable: OSS < 1.31.2 (or 1.30.x < 1.30.3)
ver=$(nginx -v 2>&1 | sed -E 's#.*nginx/([0-9.]+).*#\1#')
maj=${ver%%.*}; rest=${ver#*.}; min=${rest%%.*}; patch=${rest#*.}
if [ "$maj" -eq 1 ] && { [ "$min" -lt 30 ] \
|| { [ "$min" -eq 30 ] && [ "$patch" -lt 3 ]; } \
|| { [ "$min" -eq 31 ] && [ "$patch" -lt 2 ]; }; }; then
echo "VULNERABLE: nginx $ver -- patch to 1.31.2 / 1.30.3"
else
echo "OK: nginx $ver"
fi
Playbook B · Apply interim config mitigations (nginx.conf) — only if you cannot patch yet
# CVE-2026-42530 (HTTP/3 UAF): disable HTTP/3 / QUIC.
# In each server{} block, remove the 'quic' parameter and any 'http3 on;':
# - listen 443 quic reuseport; # <-- REMOVE this listener (or drop 'quic')
# listen 443 ssl; # keep TLS over TCP only
# - http3 on; # <-- REMOVE
# CVE-2026-42055 (HTTP/2 proxy/gRPC heap overflow): remove the trigger conditions.
# ignore_invalid_headers off; # <-- REMOVE (default is 'on')
# large_client_header_buffers 4 8k; # keep buffer size well below 2 MB
# Validate & reload:
nginx -t && nginx -s reload
# Confirm no quic listeners remain:
nginx -T 2>/dev/null | grep -E 'listen .*quic|http3 on|ignore_invalid_headers off'
Playbook C · Confirm ASLR is enabled (Linux) — RCE requires it disabled/bypassed
# Read current ASLR setting (2 = full randomization, the secure default): sysctl kernel.randomize_va_space # expect: kernel.randomize_va_space = 2 # If not 2, enable persistently: echo 'kernel.randomize_va_space = 2' > /etc/sysctl.d/99-aslr.conf sysctl --system # Harden the unit so worker RCE has minimal reach (systemd drop-in): # [Service] # NoNewPrivileges=yes # ProtectSystem=strict # ReadOnlyPaths=/usr/share/nginx/html
Containment Runbook
| Phase | Actions | Owner | Evidence |
|---|---|---|---|
| Isolate | Network-contain the host in Falcon on a confirmed Q1/Q2/Q3/Q4 hit; do not power off (preserve volatile state); for pods, cordon & capture before delete | SOC L2 | Containment timestamp; Q1–Q4 event rows |
| Triage | Pull the NGINX process tree: identify the master/worker PIDs, any spawned shell/recon process and its command line, any ELF/webshell the worker wrote, and any new listener; capture access/error logs around the event | SOC L2 | Process/file tree; nginx logs; Q1–Q4 rows |
| Eradicate | Remove dropped payloads/webshells from web roots and tmp paths; kill malicious processes and listeners; check cron / systemd units / timers / authorized_keys created post-compromise (N3) | IR | Web-root diff; cron/unit/key review |
| Recover | Patch NGINX to the fixed build and reload (or redeploy a clean image); rotate any secrets/keys/tokens stored on or reachable from the host; re-image / rebuild the image if OS-level code execution is confirmed | IR + IT | NGINX version; secret-rotation log |
| Harden | Confirm patch fleet-wide (Q7/N1); apply §12 controls (disable HTTP/3, fix header config, confirm ASLR, egress-filter); promote Q1 IOA to Detect+Block | Detection Eng | Patch coverage; config audit (N5); IOA enabled |
Detection Coverage Map
| Technique | Behavior | CQL | IOA | Coverage |
|---|---|---|---|---|
| — | Vulnerable NGINX version | Q7 | — | Good patch + N1 inventory |
| T1190 | Crafted HTTP/3 or HTTP/2-proxy request (delivery) | N4 | — | Partial edge/WAF-log-dependent (N4) |
| T1203 | In-worker UAF / heap corruption (in-process) | Q6 | — | GAP invisible to EDR; crash-storm proxy only |
| T1059.004 | NGINX worker spawns shell / interpreter | Q1 | IOA-1 | Good |
| T1082 / T1033 / T1105 | Worker spawns recon / download tool | Q2 | IOA-2 | Good |
| T1505.003 / T1105 | Worker writes webshell / ELF | Q3 | IOA-3 | Partial FP risk; scope exts / correlate |
| T1571 | New non-nginx listener (bind shell) | Q4 | — | Partial allow-list daemons per role |
| T1071.001 | Post-exploit egress / reverse shell | Q5 | — | Partial rarity-scoped pivot only |
| T1499.004 | Worker crash loop (DoS) | Q6 | — | Partial reload/autoscale FP; pair N2 |
Validation gates: (1) confirm Linux ProcessRollup2 retains ParentBaseFileName + ElfFileWritten/NetworkListenIP4 context fleet-wide; (2) Q1/Q2 return zero hits in a 30-day benign lookback after FastCGI/health-check exclusions; (3) inventory NGINX versions (Q7/N1) and confirm the fixed build; (4) lab-validate lineage firing with a benign nginx-parent harness — never the live exploit; (5) promote Q1 to Custom IOA Detect+Block (target FP < 1/week). The in-worker UAF/heap step is an accepted detection gap — mitigated by the patch, config mitigations, ASLR, and the crash-storm proxy (Q6).
Hunt Summary Ticket
TITLE: Hunt - F5 NGINX CVE-2026-42530 (HTTP/3 UAF) & CVE-2026-42055 (HTTP/2 proxy/gRPC heap overflow)
SEVERITY: Critical (CVSS v4 9.2 x2; remote unauthenticated; DoS reliable, RCE where ASLR disabled/bypassed)
SCOPE: Linux hosts/containers running NGINX OSS < 1.31.2 (1.30.x < 1.30.3) / NGF < 2.6.4 / Plus < R36 P6
HYPOTHESIS: A crafted HTTP/3 (QPACK encoder reopen) or oversized HTTP/2-proxy request corrupts NGINX
worker memory -> worker crash loop (DoS) and, where ASLR is off/bypassed, code execution in
the worker; attacker spawns a shell/recon tool, drops a webshell/ELF, opens a listener, and
beacons out. EDR sees the post-exploit consequences (worker-parented exec / file write / net).
QUERIES RUN: Q1 nginx->shell/interpreter (IOA) | Q2 nginx->recon/download (IOA) | Q3 nginx writes ELF/webshell (IOA) |
Q4 new non-nginx listener | Q5 rare nginx egress | Q6 worker respawn storm | Q7 vulnerable version inventory
+ Native N1-N5 (version inventory, crash logs, persistence, edge traffic, config audit)
DO FIRST: Patch NGINX >= 1.31.2 / 1.30.3 / NGF 2.6.4 / Plus R36 P6 and reload (Q7/N1); else disable HTTP/3 and
remove ignore_invalid_headers off / shrink buffers (S12); confirm ASLR=2; then Q1, Q2 - escalate any hit
FINDINGS: <pending analyst execution>
GAPS: In-worker UAF/heap primitive invisible to EDR (in-process); delivery step needs edge/WAF logs
ACTIONS: Patch fleet-wide; disable HTTP/3 + fix header config; egress-filter web tiers; read-only web roots;
promote Q1 to Custom IOA Detect+Block
OWNER: HuntPack
VERSION: v0.1 - 2026-06-19
Changelog
table() calls now carry an explicit row limit: the default is 200 and truncation is silent, so a capped result was indistinguishable from a complete one. Atomic-IOC sweeps (filters over 5+ hashes or C2 IPs) use limit=max so a wide infection is never silently under-scoped; behavioural hunts use limit=200, where exceeding the cap indicates the query needs tuning. Where present, event names that do not exist in the Falcon data model were corrected (e.g. ServiceInstalled is a Sysmon concept, not a Falcon event; ElfFileWritten is ELFFileWritten) — such queries could never return a row. No detection logic, fields, or IOCs changed.References
| Tier | Source | Used For |
|---|---|---|
| 1 | F5 Advisory K000161616 — CVE-2026-42530 (NGINX HTTP/3 UAF) | Authoritative affected/fixed versions; trigger conditions; mitigation (disable HTTP/3) |
| 1 | The Hacker News — F5 Patches Two Critical NGINX Open Source Flaws Enabling RCE | CVSS v4 9.2 x2; mechanism (QPACK reopen UAF / HTTP/2 heap overflow); ASLR caveat; full affected-product list; fixed builds; advisory IDs |
| 2 | SecurityWeek — F5 Patches Critical, High-Severity NGINX Vulnerabilities | Two criticals + high-sev NGF config-injection bugs (-11311/-50107); affected families; mitigation framing |
| 2 | BleepingComputer — F5 issues out-of-band patches for critical NGINX vulnerabilities | Out-of-band release (18 Jun 2026); no active exploitation reported; mitigation (remove quic from listen); F5 targeting history |
| 2 | Security Affairs · Cyber Security News · GBHackers | DoS-via-worker-crash as reliable outcome; RCE conditional on ASLR; impact framing; patch-now guidance; no IOCs |
HuntPack v0.1 · F5 NGINX CVE-2026-42530 / CVE-2026-42055 (critical unauthenticated RCE) · Generated 2026-06-19 · Defensive use only — no exploit code. The patch (NGINX ≥ 1.31.2 / 1.30.3, NGF 2.6.4, Plus R36 P6 / 37.0.2.1) is the fix; config mitigations (disable HTTP/3, fix header handling) close the trigger conditions; behavioral hunts cover the post-exploitation chain and are durable defense-in-depth for web-server-exploit follow-on. No atomic IOCs, PoC, or confirmed in-the-wild exploitation were published as of generation; validate field names (especially the Q7 version feed) in your tenant before promoting any query to alerting.