# Critical PHP Vulnerability (PHP2Shell): What to Do Today to Protect Your Sites
Table of Contents
On 21 October 2026 the PHP security team released emergency updates for two critical vulnerabilities, rated 9.2 out of 10: CVE-2026-109618 and CVE-2026-109619, nicknamed PHP2Shell. According to the official advisory they can let anyone, with no password and no account, run commands on the server that runs PHP. They are not flaws in WordPress, PrestaShop or some plugin: they sit in the interpreter, the program that executes PHP code, so they affect any site or business application running on top of it.
If you run a site, an online shop or a management application written in PHP, there are three things to do today: find out which version it runs on, update it, and check that the update really landed. The UK National Cyber Security Centre (NCSC) has urged organisations to act immediately and, for systems that cannot be fixed, to consider taking them offline for now.
Below: what is happening, who is exposed, what to do and in which order, how to reduce the risk if you cannot update today, and how to tell whether someone is already inside. The information comes from the PHP project’s advisory, the two advisories published on GitHub, the report by Wiz Research, which found the flaws, and the NCSC, all linked at the bottom. Things are moving fast: this text is a snapshot of 18:00 CEST (16:00 UTC) on 21 October.
What was found: two flaws in how PHP handles out-of-memory errors
Both stem from what happens when a web request dies badly, in particular when PHP runs out of the memory it was allowed while it is still setting the request up.
- CVE-2026-109618, memory corruption on memory exhaustion: if memory runs out at the wrong moment, PHP aborts the request with an emergency exit and leaves some internal data half-built. The end-of-request cleanup treats it as if it were in order and works on it. It is like a warehouse worker who finds an order only half packed, closes it as complete and starts touching shelves that do not exist.
- CVE-2026-109619, leftover state between one request and the next: a PHP worker, the process that serves requests and is reused for thousands of visitors, can keep references to memory from the previous request that has already been freed. The next request uses them before they are reset. It is a whiteboard the previous customer did not wipe, which the next one reads and writes thinking it is blank.
With the right sequence of requests an attacker can read parts of the server’s memory and end up running code with the web server’s privileges. The attack goes in particular through multipart HTTP requests (the kind used by forms with file uploads), needs no login and does not depend on the application: Wiz demonstrated unauthenticated code execution against the latest WordPress, Drupal and Joomla images, and the PHP project reports a full demonstration against Apache with mod_php and default settings.
A note on tone: the official score lists the attack complexity as high and, according to Wiz, full code execution requires chaining several defects and adapting to the target’s memory layout. It is not within everyone’s reach, but the demonstration exists, and Wiz, which says it used AI models in its research, argues that this very adaptation work is what AI makes cheaper.
The timeline: reported to the PHP team on 24 August, acknowledged on 21 September, on 20 October the identifiers of the flaws leaked online and PHP announced an emergency release, and the fixes shipped on 21 October.
Who is exposed and which versions are fixed
The versions that fix both flaws are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. The project lists installations that serve web requests as at risk: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed, with the highest risk for mod_php. Command-line scripts alone are not the case described, but they get updated along with everything else.
Old versions are the sore point. PHP 8.1 and earlier no longer get updates from the project, and Wiz estimates that every version back to 5.4 is hit by at least one of the two flaws. For PHP 7.4, 8.0 and 8.1 minimal source-code fixes were published, useful to those who build PHP themselves; Linux distributions and extended-support (LTS) vendors received the patches in advance. It is the scenario we describe in PHP end of life: on an abandoned version every new flaw stays open, unless someone fixes it for you.
It is not only about the website. PHP also runs inside control panels, management software, appliances and products that bundle it: the NCSC asks you to inventory these too and to follow vendors’ updates. On shared hosting the provider does the update, and it makes sense to ask them for written confirmation rather than assume.
What to do now: update, restart, verify
- Inventory: list where PHP runs (servers, hosting, containers, panels, software that bundles PHP) and start with whatever is reachable from the internet. Do not limit yourself to old systems: the NCSC asks for that too.
- Backup: before touching anything, a verified copy. These are maintenance updates and the risk of breakage is low, but the rule always applies.
- Update: on a server using the distribution’s PHP packages, then restart the services, because workers that are already running keep the old code in memory:
sudo apt update && sudo apt upgradesudo systemctl restart php8.3-fpmThe service name depends on the version (php8.4-fpm, php8.2-fpm); with Apache and mod_php you restart apache2. On Red Hat family distributions the command is dnf upgrade, but anyone using the third-party Remi repository should know that on 21 October it had no updated packages yet: the suggested route is to switch to the distribution’s packages or build from source.
- Real verification: the number shown by
php -vis not enough on its own. Debian published the fix under the new number (on Debian 12 the fixed package is8.2.35-1~deb12u1), while Ubuntu backported it onto the version it already shipped: on Ubuntu 24.04 the fix is in package8.3.6-0ubuntu0.24.04.13, sophp -vshows 8.3.6, a number that looks older than the fixed 8.3.36, and yet the system is fine. In both cases what works is the changelog of the installed package, which cites the CVEs:
zcat /usr/share/doc/php8.3-fpm/changelog.Debian.gz | grep -m2 'CVE-2026-10961[89]'For the official php: Docker images and for installations built from source the opposite holds: the version number is the real one and must be at least one of the fixed ones. For containers, rebuild with docker build --pull and check the version inside the image with docker run --rm <image> php -v.
If you cannot update today: temporary mitigations (and their limits)
The PHP project is blunt: these measures do not make an installation safe. They reduce the attack surface, they do not fix anything, and they buy you a few hours. In the PHP-FPM pool (on Debian and Ubuntu, /etc/php/8.3/fpm/pool.d/www.conf):
php_admin_value[memory_limit] = -1php_admin_value[post_max_size] = 8Mphp_admin_value[session.upload_progress.enabled] = 0; PHP 8.5 onlyphp_admin_value[fatal_error_backtraces] = 0After the change, restart all workers. What each line does:
memory_limit = -1looks absurd, but the first flaw is triggered precisely when PHP hits its memory limit. The price is that a runaway script can eat all the RAM: the ceiling must be set upstream, with container or cgroup limits, and not withRLIMIT_ASorRLIMIT_DATA, which cause the very error you are trying to avoid. It is set withphp_admin_value, which applications cannot override, checking that no pool or directory puts a limit back.post_max_size = 8Mcaps the size of requests (32M if you need file uploads, keepingupload_max_filesizelower). With 8M every bigger upload stops working.session.upload_progress.enabled = 0turns off the upload progress bar, the feature used by the second flaw. It must be set in the server or pool configuration, not withini_set()or.user.ini, which arrive too late. The project recommends keeping it off after the update too, if you do not need it.fatal_error_backtraces = 0closes only one of the known paths, and exists only from PHP 8.5.
In front of the application, a reverse proxy can enforce limits on request size and, for sites with no upload forms, block multipart requests altogether. Cloudflare has switched on WAF rules for the known vectors, even on free plans: they only help if the server accepts traffic exclusively from Cloudflare, and Patchstack considers them a stopgap. If none of these measures is practical and the system is exposed, the NCSC suggests taking it offline until it is updated.
How to tell whether someone is already inside
Updating closes the door but does not throw out whoever is already in. The flaws act below the application layer, so the site’s logs may show almost nothing. The signs pointed out by Wiz and Huntress:
- unusual multipart requests followed by out-of-memory errors or runs of HTTP 500 responses;
- anomalous
PHPSESSIDcookies, very large or malformed, in responses; - unexplained restarts of PHP workers;
- web server processes (
php-fpm,apache2,httpd) launching shells, download tools such ascurlorwget, or reconnaissance commands such aswhoami,id,uname -a.
On disk, look for new or modified PHP files and scheduled tasks nobody created:
find /var/www -name '*.php' -mtime -3 -lscrontab -l -u www-dataThe web server user is www-data on Debian and Ubuntu, apache or nginx elsewhere. If you find something: isolate the server, keep the logs and do not just clean up. One of the flaws allows reading worker memory, so on a compromised server, or even a suspected one, the secrets the application held in memory should be treated as exposed: database passwords, API keys, session and encryption keys. Wiz advises considering rotating them. If the server handles personal data and there is a risk to individuals, the breach must be notified to the data protection authority without undue delay and, where feasible, within 72 hours: we cover it in GDPR from the infrastructure side.
Is it already being exploited? The sources disagree
At 14:00 UTC on 21 October Huntress stated it had not observed exploitation among its partners and knew of no public attack code (a short demonstration video had been posted and then removed). In the same hours Patchstack was receiving incident reports from hosting partners, but its own telemetry showed only probing attempts; Cloudflare’s CTO spoke of early attacks and watchTowr claimed attempts against its own honeypots. None of these sources is conclusive on its own.
The prudent reading is to treat exploitation as imminent: with the details public and a working demonstration out there, the window before mass automated attacks is measured in hours or a few days.
In short
Two critical flaws in the core of PHP, CVE-2026-109618 and CVE-2026-109619, allow, according to the project, running code on the server without authentication. They are fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, and by distributions in their own packages. You inventory, update, restart the workers and check the changelog rather than the version number. Where that is not possible, temporary mitigations reduce the attack surface but fix nothing, and an end-of-life PHP should be taken off the internet or migrated. After updating, look for traces of access and, when in doubt, change the secrets.
Sources
- PHP.net, security advisory “Critical remote code execution vulnerabilities, update now” (21 October 2026)
- PHP, advisory GHSA-w8hw-w9fx-j79w for CVE-2026-109618
- PHP, advisory GHSA-6wmf-4rv5-p3rp for CVE-2026-109619
- Wiz Research, PHP2Shell: technical report on the discovery
- NCSC, “Critical security issue affecting PHP” (21 October 2026)
- Patchstack, advisory and live updates on the PHP vulnerability
- Huntress, Rapid Response: php2shell
- Ubuntu, fixed packages for CVE-2026-109618
- Debian Security Tracker, CVE-2026-109618
