PHP2Shell: Inside the PHP Runtime Flaws That Turn Fatal Errors into Remote Code Execution
Key Observations
- Critical PHP runtime vulnerabilities. PHP released fixes on 21 October 2026 for CVE-2026-109618 (out-of-memory state corruption) and CVE-2026-109619 (stale global state / use-after-free). Both have CVSS v4.0 scores of 9.2.
- The weakness is in PHP core, not a CMS plugin. Both vulnerabilities concern native PHP request handling; updating a web application or CMS alone does not resolve an affected runtime.
- Fatal errors can expose memory-safety failures. Partially initialized state and stale worker-global references may be consumed during later cleanup, startup or session operations.
- Unauthenticated RCE is demonstrated but conditional. Researchers showed memory disclosure and code execution in controlled configurations. Actual exploitability varies with PHP version, SAPI, configuration and reachable request paths.
- Exploitation attempts predate the public patch. AWS MadPot telemetry identified attempted activity as early as 17 October 2026; attempted activity does not by itself demonstrate widespread successful compromises.
- Defender priority is runtime-level exposure reduction. Inventory externally exposed PHP services, verify vendor patches and backports, correlate request and process anomalies, and investigate systems showing credible compromise indicators.
| Tracking | CVE-2026-109618 (OOM corruption); CVE-2026-109619 (stale global state / UAF) |
|---|---|
| Severity | Critical; CVSS v4.0 9.2 (AV:N / AC:H / AT:P / PR:N / UI:N). Neither 9.8 nor 10.0. |
| Authentication / access | Network reachable; no application login required for confirmed chains; real exploitability is deployment-dependent |
| Confirmed impact | Web-worker-context RCE; process-memory disclosure; crash and memory corruption |
| Fixed upstream releases | 8.5.12; 8.4.27; 8.3.36; 8.2.35 (21 October 2026) |
| Scope | PHP request-serving deployments; Apache mod_php highest-confirmed pre-application risk |
| Confidence | PHP project advisories and original researcher demonstrations; hunting signals alone are not proof of compromise |
1. Why PHP2Shell is different from an application vulnerability
Traditional PHP RCE findings often rely on an unsafe application operation — such as user-controlled deserialization, template evaluation or command execution. PHP2Shell instead abuses memory-management and lifecycle invariants in native PHP components. Normal application authorization checks may never run before an unsafe startup path is reached. This is why applying a WordPress, Drupal or Joomla plugin update alone cannot resolve the underlying runtime flaw.
PHP executes requests through a Server API (SAPI), such as Apache mod_php, PHP-FPM, CGI/FastCGI or server integrations such as FrankenPHP and LiteSpeed. SAPIs differ in how workers start, initialize modules, parse request bodies and recover from failed request startup. Those differences are material to exploitability. The most rigorous assessment is therefore version + vendor patch status + SAPI + reachable request behavior + lifecycle conditions — not a banner match alone.

2. The vulnerable lifecycle: where memory-safety assumptions fail
2.1 Zend request memory, fatal exits and cleanup
A PHP worker retains process-level structures between requests, while the request allocator owns values that should die at the end of an individual request. During request initialization, automatic parsing of RFC 1867 multipart/form-data may allocate PHP arrays, session bookkeeping and other request-lifetime structures before application PHP code is invoked. For the affected code, memory exhaustion could invoke longjmp(), unwinding execution past normal cleanup and initialization logic.
Two safety invariants matter. First, shutdown code must never interpret a partially initialized structure as complete. Second, any worker-global pointer referring to request-owned memory must be invalidated before that memory is released. PHP2Shell breaks both invariants under particular fatal-error and state-transition conditions. The important distinction is not that PHP "accepts malicious PHP code"; rather, crafted inputs can influence native allocation and control flow so that a memory-safety failure becomes exploitable.

