All Blogs
PHP2Shell (CVE-2026-109618 and CVE-2026-109619): How the Unauthenticated PHP RCE Works and How to Fix It

Quick Overview: PHP2Shell is the name for CVE-2026-109618 and CVE-2026-109619, two critical flaws in the PHP runtime that can give an unauthenticated attacker code execution on any server running PHP for the web. PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix both. Patch now.
PHP2Shell is the name for CVE-2026-109618 and CVE-2026-109619, two critical flaws in the PHP runtime that can give an unauthenticated attacker code execution on any server running PHP for the web. PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 fix both. Patch now.
Most PHP compromises start with a bug in the application: a vulnerable plugin, an unsafe upload handler, a forgotten admin route. PHP2Shell skips that step. The flaws live in the PHP runtime itself, so an attacker does not need a weakness in your code, a login, or even a valid route. On Apache with mod_php, the PHP security advisory describes a demonstrated exploit where a single unauthenticated request triggers the attack before any application code runs.
The timing makes it worse. Details leaked before the coordinated release. Cloudflare saw attack traffic aimed at its customers, and Amazon's honeypots recorded an exploitation attempt four days before the CVEs were public. Defenders started this race from behind.
This guide breaks down how the two bugs work, which deployments carry the most risk, what each stopgap actually blocks, and how to prove the fix is running rather than merely installed.
On This Page
- What is PHP2Shell?
- How PHP2Shell Works
- Which PHP Deployments Are at Risk?
- Fixed Versions and How to Patch
- Temporary Mitigations If You Cannot Patch Yet
- How to Verify the Fix and Check for Compromise
- How ZeroThreat Detects and Helps Remediate PHP2Shell
- Key Takeaways
- Conclusion
What is PHP2Shell?
PHP2Shell is the collective name for CVE-2026-109618 and CVE-2026-109619, two memory-safety flaws in the PHP runtime that can let an unauthenticated attacker execute code on a server through ordinary HTTP requests. The PHP security team rates both at 9.2 on CVSS v4.0.
Calif.io, Wiz, OpenAI and Quarkslab disclosed the bugs. Because they sit in PHP's core request handling rather than in a framework or extension, every application built on top inherits the exposure, from WordPress and Laravel to Magento and custom code.
| Date (2026) | Event |
|---|---|
| Oct 17 | Amazon's MadPot honeypot network records a PHP2Shell exploitation attempt |
| Oct 20 | PHP announces an emergency security release after details leak |
| Oct 21 | Cloudflare deploys WAF rules roughly nine hours ahead of public disclosure |
| Oct 21, 14:00 UTC | PHP ships 8.5.12, 8.4.27, 8.3.36 and 8.2.35; CISA issues an alert urging immediate patching |
How PHP2Shell Works
PHP2Shell works by getting PHP to trust internal request state that is not what PHP believes it is: half-built data in one flaw, already-freed data in the other. Both routes end in memory corruption that researchers turned into remote code execution, and a related technique leaks worker memory without any login.
CVE-2026-109618: Out-of-Memory Corruption
When PHP runs out of memory partway through handling a request, it can be interrupted while internal request data is only partly initialized (GHSA-w8hw-w9fx-j79w). The cleanup code that runs afterwards treats that half-built data as valid, which hands an attacker a corrupted structure to work with.
From the attacker's side, the important detail is control over where the failure lands. PHP's memory limit is a fixed, configured ceiling, and request parsing allocates memory in proportion to what the client sends. Large bodies, many input variables, deep nesting and multipart uploads all drive allocation during parsing, before your application sees anything. That is why PHP's interim guidance targets post_max_size, input nesting and multipart limits.
CVE-2026-109619: Stale Global State
Here, request-owned internal state can outlive the memory backing it (GHSA-6wmf-4rv5-p3rp). A later request served by the same worker can touch that freed memory before PHP's normal initialization resets it: a use-after-free that spans two requests.
This is a persistent-worker problem. mod_php and PHP-FPM reuse the same process for many requests, so an attacker can send one request to leave dangling state behind and a follow-up that lands on the same worker to use it. PHP has confirmed reachable paths through session upload-progress handling, fatal-error backtraces on PHP 8.5, diagnostics emitted before initialization, and attacker-triggerable fatal errors and timeouts.
Leaking Worker Memory Without Logging In
Researchers also demonstrated unauthenticated disclosure of PHP worker memory. A worker's heap can hold database passwords, session tokens and API keys from earlier requests. An attempt that never reaches code execution can still be a data breach, which changes how you scope incident response for any server that was exposed before patching.
Which PHP Deployments Are at Risk?
PHP2Shell affects every PHP installation that serves web requests, regardless of application or framework, and Apache mod_php carries the highest risk. The difference between deployments comes down to how PHP is attached to the web server and how long its workers live.
| Deployment | Exposure | Why |
|---|---|---|
| Apache mod_php | Highest | Demonstrated unauthenticated exploit that fires before any application code runs |
| PHP-FPM | Affected | Startup behavior blocks one out-of-memory path, but PHP validated RCE through the session lifecycle under suitable application conditions |
| php-cgi | Affected | Named by PHP as an at-risk installation type |
| FrankenPHP | Affected | Named by PHP as an at-risk installation type |
| LiteSpeed | Affected | Named by PHP as an at-risk installation type |
The version range is wide. Cloudflare describes the flaws as affecting web servers running PHP 5.4 or later, yet only branches 8.2 through 8.5 receive official fixed releases. Long-lived estates on PHP 7.x and 8.0 are therefore exposed with no packaged upstream fix.
PHP also notes that exploitability varies with configuration and application behavior. That cuts both ways: a server that looks protected on paper may still be reachable through a path nobody listed, so exposure is something to test from the outside, not assume.
Fixed Versions and How to Patch
The only complete fix for PHP2Shell is a PHP build that includes the October 21, 2026 patches: 8.5.12, 8.4.27, 8.3.36, 8.2.35, or a vendor package with the fixes backported.
| PHP branch | Fixed release | |
|---|---|---|
| 8.5 | 8.5.12 | |
| 8.4 | 8.4.27 | |
| 8.3 | 8.3.36 | |
| 8.2 | 8.2.35 | Reaches end of life on December 31, 2026; plan the next upgrade now |
| 8.1, 8.0, 7.4 | No official release | Minimal source backports from the PHP security team; otherwise use an LTS vendor or upgrade |
| Older | None | Upgrade to a supported branch |
Three traps catch teams during rollout:
- Backported version strings. Distribution packages often carry the fix under an older upstream version number. Check the full package version against your vendor's advisory, not against the table above.
- Third-party repositories. PHP warned that the volunteer-run rpms.remirepo.net would not have updates on release day and urged users to switch to distribution packages or build from source.
- Windows. Fixed Windows source and binaries are published on the php.net downloads page alongside the source releases.
Temporary Mitigations If You Cannot Patch Yet
No configuration change makes an unpatched PHP installation safe; each of PHP's stopgaps closes a specific attack path and leaves others open. Apply them only to buy time, and apply them at the server or pool level, because ini_set() and FPM .user.ini files take effect too late to protect request parsing.
| Stopgap | What it blocks | What it leaves open |
|---|---|---|
| memory_limit=-1 via php_admin_value | Attacker-controlled failures at PHP's configured memory ceiling (CVE-2026-109618) | Genuine allocation failures still reach the bug; removing the cap invites resource exhaustion |
| post_max_size of 8M (32M if uploads are needed), upload_max_filesize below it | Shrinks how much allocation a request can force | Not a block, only a smaller lever |
| Proxy or web-server limits on decoded size, field count, multipart parts, headers and nesting | Parsing pressure before PHP sees the request | Must also cover requests without a usable Content-Length; block multipart entirely if unused |
| Container or cgroup memory limits that kill only the affected worker | Availability impact | Do not use RLIMIT_AS or RLIMIT_DATA, which can trigger the vulnerable failure |
| session.upload_progress.enabled=0 | Confirmed session paths (CVE-2026-109619) | Other stale-state variants |
| fatal_error_backtraces=0 on PHP 8.5 | Confirmed fatal-backtrace path | Only that path |
| Remove invalid per-request settings; fix attacker-triggerable fatal errors and timeouts | Diagnostic and error paths that touch stale state | Hiding errors with @ or display_errors does nothing |
| pm.max_requests=1 on PHP-FPM | Reuse of a worker across requests | Significant performance cost |
Restart every worker after each change and confirm that no pool, directory or application setting quietly restores the old value.
A WAF is a useful layer here, not a substitute. Cloudflare shipped managed rules before disclosure and then watched attackers mutate payloads to slip past them. If a patched build cannot go out promptly, restrict public access to the service or isolate it, and give each waiting system an owner and a deadline.
How to Verify the Fix and Check for Compromise
A PHP2Shell fix is complete only when every process serving web traffic runs a patched build, which means checking the running runtime rather than the package manager.
- Find every PHP install. Include parallel branches, container images, hosting-panel bundles and PHP shipped inside appliances. The version that php -v reports belongs to the CLI binary, which may not be the module or FPM pool serving requests.
- Update the right artifact. For containers, a patched base image changes nothing until the application image is rebuilt and redeployed.
- Restart or replace workers. Long-lived workers keep running the old build until they are recycled. Confirm that none are left.
- Roll back emergency settings. Once the patched runtime is confirmed, restore a finite memory_limit and revisit temporary upload limits and worker recycling.
- Assume an exposure window. For internet-facing servers unpatched since mid-October, rotate secrets that live in PHP worker memory, such as database credentials, API keys and session signing keys, and hunt for web shells and PHP or web-server workers spawning shell processes. No public indicators of compromise had been released at the time of writing.
Finally, retest from the outside. A server is fixed when an attacker-position test can no longer reach the flaw, not when a ticket says the package was updated.
How ZeroThreat Detects and Helps Remediate PHP2Shell
ZeroThreat detects PHP2Shell exposure with a dedicated check for CVE-2026-109618 and CVE-2026-109619, run from an attacker's position against your internet-facing web apps and APIs, then pairs every finding with remediation guidance and a retest to confirm the fix held. It answers the question patch tickets cannot: which of your live applications can an attacker still reach through PHP2Shell right now?
Find Every Exposed PHP Application
PHP2Shell is dangerous because it hides in the runtime, and runtimes hide in places inventories miss: a legacy marketing site, a staging host left online a container nobody rebuilt. ZeroThreat maps your external attack surface, from exposed ports, SSL/TLS and DNS through to applications, APIs and authenticated areas, then runs the PHP2Shell check against what it finds. The result is a list of the applications that are actually exposed, not a list of servers that have PHP installed.
ZeroThreat Remediation Guidance for CVE-2026-109618 and CVE-2026-109619
Each PHP2Shell finding ships with the evidence behind it, including the raw request and response, plus step-by-step remediation and an effort estimate. Reports are split by audience, so each team gets what it needs to act without a translation step:
| Team | What the PHP2Shell finding gives them |
|---|---|
| Security teams | The affected asset, its exposure, why it was prioritized and its business impact |
| Application and platform teams | The endpoint, request and response evidence, remediation steps and effort estimate |
Because the fix for PHP2Shell is a runtime upgrade, the guidance points teams at the patched build and the deployment details that decide whether it takes effect, rather than at application code.
Prioritize by Business Impact, Not Just a 9.2 Score
Every PHP app in your estate shares the same CVSS score, but not the same risk. ZeroThreat ranks findings by what the application protects and how reachable it is, and sorts them into fix windows: Fix immediately, within 7 days, within 30 days and within 90 days. An internet-facing PHP application that handles logins or payments goes to the top of the list, so your first restart is the one that matters most.
Confirm the Fix With a One-Click Retest
Installing a patched package does not prove the running workers picked it up. After you upgrade and restart, a one-click retest runs the PHP2Shell check again from the outside. If a stale worker, an unrebuilt container image or a forgotten parallel install is still serving traffic, the finding stays open. When it closes, you have evidence that the vulnerable runtime is gone, which is also the record auditors and customers will ask for.
ZeroThreat POV
The PHP2Shell bugs sat in PHP's core for decades. Wiz's researchers said turning them into a working exploit required a chain of steps at the edge of what humans could manage by hand, and frontier AI models closed that gap. Attackers have the same models. When old runtime flaws can become exploits in days, testing has to move at the same pace, which is the case for continuous zero-day vulnerability detection rather than an annual pentest.

