PHP2Shell: Two Critical RCE Zero-Days Hit Every PHP Version, Patch Now
Reach 50,000+ security professionals
Sponsor a newsletter slot and put your brand in front of CISOs, engineers, and IT decision-makers.
Two critical remote code execution vulnerabilities in PHP were confirmed under active exploitation on October 21, 2026, as patches shipped. CVE-2026-109618 and CVE-2026-109619, both CVSS 9.2, allow unauthenticated attackers to execute arbitrary code as the web worker account on Apache mod_php and PHP-FPM deployments. All PHP 8.x releases prior to today's patches are affected; the vulnerable code paths are also present in EOL 5.x and 7.x.
Discovered by Wiz Research (Sagi Tzadik, Shir Tamari, Nir Ohfeld, and Tomer Schwartz), OpenAI Codex Security (Amy Burnett), and independent researcher Ryan A. from Calif, coordinated disclosure included Google, AWS, Microsoft, Cloudflare, Akamai, Imperva, and Automattic. The PHP security team moved the release forward after details leaked early. Cloudflare confirmed exploitation was active before patches shipped.
Researchers also confirmed application-agnostic memory disclosure: an attacker can read PHP process memory -- passwords, auth tokens, API keys, TLS certificates -- without RCE. Credential theft is viable even where sandboxing blocks code execution.
CVE-2026-109618 exploits PHP's longjmp() for out-of-memory handling: crafted multipart requests exhaust memory during startup, leaving request memory in an invalid state that mod_php's unconditional shutdown then processes. CVE-2026-109619 is a use-after-free via stale worker global state: a fatal error can abort the state-reset operation, leaving freed request memory reachable to the next request.
Configuration mitigations circulated before the patch are incomplete. The only fix is updating to PHP 8.2.35, 8.3.36, 8.4.27, or 8.5.12. All web-serving SAPIs are at risk: mod_php, PHP-FPM, php-cgi, FrankenPHP, and LiteSpeed. EOL users on 7.4, 8.0, or 8.1 should check their Linux distribution or LTS vendor for source-backports.
CVE-2026-109618: RCE via OOM Memory Corruption
PHP uses longjmp() to abort execution on OOM. In certain contexts -- particularly during multipart body parsing -- an OOM leaves request memory partially initialized; the longjmp() path doesn't account for the early exit, leaving that invalid state live.
Three multipart parsing properties let an attacker exhaust memory while staying within PHP's apparent limits: absent content-length bypasses post_max_size; part headers have no count limit and consume more memory than their wire size; empty file controls still allocate full metadata arrays and nested field names multiply allocation work.
The mod_php attack path requires no application code. mod_php calls request shutdown unconditionally, even when startup fails. A crafted multipart request exhausts memory during startup, PHP longjmps out with invalid state live, and mod_php's shutdown processes that state -- RCE. The PHP team validated complete unauthenticated RCE at default limits against a standard prefork configuration.
PHP-FPM avoids the application-independent path (FPM terminates a child on startup failure), but OOM can occur in application code paths after successful startup, making FPM susceptible via application-specific triggers. FrankenPHP, which also calls shutdown unconditionally, is assessed susceptible to the application-independent path.
The patch replaces longjmp() for OOM with a delayed soft OOM at the next VM safe point and an immediate hard OOM (_exit()) at a second higher threshold -- request shutdown will no longer see invalid state.
CVE-2026-109619: RCE via Stale Worker Global State
PHP workers handle multiple requests and retain global state between them: error state, session state, object handles, extension state. That state must be reset before the request heap is freed. CVE-2026-109619 is a class of use-after-free vulnerabilities where that reset fails.
The lifecycle: a producer operation stores request-owned state in a global location. A fatal error -- including OOM -- abandons the operation before the matching reset. PHP frees the request heap. The same worker handles the next request. A consumer reads the stale pointer into freed memory. Heap layout manipulation converts the UAF to RCE.
Two paths were confirmed. First: PHP 8.5's fatal_error_backtraces feature stores backtrace data in a global field that is never reset on shutdown. A diagnostic during the next request's init reads the stale pointer -- application-independent RCE on PHP 8.5. Second: session upload progress initializes request-owned session and decoder state before normal session init; an OOM or fatal error prevents the matching reset; a later upload on the same worker consumes the freed state. Validated on both mod_php and FPM.
The full patch resets all identified state families, not just the two confirmed paths.
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
Patch Versions and Immediate Actions
PHP released patched versions on October 21, 2026 at 14:00 UTC. PHP 5.x and 7.x are end-of-life and will not receive patches.
| PHP Branch | Status | Fixed Version | Action |
|---|---|---|---|
| 8.5 | Active support | 8.5.12 | Update now |
| 8.4 | Active support | 8.4.27 | Update now |
| 8.3 | Security fixes only | 8.3.36 | Update now |
| 8.2 | Security fixes only (EOL Dec 2026) | 8.2.35 | Update now |
| 8.1 | End of life | Source backport only | Rebuild or upgrade |
| 8.0 | End of life | Source backport only | Rebuild or upgrade |
| 7.4 | End of life | Source backport only | Rebuild or upgrade |
| 5.x / older 7.x | End of life | No backport | Upgrade or isolate |
Updating is the only complete mitigation. Three partial steps reduce risk while a patch window is prepared -- apply them together and restart all PHP workers:
memory_limit=-1 removes the predictable PHP-level memory ceiling the confirmed mod_php OOM path relies on. It does not prevent allocator-level OOM from triggering the same longjmp() path but is the highest-value interim step for mod_php deployments.
session.upload_progress.enabled=0 removes the session lifecycle producer and consumer paths for CVE-2026-109619. It does not cover other state families or the fatal backtrace path.
fatal_error_backtraces=0 (PHP 8.5 only) removes the confirmed backtrace producer for CVE-2026-109619.
After patching, harden the remaining configuration: review post_max_size and max_input_nesting_level, set expose_php=0, and revert any temporary memory_limit=-1. Then check for compromise back to at least June 2026 -- look for files written to web-accessible directories by the web server account, modified .htaccess files, unauthorized accounts, unexpected outbound connections from the web server process, and PHP files with recent timestamps.
Detecting PHP2Shell Exploitation
No network IOCs exist for PHP2Shell: there is no attacker infrastructure to block. Detection focuses on post-exploitation behavior after RCE is achieved and on the HTTP request patterns that trigger the OOM and stale state conditions. Three log sources cover the critical detection surface: Linux process creation events (auditd or EDR), Linux file events (auditd or EDR), and web proxy/access logs.
What to look for in process events: any shell or script interpreter launched by a web server daemon process. Legitimate web applications do not spawn bash, sh, dash, python, netcat, wget, or curl as children of httpd, apache2, php-fpm, or php. A single hit on this pattern is a high-confidence indicator of successful RCE.
What to look for in file events: the web server account (www-data, apache, nginx) writing a PHP file to any web-accessible directory. Legitimate content management deployments write uploads to configured upload directories; spontaneous writes to web root or outside configured paths indicate webshell deployment.
What to look for in proxy logs: POST requests to PHP endpoints with multipart/form-data content type and abnormally large body size or high header count. CVE-2026-109618 exploits excessive per-part header memory expansion; hunting for outlier multipart request sizes in proxy logs catches probing activity before successful exploitation.
Subscribe to unlock Indicators of Compromise
Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.
Subscribe to unlock Sigma Detection Rules
Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.
Subscribe to unlock WAF Detection Rules
Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.
Remediation Steps
Update PHP immediately. PHP 8.2.35, 8.3.36, 8.4.27, and 8.5.12 contain the complete fix. PHP 5.x and 7.x are end-of-life and will not be patched. If you cannot update immediately, apply the interim configuration mitigations below in combination -- none individually constitutes a complete fix.
Subscribe to unlock Remediation & Mitigation steps
Free subscribers unlock full IOC lists, Sigma detection rules, remediation steps, and every daily briefing.
The bottom line
CVE-2026-109618 and CVE-2026-109619 are unauthenticated RCE vulnerabilities in PHP itself, confirmed exploited in the wild before the patch shipped. Apache mod_php deployments require zero application code to be exploited. Configuration workarounds that circulated before the patch do not fully protect against either CVE. Update to PHP 8.2.35, 8.3.36, 8.4.27, or 8.5.12 now, apply the three partial mitigations as an interim step if patching will be delayed, and hunt for compromise going back to June 2026.
This analysis is generic. create a free account to score threats like this against your own stack.
Frequently asked questions
What is PHP2Shell?
PHP2Shell is the name researchers at Aikido Security gave to two critical remote code execution vulnerabilities in PHP itself: CVE-2026-109618 and CVE-2026-109619. Both have a CVSS v4 score of 9.2. CVE-2026-109618 exploits PHP's use of longjmp() for out-of-memory errors, leaving request memory in an invalid state that gets processed during shutdown and can produce RCE. CVE-2026-109619 exploits worker global state surviving across PHP requests, where a producer operation stores request-owned state in a globally accessible location and a consumer in the next request reads that freed memory. Together, they give unauthenticated attackers remote code execution as the web worker account on Apache mod_php and PHP-FPM deployments. Patches shipped October 21, 2026.
Which PHP versions are affected?
The patched versions are PHP 8.2.35, 8.3.36, 8.4.27, and 8.5.12, so all earlier 8.x releases are affected. PHP 5.x and 7.x are end-of-life and will not receive patches; Aikido's research indicates the vulnerable code paths exist in those branches as well. Any production system running PHP 8.2 through 8.4 prior to the patched releases, or PHP 8.5 before 8.5.12, should be treated as exploitable. PHP 5.x and 7.x servers should be treated as unpatched indefinitely and should be upgraded or isolated.
Does CVE-2026-109618 require any application code to be vulnerable?
No, not on Apache mod_php. CVE-2026-109618 exploits the fact that Apache mod_php calls the PHP request shutdown procedure unconditionally, even when request startup fails. An attacker sends a crafted multipart request that exhausts the PHP memory limit during startup body parsing, leaving PHP in an invalid intermediate state. Shutdown processes that invalid state without any application code executing. This means every PHP application hosted under Apache mod_php is vulnerable regardless of what the application itself does, as long as it runs an unpatched PHP version.
Is PHP-FPM also vulnerable?
Yes, but with different characteristics. PHP-FPM terminates a worker child when request startup fails, which prevents the application-independent mod_php attack path. However, CVE-2026-109618 can still be reached via OOM in application-specific code paths after normal startup. For CVE-2026-109619, FPM exploitation was validated via the session upload progress path: a request publishes session state, reaches a fatal error during application execution, and a subsequent request on the same worker consumes the freed state. RCE via this path was confirmed against a standard dynamic FPM pool. Both vulnerabilities should be treated as exploitable under FPM.
Do the configuration workarounds actually protect against PHP2Shell?
No. Setting memory_limit=-1 removes the predictable per-request PHP memory ceiling that the confirmed mod_php exploit path relies on, but it does not prevent OOM from underlying allocator failures, and it does not address CVE-2026-109619 at all. Setting session.upload_progress.enabled=0 removes one confirmed consumer path for CVE-2026-109619, but does not protect against all producer-consumer combinations. Setting fatal_error_backtraces=0 (PHP 8.5 only) removes the confirmed fatal backtrace producer for CVE-2026-109619, but other state families remain exploitable depending on application code paths. The PHP security team confirmed that no configuration change constitutes a complete mitigation. Updating is the only complete fix.
How do I detect if a server was compromised via PHP2Shell?
Aikido recommends checking for compromise going back to at least June 2026, when details began circulating before the planned disclosure. Look for new files written to web-accessible directories by the web server user account (www-data, apache, nginx), especially PHP, shell script, or binary files. Check for new or modified .htaccess files. Review PHP error and access logs for OOM errors, fatal errors, and unusual multipart POST requests with large numbers of headers or nested field names. Look for unexpected outbound connections from the web server process to external IPs. Review administrative user accounts and configuration files for unauthorized changes.
What is the right patch priority compared to other recent PHP CVEs?
PHP2Shell should be treated as the highest priority PHP security update in recent history. Both CVEs have CVSS 9.2, require no authentication, require no user interaction, and attack vectors are network-accessible. Active exploitation was confirmed by Cloudflare before the patch was released. The only comparable scope in PHP's history is CVE-2019-11043 (PHP-FPM RCE, CVSS 9.8). Any patching queue that has PHP below other items should be revised immediately.
Sources & references
- GitHub Advisory GHSA-w8hw-w9fx-j79w: RCE via OOM corruption (CVE-2026-109618)
- GitHub Advisory GHSA-6wmf-4rv5-p3rp: RCE via stale global state (CVE-2026-109619)
- PHP2Shell Official Research Site (Wiz Research, OpenAI Codex Security, Calif)
- Aikido Security: Critical vulnerabilities in PHP (PHP2Shell)
- PHP 8 ChangeLog: Version 8.5.12 (October 22, 2026)
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Daily briefings + Google Top Stories in one step.
Enter your email and we'll subscribe you to the daily briefing and add Decryption Digest to your Google Search feed at the same time.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.