3. CVE-2026-109618: out-of-memory corruption
3.1 Root cause and attack surface
The PHP advisory documents cases in which OOM occurs while request state is visible but not fully initialized; subsequent request shutdown reads or branches on invalid state. The allocation that fails does not have to be the allocation that created the incomplete object. That temporal separation is important: treating this solely as a "large request" DoS bug misses the memory-corruption consequence.
Publicly documented pressure points within multipart parsing include (1) bodies without a usable declared content length bypassing an early post_max_size check, (2) unusually many headers in a single multipart part causing internal representations to expand far beyond their wire size, and (3) empty file controls and nested field names generating significant metadata/array work without equivalently consuming max_file_uploads accounting. An application-specific allocator-heavy route can also provide an OOM condition. These are classes of trigger, not universal exploit signatures.
3.2 SAPI-specific consequences
For Apache mod_php, the official analysis confirms that request shutdown is invoked even when startup fails. This makes a pre-application, unauthenticated trigger possible with default input and memory limits; complete RCE has been demonstrated on mod_php. In PHP-FPM, failure during php_request_startup() causes the worker child to exit, avoiding that exact startup-to-shutdown sequence; however, a later OOM after successful startup may still encounter susceptible internal state. The advisory states that a complete FPM exploit for this particular CVE was not demonstrated, while independent PHP Foundation reporting confirms FPM RCE through application-level code paths in the broader issue set.

3.3 Why the patch works
The PHP fix changes the OOM response rather than trying to enumerate every vulnerable cleanup consumer. Instead of immediately longjmp()-ing out of unsafe native contexts, PHP uses a deferred soft-OOM at a VM safe point and an immediate hard-OOM _exit() when a second, higher threshold is reached. This design prevents shutdown from observing partially initialized state while retaining bounded execution-memory behavior. These are internal implementation changes: editing a PHP configuration file cannot reproduce the same guarantee.
4. CVE-2026-109619: stale global state across requests
4.1 The producer-consumer pattern
The second CVE concerns persistent worker globals — covering error, session, object and extension state — that can retain pointers to allocations belonging to a terminated request. A producer places request-owned state in a globally reachable location; an interruption or late diagnostic leaves it published; PHP frees the request heap; the same worker then serves another request; and an early consumer reads or destroys the stale object before standard initialization resets it. This is a cross-request use-after-free, and exploit success depends on the relevant requests reaching the same worker and on suitable allocation patterns.

4.2 Four research primitives grouped into two CVEs
| Primitive | Native state / consequence |
|---|---|
| Upload-progress unserializer UAF | BG(unserialize) retains request-owned decoder bookkeeping; an interrupted operation can leave it accessible to subsequent upload-progress handling, supporting a memory-corruption chain. |
| Session ID memory disclosure | PS(id) can outlive its allocation; a later multipart upload path can URL-encode reclaimed data into a PHPSESSID response cookie. Application session_start() is not required for this demonstrated primitive. |
| Fatal-error backtrace UAF | EG(last_fatal_error_backtrace) can point into a freed request heap; an early diagnostic in the same worker can consume it, producing exploitable corruption. |
| OPcache runtime-pointer type confusion | A failure between process-local map_ptr index advancement and publication to shared OPcache metadata can create cross-worker slot/type disagreement. |
Wiz's published mapping groups its upload-progress unserializer and process-memory disclosure research under CVE-2026-109618, and fatal-error backtrace and OPcache type-confusion work under CVE-2026-109619. The root-cause CVE descriptions are broader; individual primitives and their prerequisites should not be mistaken for interchangeable exploits.
4.3 Concrete consumers and configuration pitfalls
The official stale-state advisory identifies early INI diagnostics and session upload-progress handling as confirmed pre-initialization consumers. Certain deprecated, malformed or conflicting settings can produce a warning or deprecation before normal executor initialization, including legacy assert.* or session directives in applicable releases. Importantly, suppressing display_errors, log_errors or error_reporting does not prevent the underlying consumption: PHP touches the stale state before deciding whether to display or log the diagnostic.
For PHP 8.5, the fatal_error_backtraces feature appears in a confirmed mod_php chain. The advisory also validates a session-lifecycle RCE path under FPM, but that route requires a suitable application operation after successful startup to leave stale state for a later session-upload-progress consumer. A generic claim that every PHP-FPM endpoint admits pre-application RCE is therefore unsupported.
5. Exposure and exploitability by runtime architecture
| Deployment | What is established | Defensive interpretation |
|---|---|---|
| Apache mod_php | Pre-application multipart startup/shutdown exploitation and unauthenticated RCE demonstrated. | Highest priority for internet-facing inventory and immediate patching. |
| PHP-FPM / FastCGI | Failed-startup child exits; conditional application-execution and session-lifecycle paths remain relevant. | Do not call safe; examine routes, session features, INI diagnostics and vendor patch state. |
| FrankenPHP | Official source analysis suggests unconditional shutdown may resemble mod_php; application-independent exploit is not equivalently validated. | Treat as exposed pending update, without stating a proven identical RCE chain. |
| LiteSpeed / LSAPI | Models some FPM behavior; early configuration/extension cases are conditional and not fully validated. | Patch and monitor; avoid categorical claims based on SAPI name. |
| php-cgi / other handlers | Included in PHP's affected request-serving scope; configurations vary. | Confirm installed library/runtime and handling model through authenticated inventory. |
Versions: PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12 are the fixed upstream lines as of this report. PHP 8.1 and older are no longer maintained by the upstream PHP project; its team published minimal source backports for 7.4, 8.0 and 8.1, and some distributions/LTS vendors ship patched packages with older-looking version strings. Vulnerable history reaches at least PHP 5.4 for one or more mechanisms, but exact primitives and reliability are version-dependent. A plain version comparison is not a substitute for checking vendor changelogs and package revisions.

