- What PHP2Shell is
- How the two bugs work
- How it was found, and the leak
- How to patch and protect your servers
Bonus: watch it in 3D
This is part 4 of the PHP2Shell series, and the one to read if you run or look after anything built on PHP. It covers how to find out whether you are exposed, how to patch, what to do if you cannot patch today, how to look for signs of attack, and what to do afterwards. Background is in part 1 and part 2.
Step 1: find out whether you are exposed
CISA's alert recommends taking inventory of every system running any PHP version, including PHP embedded in other software, and patching internet-facing systems first. Qualys adds practical traps:
php -von the command line may report a different PHP from the one serving your website. Check the PHP your web server actually uses (for examplephp-fpm -v, or the Apache module).- PHP can be bundled inside containers, appliances and apps. Rebuild container images and restart workers that still run the old runtime (Datadog).
- Linux distributions often backport a fix without changing the version number. To confirm, search the package changelog for the CVE ID. Sansec suggests
zgrepon Debian and Ubuntu, and on RHEL-family systemsrpm -q --changelog php-common | grep CVE-2026-109618. - If a host manages PHP for you (shared hosting, managed WordPress), ask them to confirm in writing which fix they applied.
| Your situation | What to do |
|---|---|
| PHP 8.2 to 8.5, below the fixed version | Update to the fixed version, or your vendor's patched build. |
| PHP 7.4, 8.0 or 8.1 | No regular upstream fix. PHP provided limited source backports. Use a vendor or distribution build that carries the fix, apply the backport, or upgrade to a supported branch. CISA says systems on PHP 8.1 or earlier that cannot be updated should be taken offline. |
| PHP 7.3 or older | End of life with no fix from the PHP project. Plan an upgrade, and in the meantime isolate the system. |
| Managed hosting or SaaS | Ask the provider. You cannot patch PHP from inside WordPress or a plugin. |
| Containers | Rebuild from a patched base image and redeploy. Updating packages inside a running container is not the same thing. |
Step 2: patch
| Branch | Fixed version |
|---|---|
| PHP 8.5 | 8.5.12 |
| PHP 8.4 | 8.4.27 |
| PHP 8.3 | 8.3.36 |
| PHP 8.2 | 8.2.35 |
After updating, restart every PHP worker (PHP-FPM, Apache, the lot). A patched binary on disk does nothing for workers still running the old one. On release dates, CISA and Qualys describe the releases as shipping on 21 October, while the php.net changelog lists 8.5.12 and 8.4.27 under 22 October, so match your records against the version number rather than the date.
Two later notes from php.net. On 26 October the project published updated Windows builds (8.5.12-1, 8.4.27-1, 8.3.36-1 and 8.2.35-1) that bundle a newer Brotli library for an unrelated vulnerability; the PHP versions themselves are unchanged. And the 8.2 branch reaches end of life on 31 December 2026, so a move to 8.3 or later is worth planning now.
Step 3: if you truly cannot patch today
Here is where much of the early advice online went wrong. The two bugs need different stopgaps, and a setting that helps one does nothing for the other. PHP's own security team made the same correction about the most repeated tip (Alexandre Daubois, PHP security team). The advisories say what applies to which:
| Bug | Partial measures from PHP's advisory |
|---|---|
| CVE-2026-109618 (out-of-memory) | Set and enforce memory_limit=-1 administratively, restart all workers, and confirm no pool, directory or app setting restores a finite limit. Keep post_max_size conservative and enforce decoded request size at the frontend. Lower max_input_nesting_level, and bound input variables, multipart parts, headers per part and uploads. If you do not use multipart form data, block it at the frontend. |
| CVE-2026-109619 (stale state) | Set session.upload_progress.enabled=0 and restart workers. On PHP 8.5, also set fatal_error_backtraces=0. Where performance allows, pm.max_requests=1. Remove startup diagnostics and obsolete settings, and prefer startup configuration to per-request overrides. |
Warnings that matter:
memory_limit=-1is not complete: the advisory says a failedmmap()can still reach the vulnerable path. It also removes your per-request cap, so one request can use all server memory. Sansec says to monitor memory and restore the limit after patching.- Do not use
RLIMIT_ASorRLIMIT_DATAas a substitute: they makemmap()fail and trigger the vulnerable path. A container or cgroupmemory.maxis an availability boundary, not a protection. - Blocking
multipart/form-dataat the web server (Sansec provides nginx and Apache snippets) breaks file uploads. Test checkout and forms afterwards. - The advisory for 109619 says: there is no complete generic configuration mitigation. Do not treat these settings as "patched."
What about a firewall?
Cloudflare deployed firewall rules on 21 October at 03:02 UTC, before the public release. They are available on all plans including Free (on paid plans, confirm the PHP2Shell rules are in block mode), and Cloudflare adds a response rule that can block matching responses from your origin. Cloudflare itself calls this a stopgap that only covers traffic routed through it, and says attackers were already modifying payloads. Sansec notes that its own application firewall does not cover this, because the exploit runs inside PHP before application code. Keep any firewall protection on during and after patching, and still patch. If you cannot patch at all, CERT-EU recommends isolating internet-facing applications until a fix is applied and verified.
Step 4: look for signs of attack
Datadog recommends correlating these, because none is conclusive alone:
- Requests: unusually long form field names, or unexpected control bytes in form submissions. Check that your firewall actually inspects large bodies and does not truncate them.
- PHP error log: memory-exhaustion errors marked
Unknown on line 0, which means failure during request setup, before any script ran. Legitimate load can cause these too. - Web server log: Apache worker segmentation faults (signal 11), which can follow a failed attempt.
- Processes: a web worker starting a shell, especially with outbound connections to an unfamiliar host. A successful attack may not crash the worker or change the HTTP response.
A related issue the 21 October releases do not fix
On 23 October the PHP project published an informational advisory about a separate session upload-progress issue, CVE-2026-115560. It describes an unlikely remote code execution route that needs an unusual setup: the session serialize handler set to php_binary or php_serialize in configuration, switched to php at runtime with ini_set() before session_start(), with upload progress still enabled. PHP says it will fix it in the regular release cycle and publish a full advisory with the next release. Until then it suggests setting session.upload_progress.enabled=0, the same setting already listed above for CVE-2026-109619. Set it in the server configuration, because the main advisory says it does not work if applied with ini_set() or .user.ini.
Step 5: after patching
- Restart workers and redeploy containers so nothing keeps running the old runtime.
- Keep
session.upload_progress.enabled=0if you do not need the feature. The advisory recommends this even after patching, and PHP's 23 October note suggests it until the next regular release. - Treat secrets on exposed servers as possibly read. Researchers showed worker memory can leak passwords, tokens, API keys and TLS private keys. That is our recommendation, not a step the sources prescribe: if an unpatched server was internet-facing, rotate database passwords, API keys (including model provider keys), session secrets and certificates, starting with the most privileged.
- Cap blast radius for next time. Scope AI provider keys to one purpose and set spend limits, so a leaked key has a ceiling.
- Plan the upgrade off end-of-life PHP. Datadog notes the fix does not remove the underlying pattern, so similar bugs may appear, and older branches will not get fixes.
Is it being exploited?
Sources differ, and the picture changed through 21 and 22 October. Here is who said what:
| Source | What it reported |
|---|---|
| Amazon Threat Intelligence | A honeypot attempt on 17 October, and more on 21 October with payloads suggesting multiple actors. Unclear whether they would work on real systems. |
| Cloudflare | Attack traffic against its customers, with attackers modifying payloads to evade rules. |
| watchTowr | Active exploitation attempts against both CVEs from 14:19 UTC on 21 October. |
| CISA | Had not observed exploitation when it published on 21 October, and neither CVE was in its Known Exploited Vulnerabilities (KEV) catalog as of 22 October. On 26 October it added both CVEs to KEV (due date for US federal agencies: 29 October) and updated its alert to say so. |
| Wiz (27 October) | Saw a limited number of exploitation attempts and none that succeeded end to end in its own data. It had found no public proof of concept that works in general against an arbitrary target, though it says some partners privately hold exploits that work on various targets. Wiz points to a public honeypot report of confirmed code execution on a single-worker Apache mod_php setup as the strongest public evidence, and says the scanning that followed was a likely factor in the KEV listing. |
| Sansec | Says mass exploitation looks less likely than first feared and that public proof-of-concept code it was told about did not work on a default install. It does not say it saw attacks itself. |
No source we read confirmed a successful break-in of a specific server. Some organizations, including BambooHR and several Dutch government and education sites, went offline as a precaution (The Hacker News). Our advice: assume scanning is under way, and do not rely on "the public exploits are unreliable." Attackers only need reliability on the common setups.
If you are building or running an AI product
AI products sit on PHP more often than their diagrams admit: a WordPress marketing site with a chat widget, a Laravel back office that calls a model API, a legacy admin panel in front of a new retrieval service. The risk that matters most there is worker memory, because the model keys, vector database credentials and tokens those integrations use can sit in it. Patch first, then rotate and scope the keys. Our AI agent security checklist and security review guide cover the application side, and part 3 explains why the time you have to react keeps shrinking.
Sources: PHP advisory for CVE-2026-109618, PHP advisory for CVE-2026-109619, CISA alert, Qualys write-up, Alexandre Daubois, PHP security team, Datadog Security Labs, Sansec, Cloudflare, Tenable FAQ, The Hacker News, PHP 8 changelog. Read 23 October 2026