Key Takeaways
- PHP2Shell is two runtime flaws, so no application or framework update fixes it.
- Apache mod_php is the top priority: the demonstrated exploit runs before any application code.
- Patch to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or a vendor package with the fixes backported.
- Stopgaps and WAF rules each block specific paths, and attackers are already mutating payloads around them.
- Verify the running worker, rotate secrets held in worker memory, and retest from outside.
Find Out Which PHP Apps Are Still Exposed.
Run ZeroThreat's PHP2Shell check from an attacker's position and confirm every fix held. Start AI Pentesting Free
Conclusion
PHP2Shell is a runtime problem, so the fix is a runtime upgrade. The hard part is proving that every internet-facing PHP process actually picked it up, across branches, containers and forgotten hosts, while attackers are already testing the same servers.
ZeroThreat closes that gap from the outside. Its PHP2Shell check shows which web apps and APIs are still exposed, and application-aware AI pentesting ranks them by business impact. A retest then confirms each fix held, instead of leaving you to trust a package version. Sign up and check your PHP estate today.
Frequently Asked Questions
Why is it called PHP2Shell?
PHP2Shell is the nickname researchers gave CVE-2026-109618 and CVE-2026-109619. It describes the outcome: a crafted HTTP request to a PHP server can end in a shell, meaning arbitrary code running with the privileges of the PHP worker process.
Is PHP2Shell in the CISA KEV catalog?
Are WordPress, Laravel, and Drupal sites affected by PHP2Shell?
Does hiding the PHP version protect against PHP2Shell?
What can I do about PHP2Shell on shared hosting?
Does the PHP CLI need to be updated for PHP2Shell?
Can the patched PHP version change how my application behaves?
How do I tell which PHP handler my server uses?
Explore ZeroThreat
Automate security testing, save time, and avoid the pitfalls of manual work with ZeroThreat.