6. What is actually known about exploitation?
The PHP Foundation reports that two CVE identifiers leaked publicly on 20 October (with an incorrect CVSS 10.0 claim), causing disclosure and patch release to move forward to 21 October. Its security team inspected circulating proof-of-concepts and had not confirmed functional exploits at the precise release time. Separately, Amazon Threat Intelligence subsequently reported a 17 October exploitation attempt in MadPot, additional attempts on 21 October and broad post-disclosure attempts against its sensors. These reports describe different vantage points and observation times.
Cloudflare independently reported attack traffic against customers and evasive payload variation around 21 October. None of those vendor reports justifies invented milestones such as "thousands of victims compromised in 12 hours," "Fortune 500 entities hit" or "ransomware deployed everywhere."

7. Detection engineering: signals and correlation
7.1 High-value observable signals
| Telemetry | Behavior worth investigating | Interpretation / limits |
|---|---|---|
| Reverse proxy / WAF | Unexpected multipart/form-data POSTs, unusual request framing, high repetition to PHP routes, size/header anomalies. | Multipart use is common; correlate with downstream errors rather than alerting on form data alone. |
| HTTP response | Repeated 500/502/503 responses, unusual or oversized PHPSESSID Set-Cookie values after upload traffic. | Cookie anomalies align with reported memory-leak behavior but are not alone proof of exploit. |
| PHP logs / FPM | Allowed memory size exhausted, fatal errors, timeouts, initialization warnings, repeated worker exits or replacements. | Some unsafe paths may emit no usable application log; worker churn has benign causes. |
| EDR process lineage | apache2/httpd/php-fpm/php-cgi/lsphp launching shells, interpreters, downloaders or nonstandard utilities. | Behavioral evidence of possible post-exploitation; tune against known application automation. |
| File / cloud / network | New executable PHP in webroot, modified application files, abnormal outbound traffic, access to tokens or secret stores. | Strongest when anchored to a specific server, request window and unexpected parent process. |

7.2 Example detection query — endpoint behavior
The following vendor-neutral logic is intended to be translated into your EDR/SIEM schema, not pasted unchanged into a specific product. It catches suspicious child execution by PHP/web server processes; it does not identify the vulnerable CVE with certainty. Elastic publishes comparable, tested detections for web-server-origin commands, downloaded payloads and unusual webroot writes.
parent_process_name IN ("apache2", "httpd", "php-fpm", "php-cgi", "lsphp")
AND child_process_name IN ("sh", "bash", "dash", "curl", "wget", "python", "perl", "nc", "socat")
AND NOT approved_application_execution_baseline
THEN correlate host + timestamp with HTTP POST + PHP error/worker activity7.3 Example triage commands
On systems under your administration, the following local commands help locate runtimes and review log evidence. Adjust service names and log locations for the distribution; they do not actively trigger PHP2Shell. CLI PHP version may differ from web-serving PHP.
php -v
command -v php-fpm8.4 && php-fpm8.4 -v
ps -eo pid,ppid,user,args | grep -E "[p]hp-fpm|[a]pache2|[h]ttpd|[l]sphp|[p]hp-cgi"
php -i | grep -E "Server API|Loaded Configuration File|Scan this dir"
# Replace paths with your distro and deployment log paths:
grep -Ei "Allowed memory size|Maximum execution time|PHP Fatal error" /var/log/php*/* 2>/dev/null8. Remediation: the control that closes both CVEs
8.1 Patch prioritization and verification
- Enumerate every PHP runtime in public web workloads, containers, images, VM services, control panels and embedded PHP products. Record SAPI, upstream branch, vendor package revision, container digest, service owner and exposure path.
- Install a PHP build containing the fixes: 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 or a vendor-confirmed backport. For unsupported branches, use a supported upstream release or a vendor-supported, documented patched build.
- Rebuild/redeploy images and restart all relevant web-server, FPM and long-lived worker processes. Verify the running binary and loaded modules, not only installed package metadata or
php -vfrom a separate CLI environment. - Verify package changelogs/security errata and regression-test uploads, sessions, authentication, applications and important PHP extensions. Retain an attested evidence record for closure.
# Debian/Ubuntu package-level confirmation (examples; names vary)
dpkg-query -W "php*" 2>/dev/null | head -50
apt-cache policy php8.4-fpm php8.4-cli
# RPM-based distributions: installed builds and applicable errata
rpm -qa | grep -E "^php|php-fpm|php-cli"
dnf updateinfo list --security 2>/dev/null | grep -i php8.2 Temporary exposure reduction — not complete fixes
- For CVE-2026-109618, the PHP advisory describes administratively enforcing
memory_limit=-1to remove a predictable per-request soft limit. This is an emergency trade-off, not a standard performance recommendation: underlying allocator failures remain possible and unconstrained memory demand increases host or container DoS risk. Resource isolation and monitoring are essential if used. - Apply conservative body-size, multipart-part, upload and header constraints at a front end that actually enforces decoded sizes. If a service never accepts multipart forms, block that media type after checking legitimate functionality. Never assume
post_max_sizealone prevents every described amplification. - For CVE-2026-109619, consider administratively disabling
session.upload_progress.enabledwhen unused; PHP 8.5 deployments can also disablefatal_error_backtraces. Restart workers after changes. Each control removes a known path, not all stale-state variants. - Remove obsolete/deprecated early PHP INI settings, investigate diagnostics and fatal errors around startup/shutdown, and review worker recycling.
pm.max_requests=1may reduce cross-request exposure for FPM but imposes performance cost and does not replace patching. - Enable relevant cloud-edge controls as defense in depth: AWS WAF's PHP application managed-rule-group v2.3 introduces PHP2Shell_BODY; Cloudflare published managed rules and response-aware protections. Confirm actual ruleset/version, action mode, request-body inspection limits and whether origin bypass is possible.
Do not rely on disabling display_errors, setting error_reporting=0, hiding the PHP version, updating only a CMS or rotating credentials while leaving the runtime vulnerable. In particular, PHP explains that diagnostics may access stale state even when the error is neither displayed nor logged.
9. Incident response: when telemetry indicates attempted exploitation
Prioritize hosts that combine vulnerable builds with exploit-like HTTP traffic, PHP fatal/OOM events, anomalous PHPSESSID responses and unexpected endpoint activity. Preserve source logs, response/header evidence under restricted access, package versions, process trees, container identifiers and potentially altered application files. Where operationally justified, isolate the host before an adversary can modify or destroy evidence. Avoid indiscriminate rebooting of a suspected compromised worker before deciding whether volatile memory collection is required and feasible.
If unauthorized code execution or access to memory contents is confirmed, treat web-worker permissions as the initial execution context — not automatically root. Determine which files, database accounts, instance roles, mounted Kubernetes service-account tokens and secrets that context could access; rotate exposed credentials in a controlled order; inspect for persistence (new web scripts, cron/systemd entries, SSH keys) and lateral movement. Rebuild compromised instances from trusted images after forensics and patch validation.

AWS published IP indicators associated with MadPot attempts, but explicitly cautions that some addresses are shared anonymization infrastructure. Use those indicators for context and correlation rather than indiscriminate permanent blocks. Network indicators are weaker and shorter-lived than runtime patch evidence and behavioral telemetry.
10. Authorized red-team and purple-team validation plan
The goal of a responsible assessment is to establish exposure and detection readiness without reproducing an internet-scale exploit. Scope tests to owned or explicitly authorized assets and isolate any deliberately vulnerable test runtime. Never send memory-exhaustion or UAF-triggering requests to production to "see if it crashes"; this can disrupt service or expose other users' memory.
- Inventory and classify: enumerate application routes, PHP versions, SAPI, session/upload settings, OPcache presence, frontend upload limits and worker/pool behavior through privileged access and configuration review.
- Build a reproducible lab: use pinned official or vendor container images for vulnerable and patched builds, identical resource limits, corresponding extensions and debug/sanitizer instrumentation as appropriate. Keep both control and test systems segregated from customer data.
- Use a non-exploit simulation to verify monitoring: create a clearly labeled controlled PHP worker child-process event and synthetic HTTP 500 / PHP error records; verify collection, correlation, alerting and escalation. Such simulation checks detections, not CVE exploitability.
- For deep internal code review, examine request-startup/shutdown state lifetimes and producer-consumer reset guarantees. Review PHP's published source patch and use AddressSanitizer / UndefinedBehaviorSanitizer harnesses under an agreed test plan; do not infer success from an isolated OOM or crash.
- Document results with confidence labels: "patched and verified," "potentially exposed," "laboratory-reproduced under specified conditions," or "compromise evidence identified." Obtain approval before any exploitation or memory-leak validation beyond passive checks.
For red teams, this issue demonstrates why validating PHP itself matters: a front-end WAF may see only an upload transaction while the actual primitive is a stale pointer in the runtime. For defenders, the practical exercise is to prove asset coverage, patch-state attestation, and behavioral alert fidelity without weaponizing public infrastructure.
11. CyberMon ASI: detecting externally exposed websites with vulnerable PHP
CyberMon ASI can identify externally exposed websites and applications that run vulnerable PHP versions, allowing defenders to see where PHP2Shell may affect their internet-facing attack surface. The assessment begins with attributable corporate domains, subdomains, web applications and public IP addresses. ASI correlates discovered assets with observable web-server and PHP technology fingerprints, disclosed runtime versions when available, and the affected-versus-fixed release matrix. Findings can be associated with business-critical applications, asset ownership, exposure context and remediation priority. This is visibility into potential vulnerability exposure — not evidence of an exploitation event.
For example, when external evidence indicates an internet-facing application uses a PHP release older than the published fixed version for its branch, CyberMon ASI can flag that site for urgent validation and remediation. Signals may include exposed HTTP technology headers, publicly visible error diagnostics and other non-invasive fingerprints. Conversely, missing PHP banners do not prove that PHP is absent, and apparent version numbers can be misleading when distribution maintainers backport security fixes. An ASI finding should therefore be confirmed against package revisions, SAPI configuration and the actual running process or container image before it is described as verified vulnerable.
12. Conclusion
PHP2Shell is not a generic "malicious code passes validation" defect. It is a pair of native PHP memory-safety vulnerability classes whose exploitability depends on when request-owned objects are created, whether fatal errors interrupt their lifecycle, and which early consumers touch them later. The combination of proven unauthenticated RCE, potential memory disclosure and PHP's widespread deployment makes the risk acute — but the evidence does not justify fabricated infection statistics or treating all PHP server configurations as identical.
The right response is rigorous and measurable: patch and attest the running PHP runtime, investigate telemetry dating to at least 17 October 2026 where available, correlate HTTP/runtime/endpoint signals, and treat WAF and configuration changes only as transitional risk reduction. For authorized offensive teams, the most valuable contribution is controlled validation and defensive readiness testing; for blue teams, it is fast asset identification and proof that the vulnerable code is no longer running. CyberMon ASI supports this process by detecting externally exposed websites with vulnerable PHP version indicators, surfacing potentially affected assets for triage and helping teams track the remediation of internet-facing PHP exposure.

Sources and technical references
- PHP project — 21 Oct 2026 security release and vendor update guidance
- PHP project advisory — CVE-2026-109618 / GHSA-w8hw-w9fx-j79w
- PHP project advisory — CVE-2026-109619 / GHSA-6wmf-4rv5-p3rp
- Wiz Research — PHP2Shell technical analysis and four demonstrated primitives
- PHP Foundation — Today's PHP Security Release and how it was fixed
- Amazon Threat Intelligence — PHP2Shell exploitation attempts in MadPot
- Red Hat — PHP2Shell security bulletin and vendor package status
- Cloudflare — PHP2Shell managed WAF protections and observed traffic
- Elastic Security Labs — Detection coverage for PHP2Shell-related behavior
- AWS Security — AWS WAF mitigations and rule group version 2.3
- NCSC-NL — operational intelligence repository
