[BREAKING / DEVELOPING — 22 October 2026] Two critical, unauthenticated remote code execution vulnerabilities in PHP core — collectively nicknamed PHP2Shell and tracked as CVE-2026-109618 and CVE-2026-109619 — were patched in an emergency PHP release on 21 October 2026. The PHP security team rates each one 9.2 on CVSS v4.0 (Critical). Because the bugs live in the PHP engine itself and not in any application, researchers estimate they are reachable on roughly 70% of all websites. Technical details leaked publicly on 20 October — two days before the planned coordinated disclosure — and in-the-wild exploitation attempts were observed within hours.
[Editorial note] This is a fast-moving situation. This post is a defensive and analytical writeup — root cause, attack-chain mechanics, and detection engineering. It deliberately contains no working exploit code. These are live, unauthenticated RCE zero-days under active mass exploitation; the responsible contribution right now is faster detection and patching, not a weaponized proof of concept. Patch first, hunt second, read later.
TL;DR — What You Need to Do in the Next Hour
- Patch now. Upgrade to PHP 8.5.12, 8.4.27, 8.3.36, or 8.2.35 (or later), then restart every PHP worker (PHP-FPM, Apache mod_php, LiteSpeed/lsphp, FrankenPHP). A patched binary that is still running old workers is still vulnerable.
- If you cannot patch immediately (end-of-life PHP 8.1 / 7.x / 5.x, or a change-freeze), apply the interim hardening below: disable
session.upload_progress, setfatal_error_backtraces=0on 8.5, and considerpm.max_requests = 1to kill cross-request worker reuse. - Hunt now. Deploy the Sentinel / Defender XDR KQL, the Sigma rule, and the web/WAF signatures in this post. Look back to at least 17 October 2026 — the earliest observed exploitation predates disclosure.
- Scan your estate. Burp Suite Professional and Burp Suite DAST now ship a PHP2Shell check; free non-destructive version-fingerprint scanners are also available.
What Is PHP2Shell?
PHP2Shell is the researcher nickname for two distinct but related memory-safety flaws in the PHP interpreter’s request lifecycle. Both are fundamentally use-after-free conditions in PHP’s core engine, and both can be reached before a single line of your application code runs. That last point is what makes this so dangerous: it does not matter whether you run WordPress, Drupal, Joomla, Laravel, a bespoke API, or a one-line “Hello World” script. If a vulnerable PHP build is serving web requests, it is exposed. Wiz Research, which discovered the flaws, demonstrated unauthenticated RCE against WordPress, Drupal, and Joomla in their default configurations.
The vulnerable code paths trace back to PHP 5.4.0, released in 2012. In practice that means essentially every PHP deployment of the last decade is affected by at least one of the two issues. The flaws are present across PHP-FPM, Apache with mod_php, the legacy php-cgi SAPI, FrankenPHP, and LiteSpeed/LSAPI.
CVE : CVE-2026-109618 + CVE-2026-109619
CLASS : Use-after-free -> memory disclosure + RCE
AUTH : None (unauthenticated, pre-application)
CVSS v4.0 : 9.2 / 9.2 (Critical)
VECTOR : HTTP POST, multipart/form-data
AFFECTED : PHP 5.4.0 (2012) -> all builds before the 21 Oct 2026 patches
REACH : ~70% of all websites
DISCOVERY : Wiz Research (AI-assisted)
PATCHED : 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 (21 Oct 2026, 14:00 UTC)
STATUS : Actively exploited in the wild
Disclosure Timeline: A Coordinated Release That Leaked Early
The disclosure of PHP2Shell did not go to plan, which is part of why defenders were caught flat-footed. The sequence of events:
| Date (2026) | Event |
|---|---|
| 17 October | Earliest known exploitation attempt recorded by Amazon’s MadPot honeypot network — four days before public disclosure, suggesting a limited pre-disclosure leak. |
| 20 October | Technical details of the vulnerabilities leaked publicly (surfacing on Hacker News and X), two days ahead of the planned coordinated disclosure date of 22 October. |
| 21 October, 07:43 UTC | watchTowr’s Attacker Eye honeypot network observes exploitation attempts at scale, mostly through PHP’s session upload-progress path. |
| 21 October, 14:00 UTC | PHP project moves its emergency release forward and ships patched builds: 8.5.12, 8.4.27, 8.3.36, 8.2.35. |
| 22 October onward | Broad opportunistic scanning and exploitation continues. Vendor detections (Burp Suite, CrowdStrike, Wiz, Datadog) and community IOC/rule repositories go live. |
The lesson for defenders mirrors every recent mass-exploitation event we have covered, from the record-breaking July 2026 Patch Tuesday onward: the window between “details are public” and “everyone is being scanned” is now measured in hours, not days.
Discovered by AI: Why That Matters
PHP2Shell is notable not just for its blast radius but for how it was found. Wiz Research used a combination of frontier AI models to audit PHP’s engine and chain the bugs into working exploits — collapsing what the team estimated would traditionally be months of specialized memory-corruption work into roughly one week.
The strategic takeaway for both red and blue teams: large language models now meaningfully lower the barrier to adapting a memory-corruption exploit across different PHP versions, build configurations, and heap layouts — the exact “last mile” engineering that historically kept use-after-free bugs out of the hands of commodity attackers. Expect the gap between disclosure and reliable, version-agnostic exploitation to keep shrinking. This is the same force-multiplier dynamic we have tracked in nation-state tradecraft such as Volt Typhoon’s living-off-the-land operations, now arriving at the commodity tier.
Root Cause: Two Use-After-Frees in the Request Lifecycle
To understand both detection and mitigation, you need the mechanism. The common denominator is PHP’s behaviour under a fatal error mid-request — most reliably an out-of-memory (OOM) condition when a request crosses the configured memory_limit.
When PHP hits a fatal error, it performs a non-local jump (a longjmp) to abort the current request and unwind. The problem: that jump can fire while the request’s internal data structures are only partially initialized. PHP’s subsequent cleanup then operates on half-constructed state as though it were valid — freeing, reusing, or dereferencing memory that is not in the state the engine assumes. An attacker who can deterministically trigger the OOM at the right moment controls the conditions of that corruption.
CVE-2026-109618 — Upload-Progress Unserializer Use-After-Free
This is the primary mass-exploitation path. PHP’s session upload-progress feature tracks the state of large file uploads so applications can show progress bars. Critically, this handler runs early in request processing — before application initialization, which is exactly why no amount of application-layer authentication or WAF logic in your code protects against it.
By sending a crafted multipart/form-data body that forces an allocation failure during session decoding, an attacker interrupts the unserializer while its state is corrupt. A later operation reuses that freed/stale state, yielding first a remote process-memory disclosure primitive (leaking whatever is resident in the worker’s heap — database credentials, API keys, session tokens, other users’ data) and, when chained, full remote code execution. The prerequisites on the target side are simply that session.upload_progress is enabled (it is, by default) and that the request carries a PHPSESSID.
CVE-2026-109619 — Fatal-Error Backtrace UAF + OPcache Type Confusion
The second flaw abuses PHP’s fatal-error backtrace machinery. Dangling backtrace pointers created during a fatal error can survive the destruction of the request that created them. Because PHP-FPM reuses worker processes across many requests, a later request served by the same worker can then reference that stale state — a classic cross-request use-after-free.
Worse, it chains into an OPcache type confusion: partial object state persists in OPcache’s shared memory, leaving stale metadata that points to objects of the wrong type across workers. Type confusion of shared, cross-worker metadata is a powerful RCE primitive. In total, Wiz identified four exploitable bugs clustered under these two CVE identifiers.
[2] | force OOM at memory_limit mid-parse
[3] v
[4] PHP longjmp aborts request with half-initialized state
[5] | cleanup treats corrupt state as valid (UAF)
[6] v
[7] PRIMITIVE A: leak worker heap –> creds / tokens / API keys
[8] PRIMITIVE B: cross-request / cross-worker type confusion
[9] |
[10] v
[11] REMOTE CODE EXECUTION –> webshell / reverse shell / persistence
Exploitation Chaining: Where This Goes After Initial Access
From a defender’s threat-model perspective, the RCE is the beginning, not the end. The observed and expected post-exploitation chain:
- Memory disclosure → credential harvesting. CVE-2026-109618’s read primitive leaks whatever is in worker memory. On a busy app that is a goldmine: database connection strings, cloud API keys, OAuth/JWT secrets, and live session tokens. This enables account takeover and lateral movement even if the RCE itself is mitigated. Treat any secret that was resident in a vulnerable worker as burned — rotate it.
- RCE → webshell drop. In a Huntress-documented incident, the attacker ran a one-liner that wrote a small PHP file with random marker strings into the first writable temp directory, executed it, then deleted it — a quick capability check before heavier payloads. Expect short-lived files in
/tmp,/var/tmp,/dev/shm, or Windows temp paths. - Persistence. New cron jobs / scheduled tasks, new local accounts, and webshells planted in the web root are the standard follow-on. This is where the attack starts to look like any other web-server compromise and where endpoint telemetry becomes your best friend.
- Mass CMS compromise. Because default WordPress/Drupal/Joomla installs are exploitable, shared-hosting and agency estates are high-value targets for bulk compromise and web-shell farms. If you run many PHP sites on one host, assume you are being scanned.
Am I Affected? Version Matrix
| Your PHP version | Status | Action |
|---|---|---|
| 8.5.x before 8.5.12 | Vulnerable | Upgrade to 8.5.12+ |
| 8.4.x before 8.4.27 | Vulnerable | Upgrade to 8.4.27+ |
| 8.3.x before 8.3.36 | Vulnerable | Upgrade to 8.3.36+ |
| 8.2.x before 8.2.35 | Vulnerable | Upgrade to 8.2.35+ |
| 8.1.x and older (7.x, 5.x) | Vulnerable & End-of-Life | No official patch. Migrate to a supported branch; apply interim hardening immediately. |
| 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 and later | Patched | Confirm workers were restarted after upgrade. |
Burp Suite Just Shipped PHP2Shell Detection
PortSwigger moved fast: PHP2Shell detection is now available in Burp Suite Professional and Burp Suite DAST. If you do offensive assessment or authorized VAPT, you can detect CVE-2026-109618 / CVE-2026-109619 across your scope through:
- ActiveScan++ v2.0.13 — the extension’s updated active scan check covers PHP2Shell.
- BChecks — PortSwigger’s custom-check format, for teams that want to pin the exact detection logic.
- Bambda scan checks — programmatic, Java-lambda-style checks inside Burp.
For non-destructive estate-wide triage outside Burp, several free PHP2Shell scanners are available (for example pentest-tools.com’s hosted check, and open-source fingerprint scanners on GitHub). These are version-fingerprint and session-write oracle style checks — they confirm exposure without attempting memory corruption, which is the right approach for production estates. Always confirm you have written authorization before scanning any asset you do not own.
Blue Team Detection: The Honest Picture First
Before the queries, an important caveat that the best researchers (Datadog, Huntress, the community rule authors) all stress: the use-after-free itself — the cross-request worker-reuse corruption — generally cannot be seen in standard web, WAF, or EDR logs. What you can detect is (a) the amplification technique attackers use to drive PHP into the vulnerable OOM path, and (b) the post-exploitation symptoms — shells, dropped files, recon commands. Build layered detection and correlate; do not rely on any single signal.
1. Web Server / WAF Request Signatures
Every known trigger is a multipart/form-data POST. The documented request-level tells:
- Abnormally long form field names — on the order of several megabytes (reports cite field names around 3.5 MB) used to drive the allocator toward OOM.
- Binary data with null bytes in empty-named fields, and body shapes along the lines of
=[binary]&a=1&[oversized_name][x]=1. - Excessive / duplicate multipart part headers — the RFC 1867 header-amplification producer signal.
- Requests that carry a
PHPSESSIDand target an endpoint withsession.upload_progressactive.
WAF guidance: flag multipart submissions with unusually long field names and unexpected control bytes. One sharp caveat from Datadog: a rule cannot inspect bytes that the engine truncates — tune field-size inspection limits to your legitimate-traffic baseline so you are actually examining the oversized fields rather than silently dropping them.
2. PHP and Web Server Error-Log Signatures
The clearest host-side tell for CVE-2026-109618 is an OOM fatal error during initialization, not inside application code:
PHP Fatal error: Allowed memory size of NNNN bytes exhausted (tried to allocate NNNN bytes) in Unknown on line 0
The in Unknown on line 0 portion is the hallmark — it means the failure happened before any script context existed, i.e. in the pre-application parsing phase this exploit abuses. On Apache you may also see worker crashes during address-guessing attempts:
AH00052: child pid NNNN exit signal Segmentation fault (11)
Note: a successful exploit does not necessarily crash the worker, so treat crashes as a supporting signal, not a prerequisite.
3. Microsoft Sentinel — Hunt PHP Error Floods and 500 Bursts
If you ship PHP/web logs into Sentinel (via Syslog, AMA, or a custom table), hunt the OOM-at-init signature and bursts of HTTP 500s on POST. Adjust table and field names to your schema (Syslog, W3CIISLog, AGWAFAccessLogs_CL, nginx/Apache custom logs, etc.).
// Sentinel — PHP out-of-memory at initialization (CVE-2026-109618 tell)
Syslog
| where SyslogMessage has "Allowed memory size of"
| where SyslogMessage has "in Unknown on line 0"
| summarize Hits = count(), Sample = take_any(SyslogMessage) by Computer, bin(TimeGenerated, 5m)
| where Hits >= 3
| sort by Hits desc
// Sentinel — burst of HTTP 500 on multipart POST from a single source
// Swap W3CIISLog for your web-access table; csMethod/scStatus/cIP as appropriate.
W3CIISLog
| where csMethod == "POST"
| where scStatus == 500
| summarize Count = count(), Paths = make_set(csUriStem, 20) by cIP, bin(TimeGenerated, 5m)
| where Count >= 10
| sort by Count desc
4. Microsoft Defender XDR (Advanced Hunting) — Post-Exploitation
This is where you have the strongest ground truth: a PHP worker should almost never spawn an interactive shell or recon binary. These queries run in Microsoft Defender XDR Advanced Hunting and are directly portable to Sentinel analytics rules.
Query 1 — PHP worker spawning a shell or recon/download tool:
DeviceProcessEvents
| where InitiatingProcessFileName in~ ("php-fpm","php-fpm8","php-cgi","php-cgi.exe","php","php.exe","httpd","apache2","lsphp","litespeed")
| where FileName in~ ("sh","bash","dash","zsh","cmd.exe","powershell.exe","pwsh.exe",
"python","python3","perl","ruby","curl","wget","nc","ncat",
"certutil.exe","bitsadmin.exe","whoami","whoami.exe","id","uname")
| project Timestamp, DeviceName, AccountName,
InitiatingProcessFileName, InitiatingProcessCommandLine,
FileName, ProcessCommandLine
| sort by Timestamp desc
Query 2 — reverse-shell and encoded-command patterns from web workers:
DeviceProcessEvents
| where InitiatingProcessFileName has_any ("php","apache","httpd","lsphp","litespeed")
| where ProcessCommandLine has_any ("/dev/tcp/","fsockopen","mkfifo","bash -i",
"nc -e","/bin/sh -i","-enc ","FromBase64String",
"IEX","Invoke-Expression")
| project Timestamp, DeviceName, AccountName, InitiatingProcessCommandLine, ProcessCommandLine
| sort by Timestamp desc
Query 3 — short-lived PHP files dropped into writable temp directories (Huntress pattern):
DeviceFileEvents
| where ActionType in ("FileCreated","FileModified")
| where FolderPath has_any ("/tmp/","/var/tmp/","/dev/shm/","\Temp\","\Windows\Temp\")
| where FileName endswith ".php"
| where InitiatingProcessFileName has_any ("php","apache","httpd","lsphp","sh","bash")
| project Timestamp, DeviceName, FolderPath, FileName, ActionType, InitiatingProcessCommandLine
| sort by Timestamp desc
Correlate Query 1-3 hits for the same device/time window with the web-log 500 bursts from the Sentinel queries to build a high-confidence incident. For a worked methodology on stitching process, file, and network telemetry into a single attack narrative, see our Volt Typhoon KQL threat-hunting playbook.
5. Sigma Rule (Portable to Any SIEM)
title: PHP Worker Spawning Suspicious Child Process (Possible PHP2Shell Post-Exploitation)
id: 7e1c9a30-php2-shell-2026-109618-109619
status: experimental
description: Detects php-fpm/php-cgi/apache/lsphp spawning shells, recon, or download
utilities, consistent with post-exploitation of CVE-2026-109618 / CVE-2026-109619.
references:
- https://sansec.io/research/php2shell
- https://www.huntress.com/blog/php2shell-leaked-critical-php-vulnerabilities
logsource:
category: process_creation
detection:
parent:
ParentImage|endswith:
- '/php-fpm'
- '/php-cgi'
- '/httpd'
- '/apache2'
- '/lsphp'
- 'php-cgi.exe'
child:
Image|endswith:
- '/sh'
- '/bash'
- '/dash'
- 'cmd.exe'
- 'powershell.exe'
- '/python3'
- '/perl'
- '/curl'
- '/wget'
- '/nc'
condition: parent and child
falsepositives:
- Applications that legitimately call exec()/shell_exec()/system(). Baseline first.
level: high
6. Network Detection (Suricata) and Endpoint Agents
The community IOC/rule repositories have published Suricata coverage for the amplification technique. At time of writing the active SIDs are 9109627, 9109633, and 9109637 (several earlier SIDs were retired in favour of these). Conceptually they match the RFC 1867 header-amplification / oversized multipart field-name producer signal rather than the UAF itself — again, you are catching the technique, not the memory corruption.
On the endpoint, vendors have shipped behavioural coverage: CrowdStrike Falcon flags the PHP-worker-spawns-shell behaviour, and Wiz’s runtime sensor can terminate processes exhibiting exploitation behaviour. If you have no EDR on your Linux web tier, Florian Roth’s open-source process-watcher run in observe mode is a lightweight stopgap for spotting anomalous PHP child processes.
Mitigation and Hardening (When You Cannot Patch Yet)
Patching + worker restart is the only real fix. But if you are stuck on EOL PHP or in a change freeze, these interim controls reduce exposure. Treat them as temporary.
; php.ini — reduce exposure to the upload-progress path (CVE-2026-109618)
session.upload_progress.enabled = 0
; PHP 8.5 only — disable fatal-error backtraces (CVE-2026-109619 path)
fatal_error_backtraces = 0
; php-fpm pool — kill cross-request worker reuse (defeats the stale-state reuse)
; Costs performance; use as a stopgap on exposed pools.
pm.max_requests = 1
- Rebuild container images with a patched PHP base image and redeploy — do not just
apt upgradeinside a running container and forget the image. - Restart all workers after any upgrade. This is the single most-missed step.
- Front your origin with a WAF tuned to the multipart signatures above, and rate-limit anonymous POSTs to upload endpoints.
- Rotate secrets that could have been resident in worker memory on any internet-facing host that ran a vulnerable build (DB passwords, API keys, JWT/session secrets).
Incident Response Checklist
- Confirm current PHP version on every host:
php -vand per-SAPI (php-fpm -v). Do not trust the package manager alone — check what the running workers actually loaded. - Patch to the fixed branch and restart every worker / reload FPM. Re-verify.
- Run the Defender XDR / Sentinel queries and the Sigma rule, looking back to at least 17 October 2026.
- Grep web roots and temp directories for new/unknown
.phpfiles, especially randomly named ones. Review new cron jobs, scheduled tasks, and local accounts. - If you find evidence of RCE: isolate the host, preserve logs and memory, rotate all secrets that touched that host, and treat it as a full web-server compromise. In India, assess CERT-In’s 6-hour reporting obligation and any DPDPA 2023 personal-data breach notification duty.
- Scan the rest of the estate with Burp Suite’s PHP2Shell check or a free non-destructive scanner to find stragglers.
Conclusion
PHP2Shell is close to a worst-case web vulnerability: unauthenticated, pre-authentication, pre-application, present for over a decade, reachable on most of the internet, and already exploited in the wild before its patches landed. The engine-level nature means no framework or application-layer control fully protects you — only a patched, restarted interpreter does. Its AI-assisted discovery is also a signal of where vulnerability research is heading: the time from disclosure to reliable, version-agnostic exploitation is collapsing, and defenders have to assume the scan is already underway.
Patch to 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12, restart your workers, deploy the detections above, hunt backwards to mid-October, and rotate anything a vulnerable worker could have held in memory. This post will be updated as confirmed IOCs and further analysis are published.
Primary Sources & Further Reading:
- Sansec — PHP2Shell: Critical PHP RCE (CVE-2026-109618, CVE-2026-109619)
- Wiz Research — PHP2Shell: AI uncovers critical RCE vulnerabilities affecting 70% of the internet
- watchTowr — PHP RCE FAQ (CVE-2026-109618 & CVE-2026-109619)
- Huntress — Rapid Response: php2shell, Leaked Critical PHP Vulnerabilities
- Datadog Security Labs — PHP2Shell: Detection, Analysis, and Remediation
- The Hacker News — PHP Issues Emergency Patches for Two Critical PHP2Shell RCE Flaws
- BleepingComputer — PHP ships emergency patches for critical PHP2Shell flaws
- Help Net Security — PHP2Shell: Critical PHP vulnerabilities patched, update now
- CrowdStrike — Protecting Customers from Threats Delivered via PHP2Shell
- PortSwigger / Burp Suite — PHP2Shell detection now in Burp Suite Professional & DAST
Related Research from Vivek Verma | Cybersecurity: