PHP2Shell at a glance
PHP2Shell is not a flaw in WordPress, Laravel or a plugin: the PHP engine itself is at fault. Every PHP application that answers web requests is therefore affected, whatever its code looks like. The security advisory names PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed.
Both flaws share the same underlying mechanism. When PHP abruptly aborts a request (exhausted memory, fatal error), it can leave behind an internal state that is only half initialised or that has already been freed. A subsequent request, handled by the same PHP process, then reuses that state: this is what opens the door to remote code execution.
Key takeaways
- CVE-2026-109618 — memory corruption when
memory_limitis exceeded: request data that was only partially initialised is later treated as valid during the cleanup phase. - CVE-2026-109619 — stale global state: state that belongs to one request survives after its memory has been freed and can be read by the next request on the same process.
- Score: 9.2 out of 10 under CVSS 4.0 for each one, with no authentication and no user interaction required.
- Patched versions: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. The project no longer publishes releases for 8.1 and the older branches.
- Exploitation: watchTowr reports exploitation attempts caught in its network honeypots as early as 21 October 2026.
- Scope: researchers believe the affected branches go all the way back to PHP 5.4, although not every single version has been tested individually.
Why these two flaws are so dangerous
Most web flaws require a specific form, a user account or a vulnerable plugin. PHP2Shell needs none of that: the most common trigger is the processing of a multipart/form-data upload with session upload progress tracking (session.upload_progress), a mechanism that PHP enables by default and that runs before the first byte of your application. A web application firewall living inside your code, a WordPress security plugin or a Laravel middleware therefore all come into play too late.
The second factor is the execution model itself. PHP-FPM and Apache reuse the same process for hundreds of successive requests: this is precisely what allows a booby-trapped request to contaminate the next one. According to Imperva, the published techniques range from crashing processes to reading arbitrary files through the OPcache cache, including leaking around 67 KB of process memory inside an oversized PHPSESSID cookie. That memory can contain database passwords or API keys.
Which version to install for your branch
Scroll the table
| PHP branch | Patched version | What to do |
|---|---|---|
| 8.5 | 8.5.12 | Update, then restart PHP |
| 8.4 | 8.4.27 | Update, then restart PHP |
| 8.3 | 8.3.36 | Update, then restart PHP |
| 8.2 | 8.2.35 | Update, then plan the migration to 8.3 or 8.4 |
| 8.1, 8.0, 7.4 | No official release | Your distribution's patched package, a source backport, or else migration |
| 7.3 and earlier, 5.x | No published fix | Migrate to a maintained branch |
Check whether your servers are exposed
Watch out for a classic trap: the version shown by php -v on the command line is not necessarily the one that serves your websites. A server can have several versions of PHP-FPM installed side by side, and each site can point to a different one. You therefore need to check the version that is actually served over the web, one site at a time.
Take an inventory of the PHP versions being served
List the installed versions
On Debian or Ubuntu:
dpkg-query -W -f='${db:Status-Abbrev} ${Package} ${Version}\n' 'php*' | awk '$1=="ii"' | grep -E 'php[0-9.]+-(fpm|cli|common)|libapache2-mod-php'On RHEL, AlmaLinux or Rocky Linux:
rpm -qa 'php*' 'ea-php*' 'alt-php*' | sortFind the PHP processes that are running
systemctl list-units --type=service --state=running | grep -E 'php|apache2|httpd|lsws'Every active
phpX.Y-fpmservice is a version you need to check and to patch.Read the version served by a site
Drop a temporary file at the root of the site, query it, then delete it immediately afterwards:
echo '<?php echo PHP_VERSION, " ", PHP_SAPI;' > /var/www/monsite/v-check.php curl -s https://monsite.example/v-check.php rm /var/www/monsite/v-check.phpA result such as
8.3.36 fpm-fcgiindicates a patched version being served by PHP-FPM.Check your Docker containers
docker ps --format '{{.Names}}' | while read c; do echo "$c: $(docker exec "$c" php -r 'echo PHP_VERSION;' 2>/dev/null)"; doneA container without PHP shows nothing at all after its name.
Apply the fix
Linux distributions and extended support vendors received the fixes ahead of the public release. The patched package from your distribution therefore does not necessarily carry the number 8.3.36: Ubuntu 24.04, for example, patches its own version 8.3.6 in the package 8.3.6-0ubuntu0.24.04.13. Rely on your distribution's security advisory rather than on the PHP version number alone. In every case, a restart is essential: as long as the old processes keep running, it is the old code that answers your requests.
Update PHP for your environment
Debian and Ubuntu
sudo apt update sudo apt install --only-upgrade $(dpkg-query -W -f='${db:Status-Abbrev} ${Package}\n' 'php*' | awk '$1=="ii"{print $2}') sudo systemctl restart 'php*-fpm' sudo systemctl restart apache2 # if you use mod_phpIf your versions come from a third-party repository (for example the
ondrej/phpPPA), check that the version installed after the update really is one of the patched versions.RHEL, AlmaLinux, Rocky Linux
sudo dnf upgrade 'php*' sudo systemctl restart php-fpm sudo systemctl restart httpdAlmaLinux published its patched packages on 21 October 2026. The community Remi repository, on the other hand, had no update available at the time of the announcement: if you depend on it, check the installed version afterwards.
cPanel server (EasyApache 4 or CloudLinux)
sudo dnf upgrade 'ea-php*' 'alt-php*' /scripts/restartsrv_apache_php_fpm /scripts/restartsrv_httpdOn an older server, replace
dnfwithyum. Then check each version in WHM › MultiPHP Manager: any account still set to a branch with no fix available (7.x, 8.0, 8.1) must be switched over to a maintained version.Docker containers
docker compose pull docker compose up -d --force-recreate docker compose exec app php -r 'echo PHP_VERSION;'If your
Dockerfilestarts from aphp:8.3-fpmimage, rebuild the image withdocker compose build --pull: without--pull, Docker reuses the old base image that it has in its cache.Check the result
Run the check from the previous step again on every site. The fix is only in place if the version served over the web is patched, not merely the version installed on disk.
If you cannot update right away
The official PHP advisory suggests settings that reduce exposure without making the installation safe. They are there to buy you a few hours, not to replace the fix. They must be set in php.ini, in the PHP-FPM pool or in the web server configuration, never through ini_set() or a .user.ini file: those are read too late, after the request has already been parsed.
Against CVE-2026-109619, disable upload progress tracking. On PHP 8.5, also disable fatal error backtraces:
; in the FPM pool, for example /etc/php/8.3/fpm/pool.d/www.conf
php_admin_flag[session.upload_progress.enabled] = off
; PHP 8.5 only:
php_admin_flag[fatal_error_backtraces] = offAgainst CVE-2026-109618, the advisory recommends memory_limit = -1 enforced through php_admin_value, so that no application can redefine it, together with a bounded request size (post_max_size = 8M, or 32M if you need file uploads). In return, memory has to be capped somewhere else, with a container or cgroup limit. Do not use RLIMIT_AS or RLIMIT_DATA: they are exactly what causes the vulnerable allocation failure.
Then restart all PHP processes so that the settings take effect.
Add a barrier in front of PHP
Cap the size of requests at the web server level, before they ever reach PHP: client_max_body_size 8m; in nginx, LimitRequestBody 8388608 in Apache. If your site sits behind Cloudflare in proxied mode, WAF rules targeting the known PHP2Shell vectors have been rolled out to every account, the free plan included. These are safety nets only: nothing but the PHP update actually closes the flaw.
Look for traces of exploitation
The published attempts leave characteristic traces behind: PHP processes that crash, bursts of out-of-memory errors and multipart uploads that are abnormally large. If your server was exposed before you updated it, take ten minutes to check.
Checks to run after applying the fix
Look for killed PHP-FPM processes
sudo grep -E 'exited on signal (11|6)' /var/log/php*-fpm.log | tail -20A series of processes killed by signal 11 (SIGSEGV) since 21 October is a warning sign.
Look for memory limit overruns
sudo grep -rh 'Allowed memory size' /var/log/php* /var/log/nginx /var/log/apache2 2>/dev/null | tail -20Spot recently created PHP files
sudo find /var/www /home -name '*.php' -newermt '2026-10-20' -not -path '*/vendor/*' -not -path '*/cache/*' -lsAn unknown file with a generic name, in an upload folder or in
/tmp, should be examined before you delete anything.When in doubt, treat the server as compromised
Isolate the machine, keep a copy of the logs, then rotate the database passwords, the API keys and the secrets stored in
.envfiles: a memory leak may have exposed them without leaving any other trace behind.
On shared hosting
On shared hosting, you are not the one who updates PHP: the hosting provider maintains the versions on offer. Your part of the job is to check that your site uses a branch that still receives fixes. In cPanel, the version selection tool (MultiPHP Manager, or Select PHP Version on a CloudLinux server) shows the active version for each domain. If your site still runs on 7.4, 8.0 or 8.1, those branches no longer receive official PHP releases: switch to 8.3 or 8.4 after testing your site, following our PHP migration checklist.
The official documentation
The technical details and the workaround settings are published in the PHP security advisory and in the GitHub advisories GHSA-w8hw-w9fx-j79w (CVE-2026-109618) and GHSA-6wmf-4rv5-p3rp (CVE-2026-109619). For distribution packages, see the Ubuntu announcement and the AlmaLinux one.