PHP2Shell: two critical PHP core flaws, what they do, and how to actually fix them
TechScripts Nepal · Kathmandu · October 26, 2026 · 6 min read
On October 21 and 22, 2026, PHP's maintainers and Wiz Research disclosed two critical vulnerabilities in the PHP core itself, not in a framework or a plugin. Together they have been nicknamed PHP2Shell. Both carry a CVSS v4.0 score of 9.2, and both can lead to unauthenticated remote code execution and memory disclosure. Because PHP sits underneath a very large share of the web, from custom applications to WordPress hosting to the admin panels of network appliances, this is one of the more consequential PHP advisories in years.
The two bugs
Both flaws live in how PHP handles an incoming request, and both are reachable over the network with no login.
CVE-2026-109618 is an out-of-memory handling flaw. When PHP runs out of memory while processing a request, it can be interrupted while the request's data is only partly initialized. The cleanup code that runs afterwards then treats that half-built data as if it were valid. An attacker can push PHP into this state with large or deeply nested multipart payloads, the same format used for file uploads.
CVE-2026-109619 is a use-after-free. Internal state that belongs to one request can outlive the memory backing it. A later request handled by the same worker process can then use that stale state before it is reset. This one depends on a worker serving more than one request, which is how most production PHP setups (php-fpm, Apache with mod_php, FrankenPHP and similar) are configured.
According to Google's write-up, AI models were used in discovering the flaws, developing exploits, and validating the patches. That detail is worth noting for what it implies: the time between "a bug exists" and "a working exploit exists" keeps shrinking.
Who is affected
- Vulnerable: every PHP version from 5.4 through 8.5.11.
- Fixed in: PHP 8.5.12, 8.4.27, 8.3.36, and 8.2.35.
- Not getting a fix: PHP 8.1 and earlier are end-of-life, and the project will not backport patches to them. If you are still on PHP 7.4, 8.0, or 8.1, the only remediation is upgrading to 8.2 or newer.
That last point is the uncomfortable one. Plenty of production PHP in the world runs on old branches because upgrading was always "next quarter." This is the moment that postponement stops being free.
Timeline
- October 17: Amazon Threat Intelligence reported seeing an exploitation attempt that predates public disclosure by several days.
- October 21: CVE IDs were assigned, PHP published its advisory, and the fixed releases shipped. Technical details reportedly leaked before the coordinated patch window, according to Infosecurity Magazine.
- October 22: Wiz and PHP made the disclosure public, and Google Cloud published response guidance.
- October 23: PHP published an informational advisory for a third issue, CVE-2026-115560, an RCE that requires an unusual combination of configuration and application code. The mitigations for PHP2Shell also address it.
Is it being exploited? Reports conflict
This is where careful reading matters. watchTowr says it has seen exploitation in the wild since October 21 through its honeypots. CISA said on the same day that it had not observed exploitation, and as of October 22 neither CVE was in its Known Exploited Vulnerabilities catalog. Sophos published a proof-of-concept write-up but walked back an earlier claim of confirmed successful exploitation, saying its telemetry shows scanning and a small number of attempts. Recorded Future's view is that available reporting doesn't establish how many compromises have actually succeeded.
A sensible reading: exploit code is public, scanning is happening, and the number of confirmed victims is unclear. None of that argues for waiting. It argues for patching before the uncertainty resolves itself the hard way.
What to do, in order
1. Upgrade and restart the right process. Install a fixed version from your distribution's security repository or an official build, then restart the process that actually serves traffic: php-fpm, apache2/httpd, FrankenPHP, or LiteSpeed. Updating packages on disk does not replace code already loaded into running workers, and this is the step most often missed. Rebuild and redeploy any custom container images too.
2. If you can't patch yet, shrink the attack surface.
- Put settings in the global
php.inirather than.htaccess. - Disable
session.upload_progress.enabledif you don't need it. - Tighten limits such as
post_max_size,upload_max_filesize,max_input_vars, andmax_file_uploads, or turn uploads off entirely for services that don't use them. - Setting
pm.max_requests = 1makes each worker handle a single request before resetting, which blocks the multi-request attack path at a performance cost. - At the edge or WAF, block
multipart/form-dataon routes that don't need uploads, reject chunked POST requests, and cap request body size.
These are stopgaps. Google's guidance is explicit that they do not replace patching.
3. Hunt for signs of probing. Google and Mandiant suggest looking for:
- unusually large
PHPSESSIDvalues (over 256 bytes) in logs or responses, - URIs with repeated
.php/segments returning 404, - rapid, interleaved bursts of HTTP 500 and 200 responses to the same POST endpoint,
- PHP worker crashes (SIGSEGV, exit code 139) or core dumps,
- web server processes spawning shells or download tools such as
sh,curl, orwget.
If you suspect a compromise, capture memory forensics from the host before restarting it, because a restart destroys the evidence in memory.
4. Don't forget the PHP you didn't install. Many appliances, gateways, and management panels embed PHP and need vendor firmware updates rather than a package upgrade. Add them to your inventory.
5. Contain by default. Run PHP workers as an unprivileged user with a read-only document root, block outbound internet access from PHP servers where you can, and prevent the PHP process from spawning shells. These controls limit the damage of this bug and the next one.
The larger lesson
PHP2Shell is a reminder that the dependency you trust most is the one you stop thinking about. Runtime upgrades rarely make anyone's roadmap until a headline forces them. Teams that already had an inventory of their PHP versions, a tested upgrade path, and a way to restart workers safely spent this week patching. Teams without those spent it finding out what they run.
If your estate is mostly legacy PHP and the people who know it best are already fully booked, this is exactly the kind of short, urgent job where an engineer embedded in your team does more than a long project plan would. It's a role we fill at TechScripts Nepal, and we wrote about how forward-deployed engineering works if you want to see whether it fits. Either way, the same lesson applies as in the FBI portal breach: the patch existed, and the damage happens in the gap before it's applied.