Blog
PHP2Shell: AI Helped Find Two Critical Bugs in PHP Itself. Patch Today.
Two CVEs in the PHP engine allow unauthenticated remote code execution. The fixes shipped October 21, exploits are getting better, and most PHP installs still aren't patched. Here's how to check yours.
Caleb Dorris 21 October 2026, 8:06 PM Updated 28 October 2026 18 min

Update, October 28, 2026
The federal deadline is tomorrow, and most PHP servers that show their version still aren't patched
CISA's deadline for federal agencies to fix both PHP2Shell bugs is tomorrow, Thursday, October 29. That deadline only binds federal civilian agencies, but it's a sensible one for everyone else too. The details are in yesterday's update below.
How many servers are still exposed? You may have seen "76% of servers are still unpatched" going around. I couldn't find who measured that exact number or how, so treat it as a reported figure, not a fact. The best primary data I've found is Censys's public PHP2Shell tracker. As of 6:15 AM Central on October 28, it counted about 32.7 million internet-facing PHP services reporting an affected version and about 11.8 million reporting a fixed one. That's 73.4% still affected, down from about 78% on October 23. Patching has slowed a lot. Censys saw more than 4 million services move to a fixed version on each of October 22 and 23, and only a few hundred thousand a day since.
Two caveats. Censys can only count services that reveal their PHP version, and it couldn't see the version on about 64.8 million more. A distro package can also carry the fix under an older version number. Still, about 24.2 million of the affected services run PHP 8.1 or older, which has no official fixed release. For those, the fix is an upgrade.
One more KEV entry. On October 27, CISA added CVE-2026-111497, the Brotli bug that PHP's rebuilt Windows packages fix, to the same catalog, with a November 10 federal deadline. Brotli is a compression library used well beyond PHP, so update it in your OS packages too, not just PHP on Windows.
If you're not sure which of your servers are in that 73%, get a free quote and I'll check them with you.
Update, October 27, 2026
CISA now lists PHP2Shell as exploited in the wild. Patch this week.
On October 26, CISA added both PHP2Shell bugs, CVE-2026-109618 (OOM corruption) and CVE-2026-109619 (stale request state), to its Known Exploited Vulnerabilities catalog. CISA only adds a bug there when it has reliable evidence of active exploitation in the wild. Federal civilian agencies have until Thursday, October 29 to fix them, and CISA flagged both as requiring forensic triage under its patching directive. It lists ransomware use as unknown. When I wrote my October 23 update, neither CVE was on that list. Now both are.
The fix hasn't changed. PHP's October 21 releases are still the ones to get: 8.5.12, 8.4.27, 8.3.36 or 8.2.35, which covers every supported branch. There's no fix for 8.1 or older. Those branches are end of life, so the real fix is an upgrade to a supported version. If you run PHP on Windows, PHP also posted rebuilt Windows packages on October 26 (8.5.12-1, 8.4.27-1, 8.3.36-1 and 8.2.35-1) that fix a separate Brotli bug, CVE-2026-111497. The PHP version number stays the same.
Patch now:
- Check your version. Run
php -v, and check what the web server runs too (php-fpm -v), because they can differ. - Upgrade to the fixed release for your branch, or a distro package whose changelog lists both CVEs.
- Restart PHP-FPM, Apache or LiteSpeed, and any long-running workers. Old processes keep running the old code until they restart.
- On shared hosting, check the PHP version in your control panel (in cPanel, MultiPHP Manager) or in WordPress under Tools > Site Health > Info > Server. If it's below the fixed release, ask your host whether it's patched for CVE-2026-109618 and CVE-2026-109619.
- Verify. Run the check again after the restart. The full five-minute version is in the patch check below.
If you have servers you're not sure about, get a free quote and I'll check them with you.
Update, October 25, 2026
Four days in: a better exploit, a botnet, a public challenge lost, and slow patching
Here's what changed since my last update, and what didn't.
The exploits got better. VulnCheck built an exploit for CVE-2026-109618 that gets past ASLR on x86-64 with display_errors=off, the setup PHP recommends for production. As of October 23 it covers PHP 8.4.10 through 8.4.26 and 8.5.10 and 8.5.11 on mod_php, including a default WordPress Docker install. It's only available to VulnCheck's paying customers, and VulnCheck says it doesn't know of any other public or commercial exploit that does this across multiple PHP versions. It also expects that to change. Most of the hundreds of "PoC" repos on GitHub don't work.
Someone took the "prove PHP2Shell is hard" bitcoin. Over the weekend, Steal My Bitcoin put a small bitcoin wallet key on an internet-facing PHP 8.4.26 server — one release short of the 8.4.27 fix — and dared people to take it. LiveOverflow had looked at the challenge earlier on Sunday and described it as aiming to show PHP2Shell isn't realistically exploitable; his fingerprinting put the server at X-Powered-By: PHP/8.4.26. Later that evening he posted that @killa had solved it a few hours earlier, and that killa was confused because the wallet address was wrong — the server didn't have the right wallet. The challenge creator, James Pavur, confirmed the same: killa solved it hours earlier, and Pavur had put the root wallet WIF on the server instead of the branch WIF. The winner page at stealmybitcoin.com lists the win at 15:47 UTC on October 25, about 19 hours after the challenge started, and links killa's write-up. That write-up walks a multipart PHP_SESSION_UPLOAD_PROGRESS OOM path into a forged structure that ends in zif_system against Alpine PHP 8.4.26 — the same family of bugs the October 21 releases closed. A CTF isn't a production break-in, but an unpatched 8.4.26 box on the public internet lost. If you're still on 8.4.26, or any build below the fixed releases, patch and restart. If you're still on 8.1 or older, read why you should upgrade to PHP 8.5.
A botnet tried it. Sophos says attackers tried to use PHP2Shell to install a Mirai-derived botnet it calls Potassium, per SecurityWeek. That attempt was stopped, and the malware never reached the server. Hunt.io tied the traffic it saw to an established Mirai-style botnet that recently added these bugs to how it spreads.
One reported break-in, with an asterisk. On October 23, Unit 42 added a case to its PHP2Shell threat brief: attackers hit a government entity in Europe and, within two hours of the initial exploitation, had password hashes and multi-factor secrets, set up an NTLM-relay tunnel into Active Directory, and tried for Domain Admin. Unit 42 says the follow-up work looked like an agentic AI platform at the wheel: command batches wrapped in markers like ==SHELLUSER== and ==PASSWD== so a model can parse the output, short tasks one after another, and quick pivots after failures. The brief doesn't spell out which bug got them in, and it doesn't name the government. Earlier that same day, SecurityWeek reported that no successful compromise had been confirmed, citing Hunt.io, Wordfence and Sophos, and that as of that morning CISA hadn't added either CVE to its Known Exploited Vulnerabilities catalog. So: lots of attempts, one vendor-reported intrusion, no confirmed wave.
Patching is slow. Qualys looked at anonymized data from more than 10,000 customers. Of 156 million PHP installations with a known version, only 199,000 were patched in the first 12 hours, and 581,000 in the first 24. About 110 million (71%) run PHP 5.4 through 8.1, which are past end of life, and Qualys says most of those will never get a vendor patch. Another 44 million run supported branches where the fix exists but hadn't been applied.
The third CVE still has no fix. PHP hasn't shipped a release for CVE-2026-115560 yet. Its advice is still to set session.upload_progress.enabled=0 until the next regular bugfix release. If you set it on October 21, leave it.
My read hasn't changed: exploiting this on a hardened server is hard, and it's getting easier. Patch and restart.
PHP2Shell patch check
Is my site patched? Five minutes to find out
- Check the version. On the server, run
php -v. You want 8.5.12, 8.4.27, 8.3.36, 8.2.35 or newer on your branch. - Check what the web server actually runs. The CLI and PHP-FPM can be different builds. Run
php-fpm -v(on Debian or Ubuntu it's usuallyphp-fpm8.3 -vor similar), or drop a one-line<?php echo PHP_VERSION;file in the webroot, load it once, and delete it right away. - Distro packages can hide the fix. Backported fixes may keep the older version number, so a lower number isn't proof you're exposed. Search the package changelog for the CVE:
apt changelog php8.3-fpm | grep CVE-2026-109618on Debian or Ubuntu,rpm -q --changelog php-fpm | grep CVE-2026-109618on RHEL-family systems. - Check the stopgap setting. Run
php -i | grep session.upload_progressand look forsession.upload_progress.enabled => Off => Off. Check the FPM side too, because the pool config can override php.ini. If it's on, set it in php.ini or the FPM pool, notini_set()or.user.ini, and restart every worker. - On shared hosting or WordPress, you probably can't run commands. In WordPress, go to Tools > Site Health > Info > Server. In cPanel, check MultiPHP Manager. If the version is below the fixed release, open a ticket and ask your host directly whether it's patched for CVE-2026-109618 and CVE-2026-109619 and whether
session.upload_progress.enabledis off.
If any box comes back old, update it, restart PHP-FPM, Apache and any long-running workers, then run the check again. If you'd like a second set of eyes on your servers, get a free quote.
Update, October 23, 2026
A new PHP advisory, and where exploitation actually stands
One more setting. PHP published an informational advisory today for a separate, unlikely RCE path, CVE-2026-115560. It recommends session.upload_progress.enabled=0 until the next regular bugfix release. The October 21 releases don't fix this one, and PHP says the full advisory comes with that next release. It only happens when an app sets session.serialize_handler to php_binary or php_serialize and then switches it to php with ini_set() before session_start(), with upload progress still on. If you already turned upload progress off on October 21, you're covered. If not, set it in php.ini or the FPM pool, not with ini_set() or .user.ini, and restart every worker.
Exploitation: lots of attempts, no confirmed break-ins yet. Amazon saw its first attempt on October 17 and reports broad exploitation attempts since. watchTowr's FAQ, updated today, lists exploitation "in the wild" based on its honeypot network. Sophos reported a successful compromise on October 22, then corrected itself the same day: its telemetry showed scanning and failed attempts, with no evidence of a successful compromise, and it says building a working exploit is proving hard. As of October 22, no successful break-in had been publicly confirmed, and neither CVE was on CISA's Known Exploited Vulnerabilities catalog. That's a window, not a reason to wait. (See the October 25 and October 27 updates above for what changed.)
Update, October 22, 2026
Attacks started before the patch. Update now.
A day after I wrote this, the picture is worse. SecurityWeek reports that Amazon saw the first exploitation attempt on October 17, while the bugs were still under embargo. Details leaked online on October 20, and more proof-of-concept exploits showed up within hours of the release. Amazon says PHP2Shell is now being broadly exploited. watchTowr says the exploits it has seen so far don't actually get code execution. I wouldn't bet a server on that lasting.
CISA told organizations to patch immediately, prioritize internet-facing systems, and take PHP systems offline if they can't update or are still on 8.1 or older. CERT-EU rates both CVEs 9.2, notes that proofs of concept are circulating, and says to isolate internet-facing apps you can't patch yet.
Nothing about the fix has changed. The fixed releases are still 8.5.12, 8.4.27, 8.3.36 and 8.2.35, and php.net says there's no complete mitigation. Every PHP setup that serves web requests is affected: PHP-FPM, mod_php, php-cgi, FrankenPHP and LiteSpeed. mod_php is the highest risk.
What to do now
Five steps, in order
- Check your version. Run
php -von every box, and check what each web SAPI is actually running. The CLI and FPM aren't always the same build. - Upgrade to the fixed release for your branch: 8.5.12, 8.4.27, 8.3.36 or 8.2.35. Then restart PHP-FPM, Apache and any long-running workers.
- If you use remirepo, don't wait on it. PHP says those packages weren't updated on release day. Switch to your distro's packages or build from source.
- Plan your way off 8.1 and older. The PHP project has no official fix for them. Some distros and LTS vendors have backports, and PHP posted minimal source backports for 7.4, 8.0 and 8.1. Treat those as a bridge, not a plan.
- Turn on WAF rules as a stopgap. Cloudflare enabled php2shell rules by default on every plan with the WAF deployed, Free included. A WAF is not a substitute for patching. Cloudflare says to patch anyway, and so do I.
Most PHP security news I read is about a plugin, a framework, or somebody's custom code. This one is different. The bugs are in PHP itself, in the engine under WordPress, Drupal, Laravel and whatever admin panel you inherited three years ago.
The PHP team shipped emergency releases on October 21, 2026, for two critical vulnerabilities grouped under the name PHP2Shell. The researchers who found them say frontier AI models were a big part of how they did it. I spend my days in PHP, so here's what happened, kept as close to the sources as I can, and what I'm doing about it.
What the bugs are
There are two CVEs. Both are rated critical, CVSS v4.0 9.2, in PHP's own advisories.
CVE-2026-109618, RCE via OOM corruption (GHSA-w8hw-w9fx-j79w). PHP handles out-of-memory errors by jumping out of the current context. Sometimes that happens while request data is only partly set up. Request shutdown can then treat the half-built data as valid.
CVE-2026-109619, RCE via stale global state (GHSA-6wmf-4rv5-p3rp). Internal state that belongs to one request can outlive the memory behind it. The next request handled by the same worker can use that stale state before normal setup resets it. That's a use-after-free.
The researchers demonstrated unauthenticated remote code execution against WordPress, Drupal and Joomla. Calif says it also confirmed pre-auth RCE on MediaWiki, Magento, phpMyAdmin, Nextcloud, Laravel, Symfony and WHMCS, among others. Wiz also showed a separate memory leak where a crafted request can pull chunks of worker memory back out in a PHPSESSID cookie. That memory can hold passwords, tokens and API keys from other requests.
The important part: the flaw isn't in those apps. Per Wiz, even a plain "Hello World" script on an affected PHP version can be vulnerable. PHP lists PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed as at risk, and it rates mod_php highest. On mod_php, one unauthenticated request can trigger the attack before any of your code runs.
The affected code goes back a long way. Wiz and Calif both trace affected paths to PHP 5.4.
How AI found it
Three groups reported the issues.
Calif reported first, as part of OpenAI's Patch the Planet initiative. OpenAI says Calif found a critical flaw using GPT-5.6 Sol. Calif's write-up says its researcher started the audit by pointing an LLM at a known bug pattern: a memory-limit bug Stefan Esser found back in 2004, plus an out-of-memory issue from 2020 that a 2024 audit rediscovered but never proved exploitable. Calif says that initial discovery used no special harness and only models anyone could get. The model then helped turn the pattern into a reusable check, which surfaced more variants.
Wiz Research found and reported the bugs independently, using Wiz Atlas, Gemini 4 Argon and GPT-5.6 Sol. In Wiz's telling, the hard part was never spotting the weird code. It was chaining several memory bugs into a working exploit and adapting that exploit to each target's memory layout, and that's what the models made practical. OpenAI's Codex Security team is also credited.
The timeline so far
- Aug 1
- Calif's first findings.
- Aug 11
- Calif reports to the PHP security team.
- Aug 19
- Wiz's first finding.
- Aug 24
- Wiz reports.
- Oct 17
- First exploitation attempt seen by Amazon, while the bugs were still under embargo.
- Oct 20
- PHP gives advance notice of a critical release. Details leak online the same day.
- Oct 21
- Patched releases and public disclosure.
- Oct 21
- CISA urges immediate patching. Mass exploitation attempts follow the release.
- Oct 22
- Sophos reports, then retracts, a successful compromise. No confirmed break-ins publicly reported.
- Oct 23
- PHP's informational advisory on session upload progress (CVE-2026-115560).
- Oct 22
- VulnCheck has an exploit that gets past ASLR in PHP's recommended production setup.
- Oct 23
- Unit 42 reports a government intrusion with AI-driven follow-up. Qualys: 199,000 of 156M installs patched in the first 12 hours.
- Oct 25
- Steal My Bitcoin challenge on PHP 8.4.26 solved by @killa (~19 hours after it went up). LiveOverflow and James Pavur confirmed the solve; winner write-up uses the upload-progress OOM path.
- Oct 26
- CISA adds both CVEs to its Known Exploited Vulnerabilities catalog, with an October 29 deadline for federal agencies.
- Oct 27
- CISA adds the Brotli bug fixed in PHP's Windows rebuilds (CVE-2026-111497) to its KEV catalog, with a November 10 federal deadline.
- Oct 28
- Censys's tracker shows 73.4% of PHP services that reveal their version still on an affected release (32.7M affected, 11.8M fixed).
Distros and LTS vendors got the patches early.
What PHP devs should do
Update PHP, then restart it.
Fixed versions
- 8.5
- 8.5.12
- 8.4
- 8.4.27
- 8.3
- 8.3.36
- 8.2
- 8.2.35
The fixed versions are 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Distros and LTS vendors got the patches early, so check your vendor's packages first. The volunteer-run remirepo packages weren't updated on release day, and PHP says to switch to distro packages or build from source instead. After you upgrade, restart Apache, PHP-FPM and any long-running workers. Updating WordPress or running composer update does nothing here. This is the runtime, not your app.
Check every runtime, not just the main one. The staging box, the cPanel account running an old client site, the container image nobody has rebuilt since spring. Run php -v on all of them, and check what each web SAPI is actually serving.
If you're on 8.1 or older, you're off the main road. The PHP project doesn't support those versions anymore. Some distros and LTS vendors have backports. Given how bad this is, the PHP security team also put out minimal source backports for 7.4, 8.0 and 8.1, for people who build from source. Also on the calendar: 8.2 hits end of life on December 31, 2026.
If you can't patch today
Reduce exposure
None of these settings fix the bugs. They block some known paths while you schedule the real fix. Set them in php.ini, the FPM pool or the server config, not with ini_set() or .user.ini, and restart every worker:
session.upload_progress.enabled=0. Most apps don't use it, and PHP suggests leaving it off even after you patch.fatal_error_backtraces=0on PHP 8.5.memory_limit=-1, enforced so apps can't override it, with a container or cgroup limit as the backstop. Don't useRLIMIT_ASorRLIMIT_DATA. PHP warns those can trigger the vulnerable path.- A lower
post_max_size, and limits on request size and multipart parts at the proxy.
Cloudflare says its php2shell WAF rules are on by default for every plan with the WAF deployed, Free included. Treat that as a speed bump, not a fix. If you can't patch or add these settings, CISA and CERT-EU both say to take the system offline or isolate it until you can.
Look for signs. Wiz suggests watching for odd multipart requests followed by memory-limit errors or bursts of HTTP 500s, oversized or malformed PHPSESSID cookies, and workers crashing or restarting for no clear reason. CISA adds PHP worker processes launching shells or downloading tools. A clean log doesn't prove you're safe. These paths run below the app, so there may be little to see.
What the governments and WordPress are saying
- NSA: inventory everything that relies on PHP, replace end-of-life versions, and take a system offline if an immediate update isn't feasible.
- UK NCSC: find every PHP install, not only old ones, and patch internet-facing systems first. If you can't update or take a system offline right away, check it for signs of compromise and backdoors before you upgrade or apply mitigations. Patching doesn't remove a backdoor that's already there.
- WordPress.org: no WordPress update is needed for PHP2Shell. It's a PHP fix from your host or server. You can see your PHP version under Tools > Site Health > Info > Server. Separately, WordPress 7.1.3 (October 6) has its own seven security fixes, so make sure you have that too.
Website security checklist for October 2026
If you look after a WordPress or PHP site and just want the list, here's the order I'm working in:
- Find every PHP version you run, including staging and old client sites.
- Get onto a fixed release (8.5.12, 8.4.27, 8.3.36 or 8.2.35, or a vendor backport) and restart PHP-FPM, Apache and workers.
- On 8.1 or older, make a plan today. CISA's advice for systems you can't update is to take them offline.
- Set
session.upload_progress.enabled=0in php.ini or the FPM pool, and restart. It covers both the October 21 path and today's CVE-2026-115560. - Turn on WAF rules as a stopgap, not a fix.
- Update WordPress to 7.1.3 and your plugins.
- Look back to October 17. Amazon says to investigate from then, including POST requests with
PHP_SESSION_UPLOAD_PROGRESSin a form upload. Sophos lists the user agentphp2shell-scan/109618and a file at/tmp/nfsas signs of exploit traffic. Also check for admin accounts or plugins you didn't add. If anything looks off, my guide to auditing a WordPress site after a plugin compromise walks through what to check next. - Confirm you have a backup you can actually restore, stored somewhere other than the server.
The short version
Upgrade PHP, restart it, and check the servers you forgot you had.
I'm working through mine today.
Sources
- PHP.net, "Security advisory: Critical remote code execution vulnerabilities, update now"
- GHSA-w8hw-w9fx-j79w, RCE via OOM corruption (CVE-2026-109618)
- GHSA-6wmf-4rv5-p3rp, RCE via stale global state (CVE-2026-109619)
- Wiz Research, "PHP2Shell: AI uncovers critical RCE vulnerabilities affecting 70% of the Internet"
- Calif Research, "php2shell"
- OpenAI, "Patch the Planet: global response coordination as agents uncover critical vulnerabilities"
- PHP2Shell disclosure site
- Help Net Security, "PHP2Shell: Critical PHP vulnerabilities patched, update now!"
- CISA, "Critical Vulnerabilities in PHP Require Immediate Patching"
- CERT-EU, "Critical Vulnerabilities in PHP" (Security Advisory 2026-018)
- SecurityWeek, "PHP2Shell Exploitation Started Days Before Patches"
- Cloudflare, "Cloudflare deploys protections against php2shell vulnerability"
- PHP.net, "Informational advisory: Session upload progress" (Oct 23, 2026)
- NSA, "NSA Advisory: Critical Patches Recommended for PHP Vulnerabilities"
- NCSC, "Critical security issue affecting PHP"
- WordPress.org, "Critical PHP Security Release"
- WordPress.org, "WordPress 7.1.3 Maintenance and Security Release"
- AWS Security Blog, "Amazon Threat Intelligence identifies PHP2Shell exploitation prior to public disclosure in MadPot"
- watchTowr, PHP2Shell FAQ
- Sophos, "Proof-of-concept exploit released for PHP vulnerabilities"
- SecurityWeek, "Mirai Botnet Operators Join PHP2Shell Attacks as ASLR Bypass Exploits Emerge"
- Unit 42, "Threat Brief: Critical Vulnerabilities in PHP: CVE-2026-109618, CVE-2026-109619 (Updated October 23)"
- VulnCheck, "PHP2Shell Vulnerabilities: CVE-2026-109618 and CVE-2026-109619"
- Qualys, "PHP2Shell: Find, Mitigate, and Patch Now"
- Qualys, "Media Alert: Qualys Offers Free Services to Help Organizations Quickly Find and Fix PHP2Shell Vulnerabilities"
- LiveOverflow, X post announcing the Steal My Bitcoin solve
- LiveOverflow, earlier analysis of the Steal My Bitcoin challenge
- James Pavur, congratulations and key mix-up acknowledgment
- Steal My Bitcoin, winner page
- KillaBoi, StealMyBitcoin-PoC write-up
- CISA, Known Exploited Vulnerabilities Catalog (CVE-2026-109618 and CVE-2026-109619, added Oct 26, 2026)
- PHP.net, "Updated PHP Windows builds for Brotli security fix" (Oct 26, 2026)
- Censys, PHP2Shell Exposure Tracker (read October 28, 2026, 6:15 AM CDT)
- Censys, "Oct 21 Advisory: php2shell - PHP Unauthenticated Remote Code Execution" (updating live)
- NVD, CVE-2026-111497 (Brotli; added to CISA KEV October 27, 2026)
Need a web developer in Nashville?
PHP, WordPress and Next.js. Free quote, and I usually reply within a couple of hours.
caleb@calebdorris.com and call or text (615) 914-1073