PHP2Shell is the name for two critical bugs in PHP itself that let an attacker run code on a PHP web server without logging in, even when the site's own code has no flaws. If you run a site on PHP, you need the updates released on 21 October 2026.
What PHP2Shell is
PHP2Shell covers two vulnerabilities, CVE-2026-109618 and CVE-2026-109619, disclosed on 21 October 2026. Both are rated critical, 9.2 out of 10 on CVSS v4, and both can lead to remote code execution: the attacker gets to run their own commands on your server, as the user PHP runs as.
Researchers at Wiz found them with help from AI models and reported them to the PHP security team in August. The weak code is old. Wiz traced affected versions back to PHP 5.4, released in 2012, so almost every PHP install still running is exposed in some way.
The bugs aren't in WordPress, Drupal or a plugin. They sit in the PHP engine, in code that runs while PHP is still reading the incoming request, before any of your code has started. A 'Hello World' page on an unpatched PHP version can be attacked the same way as a large CMS. If 'vulnerability' and 'CVE' are new terms, the zero-day and CVE explainer covers them.
Why one request can affect the next
To see how the attack works, you need to know how PHP serves a website. PHP-FPM, Apache's mod_php and similar setups keep a small pool of long-lived worker processes. Each worker handles one request, cleans up, then takes the next one. A busy worker might serve thousands of visitors before it is ever restarted.
You can see this on a server by listing the PHP processes and running the command again a few minutes later:
Inside a worker, each request gets its own area of memory, called the request heap. When the request ends, PHP throws the whole heap away in one go, and the next request starts on clean memory. That design is fast, and it normally keeps visitors apart: your request can't see mine.
Each request also has a ceiling, memory_limit, which defaults to 128 MB. If a request tries to use more, PHP stops it with a fatal out-of-memory error. Hitting that limit is meant to be a safe failure: one visitor gets an error page and the worker moves on.
How the attack works
PHP2Shell turns that safe failure into an unsafe one by making PHP run out of memory at the wrong moment.
The attacker sends a form upload, a multipart/form-data request, stuffed with hundreds of empty upload parts or deeply nested field names. Each part is cheap to send but costs PHP extra memory to track, so a body under the usual 8 MB post_max_size can still push a request past memory_limit. PHP parses all of this before your application runs.
While parsing, PHP keeps some bookkeeping about the request in global variables that live as long as the worker does. For example, the session upload progress feature can record a session ID and a pointer to where it sits in the request heap. When the out-of-memory error hits mid-parse, PHP frees the request heap but doesn't reset those globals. They now point at memory that no longer belongs to anyone. That is a dangling pointer, and using one is a 'use-after-free' bug. The pointers video explains what a pointer is if the idea is new.
Here is the whole attack across two requests to the same worker:
How one request poisons the next
Step 1 of 7: The attacker sends a form with hundreds of empty upload parts. PHP starts parsing it before the site's code runs.
Leaking memory
In one version of the bug, PHP takes the stale session ID pointer and its length, and copies whatever now sits there into a PHPSESSID cookie in its response. The attacker reads the cookie. Because the worker has been serving other people, that memory can hold their passwords, session tokens, API keys or database credentials. This works even if the site never uses sessions, because the code path runs during request startup.
Running code
Other versions let the attacker write as well as read. By shaping the second request, they control what the stale pointer finds, so PHP updates or frees structures the attacker built. Wiz combined the memory leak, which reveals where things sit in memory, with these writes to run code on stock WordPress, Drupal and Joomla installs. A third variant goes through OPcache's shared memory, so one worker's failure can corrupt state that every worker uses.
Why it is so serious
PHP2Shell is worse than a typical web bug because the attacker needs no account and no mistake in your code. PHP also runs a large share of the web, much of it on servers nobody has looked at in years.
The bugs are fiddly to exploit: the official CVSS scores mark the attack complexity as high, and an exploit has to adapt to each server's memory layout. Wiz reports that AI models made that adaptation fast, which is part of why they compare PHP2Shell with Heartbleed in 2014 and Log4Shell in 2021.
Attackers didn't wait for the disclosure. Amazon's threat intelligence team logged an exploitation attempt against its MadPot honeypots on 17 October 2026, four days before the patches came out, and reports broad exploitation since. If you run PHP, treat 17 October as the date to start checking your logs from, not 21 October.
Fixing it
The only complete fix is to update PHP. The fixed releases are:
- PHP 8.5.12
- PHP 8.4.27
- PHP 8.3.36
- PHP 8.2.35
Linux distributions received the patches in advance, so on most servers the fix is an ordinary package update. Then restart PHP. This step is easy to forget: the old worker processes from earlier are still running the old code in memory, and they keep running it until PHP-FPM or Apache restarts them.
On a Debian or Ubuntu server running PHP 8.4 with PHP-FPM, the whole job takes a minute:
Containers need the same treatment. Pull the patched base image, rebuild, and redeploy; a running container keeps its old PHP until it is replaced.
When there is no patch
Take a small shop with three PHP sites. Two run PHP 8.4, and the update above fixes them. The third is an old site that still runs PHP 5.6. PHP 5.6 stopped getting security fixes on 31 December 2018, and nothing has been released for it now. The PHP team did publish minimal source patches for 7.4, 8.0 and 8.1 for people who build PHP themselves, but those versions are out of support too, and 5.6 isn't covered at all.
For that third site, the fix is to move it to a supported version such as PHP 8.5. That is real work: code written for PHP 5 often needs changes to run on PHP 8, so test it on a copy first. Until it is moved, CISA's advice for unsupported versions is to take the site offline.
If you can't update today
The PHP advisory lists stopgaps. They reduce the risk but don't remove it:
- Set
session.upload_progress.enabled=0inphp.inior the FPM pool configuration, then restart every worker. Setting it from inside the application withini_set()is too late, because the attack happens before your code runs. - On PHP 8.5, also set
fatal_error_backtraces=0. - Keep
post_max_sizelow, and limit request size and the number of form parts at the web server or proxy. - Turn on the PHP2Shell rules in your web application firewall if you use one; Cloudflare and AWS both published them.
Checking for an attack
PHP2Shell happens below the application, so your app's own logs may show little. Look in the web server and PHP logs for form uploads containing PHP_SESSION_UPLOAD_PROGRESS, memory-limit errors followed by HTTP 500s, oddly large PHPSESSID cookies, and workers that keep dying and respawning. On the server itself, look for new .php files in upload folders and PHP processes starting shells or downloading files. If you find signs of a break-in, rebuild the server rather than cleaning it, and change every password and key the site could read.
Common mistakes
- Updating without restarting: the new package is on disk, but the old workers still serve requests with the old code.
- Checking the wrong PHP:
php -vreports the command-line PHP, which is a separate package from PHP-FPM. Confirm the version your web server uses, for example withphp-fpm8.4 -von Debian, or a temporaryphpinfo()page you delete afterwards. - Trusting the version number alone: some distributions backport the fix without changing PHP's version number. Check your vendor's security notice for the package version that contains it.
- Forgetting PHP you didn't install: PHP often ships inside other products, appliances and old containers. List every place it runs, internet-facing first.
- Assuming 'no bug in my code' means safe: clean application code doesn't help here; only the engine update does.
Key takeaways
- PHP2Shell is two critical bugs in the PHP engine (CVE-2026-109618 and CVE-2026-109619) that allow remote code execution with no login.
- The attack makes PHP run out of memory mid-request, then uses a pointer PHP forgot to reset when the same worker serves the next request.
- Update to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, then restart PHP so the old workers go away.
- PHP 8.1 and older, including 5.6, get no official fix: move those sites to a supported version.
- Exploitation started before the disclosure, so check logs from 17 October 2026.