Your change ticket says PHP is patched. The Azure portal says your app runs PHP 8.3. Both can be true, and neither one tells you whether that app is on 8.3.36.
PHP2Shell (CVE-2026-109618 and CVE-2026-109619) is a pair of unauthenticated remote code execution flaws in PHP itself, not in WordPress or a plugin. Attackers were trying it four days before the fix shipped. The hard part this week isn't installing the update. It's proving that every PHP runtime you own is actually on a fixed build, and then dealing with what may have leaked before you got there.
Prefer to watch? The five-minute video above walks through the same checklist.
What is PHP2Shell?
Two bugs in how PHP sets up and cleans up a web request. The PHP security advisory rates both CVSS v4.0 9.2.
- CVE-2026-109618, out-of-memory corruption. An out-of-memory error can interrupt PHP while request data is only partly initialized, and cleanup then treats the broken data as valid. Result: code execution as the web worker account, no login needed.
- CVE-2026-109619, stale global state. Request state can outlive the memory behind it, and a later request on the same worker may use it. That's a use-after-free. Besides code execution, it leaks memory. Wiz says that memory can hold "passwords, authentication tokens, API keys and certificates belonging to other requests or the server itself," and the leak works without getting a shell.
You may have seen a 10.0 score. The PHP Foundation says the CVE IDs that circulated before release carried an incorrect 10.0 (Tenable FAQ). It's 9.2, which is still about as bad as a web bug gets.
Every PHP install that serves web requests is in scope: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. PHP rates mod_php highest, because a single unauthenticated request can trigger the demonstrated exploit before any application code runs. Calif says it confirmed pre-auth RCE against specific WordPress, Drupal, Joomla and Magento versions, and Silas Cutler's rough estimate is over 1.3 million exposed hosts (Tenable).
The PHP2Shell timeline
| Date (2026) | What happened |
|---|---|
| 17 October | Amazon's MadPot honeypots log the first exploitation attempt, four days before disclosure (AWS). |
| 20 October | The CVE IDs leak on Hacker News and social media. PHP posts an advance notice and pulls the release forward (Huntress). |
| 21 October | PHP ships 8.5.12, 8.4.27, 8.3.36 and 8.2.35. Source-only backports for 7.4, 8.0 and 8.1. Calif and Wiz publish details. |
| 21-22 October | Amazon reports "broad exploitation attempts in the wild" from multiple actors. watchTowr says its honeypots saw exploitation of both CVEs (watchTowr). |
PHP 5.4 through 7.3 get nothing (Help Net Security). As of 22 October the CVEs weren't in CISA's KEV catalog, but CISA's alert is blunt: if you run PHP 8.1 or earlier, take those systems offline until they're patched or upgraded.
Why "patched" is hard to prove in managed cloud
The trap: someone runs a config query, sees PHP|8.3, and closes the ticket.
Azure App Service stores the PHP version as major.minor. linuxFxVersion says PHP|8.3. It never says 8.3.36. A config scan, ours included, can tell you a branch is supported or end of life. It can't tell you the patch level running inside the worker. That's the gap between configuration and reality.
Start with an inventory. Read-only, runs in Cloud Shell:
az webapp list --query "[].{name:name, rg:resourceGroup}" -o tsv |
while read -r name rg; do
az webapp config show -g "$rg" -n "$name" \
--query "{app:'$name', linux:linuxFxVersion, windowsPhp:phpVersion}" -o tsv
done
linuxFxVersion covers Linux apps and phpVersion covers Windows apps (Microsoft Learn). Add --slot for deployment slots, because staging slots get forgotten.
Then prove the patch level where PHP actually runs:
- App Service on Linux. Open
https://<app>.scm.azurewebsites.net/webssh/hostand runphp --version. Microsoft says the patched images reached the Latest and Standard release channels on 21 October. Extended gets it last, so move off Extended (App Service announcement). - App Service on Windows. Built-in PHP there is end of life and Microsoft says no security patch is currently planned. Move to Linux or bring your own patched runtime, which you then own.
- Custom containers anywhere. App Service doesn't patch your image. Neither does any other platform. Rebuild from a fixed base, redeploy, then run
php -vinside the running container, not the Dockerfile you think you shipped. - AWS Elastic Beanstalk. The platform version maps to a PHP patch version on the PHP platform history page. Check what your environment runs and whether managed updates are on.
- Cloud Run, Cloud Run functions, App Engine. The runtime ID (
php83) is major.minor too. Check whether automatic base image updates are enabled and read Google's notice before you assume.
Managed platforms patch on their own schedule. Read the provider's notice, then measure. And remember that distro packages often keep the old version string with a backported fix, so on a VM trust the vendor advisory for that package revision, not php -v alone.
The PHP you forgot you had
The web apps are the easy part. The NCSC-NL php2shell repo keeps a running list of products that embed PHP, and it's longer than you'd like:
- Appliances and network gear. Palo Alto said all PAN-OS and Panorama versions are affected, with no fixed release yet (Help Net Security). You wait for the vendor and lock down the management interface meanwhile.
- Control panels. cPanel, Plesk and CloudLinux ea-PHP and Alt-PHP builds, each with its own package revisions.
- Windows software bundling PHP. Invisible to your Linux package inventory.
- Static binaries. FrankenPHP static builds embed PHP, so updating the system PHP doesn't fix them.
- Your own security tools. Tenable shipped patch SC-202610.1 for Security Center and Enclave Security, which bundle PHP. It moves them to 8.2.35.
Huntress's advice is the right first step: inventory every PHP install, including the ones inside vendor software. If you skipped shadow IT cleanup last year, this is where it bites.
Patching isn't the end
Two reasons to keep going after the update.
Hunt from 17 October, not 21 October. Amazon says to investigate from at least 17 October. Anything internet-facing that ran vulnerable PHP before your patch window is a candidate. Look for:
- A PHP worker (
php-fpm,php-cgi,httpd,apache2,w3wp) spawningsh,bash,cmd.exeorpowershell.exe - The same parents launching
python,perl,curl,wget,ncorcertutil.exe - Reverse shell patterns in command lines:
/dev/tcp/,fsockopen,mkfifo - Recon from the web server:
whoami,id,uname -a - New files in the web root, new cron jobs or scheduled tasks, new local accounts
- POST requests containing
PHP_SESSION_UPLOAD_PROGRESS, which Amazon flags
Most of that list comes from Huntress. A web server launching shells is classic living-off-the-land behavior, and your EDR should alert on it.
Rotate what lived in that memory. CVE-2026-109619 can leak worker memory with no shell and no process tree to catch. So a clean hunt doesn't clear you. If an exposed host ran a vulnerable build, rotate the secrets it held: database passwords, API keys, cloud credentials in environment variables, session signing keys and TLS private keys. Rotate the database password even though it lives in Key Vault, because the app pulled it into memory to use it. Our Key Vault misconfigurations post covers rotation without downtime.
If you can't patch today
PHP's interim settings reduce specific attack paths. They don't make you safe, and PHP says so.
memory_limit=-1, set where apps can't override it (php_admin_valuein the FPM pool or Apache config)session.upload_progress.enabled=0inphp.ini, the FPM pool or server config. Notini_set(), not.user.ini- On PHP 8.5,
fatal_error_backtraces=0 - Restart every PHP worker after the change
Keep session.upload_progress.enabled=0 in place: on 23 October PHP published a separate informational advisory on session upload progress (CVE-2026-115560) that recommends the same setting until the next release. Cloudflare's WAF rules help, but only for traffic that actually goes through Cloudflare.
The end-of-life trap
PHP 8.1 and older get no official release. The 7.4 to 8.1 source backports only help if you build PHP yourself. And there's a date coming: PHP 8.2 security support ends on 31 December 2026. That's ten weeks away. If you're upgrading off 8.1 this week, go to 8.3 or newer and do it once.
PHP2Shell checklist
Inventory
- List every PHP runtime: App Service, containers, VMs, serverless, appliances, control panels, Windows software, vendor tools.
- Record branch and actual patch build for each, measured with
php --versionwhere PHP runs.
Patch
- 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or a vendor package that lists both CVEs.
- App Service: Standard or Latest channel, not Extended. Windows built-in PHP: migrate.
- Rebuild and redeploy every custom image. Restart all workers.
- 8.1 and older: offline or isolated until upgraded.
Hunt
- Review process, file and account activity on exposed hosts from 17 October onward.
- Preserve web server and PHP logs before you rebuild anything.
Rotate
- Database passwords, API keys, cloud credentials, signing keys and certificates on any host that ran a vulnerable build while exposed.
Plan
- Book the 8.2 upgrade before 31 December 2026.
The one thing to do this week
Pick your three most exposed PHP apps and get a real php --version out of each one, from inside the running worker. If any answer doesn't match what your ticket says, you've found your actual risk. If you want help with the branch side, SecValley's read-only scans flag Azure App Services still running end-of-life PHP branches, AWS Elastic Beanstalk environments on deprecated or retired platform branches, and Google Cloud functions on deprecated runtimes, so you know where to look first. The patch build check is still yours to run.
Frequently Asked Questions
What is PHP2Shell?
Two critical PHP flaws, CVE-2026-109618 and CVE-2026-109619, rated CVSS v4.0 9.2, that allow unauthenticated remote code execution and memory disclosure on PHP servers handling web requests.
Which PHP versions fix PHP2Shell?
PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.1 and older have no official release, only source backports for 7.4 through 8.1.
Is PHP2Shell exploited in the wild?
Yes. Amazon saw a first attempt on 17 October 2026, four days before disclosure, and reports broad exploitation attempts since.
Does updating WordPress fix PHP2Shell?
No. The flaws are in the PHP runtime, so you have to update PHP itself and restart every worker.