PHP2Shell: how to check and protect your website

Two PHP flaws fixed on 21 October 2026 let an attacker run code on a web server without logging in. How to find out whether your site is exposed, and what to do today.

11 min readSources checked

On 21 October 2026 the PHP project released fixes for two vulnerabilities, CVE-2026-109618 and CVE-2026-109619, that researchers have named PHP2Shell. Both can let someone with no login run their own code on a web server that serves PHP, which is the server behind most WordPress, WooCommerce, Magento and Drupal sites. The fixed versions are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. If your site runs one of those or newer, and the PHP workers have been restarted since the update, the rest of this article is a checklist for confirming it.

If you do not know which PHP version your site runs, that is the first thing to find out, and step 1 below shows how.

What was fixed on 21 October

The PHP project rates both flaws 9.2 out of 10 on CVSS version 4.0, its critical band. Some early reports quoted 10.0; the PHP Foundation has said the identifiers that circulated before the release carried that score in error. The flaws were found in August by researchers at Wiz and at Calif, a security firm. Wiz says it reported them to PHP on 24 August, and that the oldest affected code dates back to PHP 5.4.

There are no complete mitigations, updating is the only safe choice.

PHP security advisory, 21 October 2026

The full advisory, with the interim settings quoted later in this article, is on php.net.

How the two flaws work

Neither bug is in your website's code. Both sit in how PHP itself recovers when a request goes wrong, and both turn on one fact about how PHP serves traffic: the same worker process handles one request after another.

  • CVE-2026-109618, out-of-memory corruption. When PHP runs out of memory partway through setting up a request, it can stop while some of its internal data is only half built. The clean-up that follows treats that half-built data as valid. A crafted upload can push PHP into that state on purpose.
  • CVE-2026-109619, stale state between requests. Some of PHP's internal bookkeeping can outlive the memory it points at. The next request handled by the same worker can then read memory that has since been reused, and an attacker who controls that next request controls what is there.

The part that matters for a site owner: on the most exposed setups the attack lands before your application has run a single line. Updating WordPress, a plugin, Magento or an extension does nothing for this. The fix is a new PHP build on the server.

Which servers are exposed

The PHP advisory says every installation that serves web requests is at risk, and names the ways PHP is commonly connected to a web server: PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. It does not rate them equally.

SetupWhat the advisory reportsHow to tell you have it
Apache with mod_phpHighest risk. A demonstrated exploit runs from one unauthenticated request, before any application code.Apache lists a PHP module (command in step 1)
PHP-FPMHarder to exploit, not safe. PHP-FPM kills a worker whose request startup fails, which blocks the first flaw's main route; the second flaw has a confirmed route through session upload progress, which is switched on by default.A php-fpm service is running on the server
LiteSpeed, php-cgi, FrankenPHPNamed as at risk; no separate rating given.Your host names it, or responses carry a LiteSpeed server header
Risk by setup, from the PHP advisory of 21 October 2026 and Rapid7's analysis of it. "Worker" means one PHP process, which handles many requests in turn.

Version matters as much as setup. Only the four current branches get official fixed releases. PHP 7.4, 8.0 and 8.1 get source patches that someone has to build. PHP 7.3 and everything older back to 5.4 gets nothing from the PHP project.

That last group is not small. On 4 November 2026, W3Techs measured PHP on 69.1% of websites whose server-side language it could identify, and of those PHP sites, 26.2% were on PHP 7 and 7.6% on PHP 5. Added together, 33.8% of PHP sites run a major version for which the PHP project ships no fixed release.

What has been seen in the wild

The picture on 4 November is of heavy probing, confirmed compromises of internet-facing firewalls, and no evidence of a mass wave against ordinary websites. The people closest to it still read the risk differently.

Amazon's threat intelligence team reported an exploitation attempt against its honeypots on 17 October, four days before the fixes were public, and further attempts from several different sources in the early hours of 21 October. It describes PHP2Shell as now broadly exploited, and also says it is unclear whether any of those attempts would have worked against a real system. A honeypot records an attempt. It does not show a break-in.

Cloudflare says it saw attack traffic aimed at its customers once details leaked, including attackers changing their payloads to get past its rules. The PHP Foundation said its security team examined the exploit code that appeared after the leak and found none of it working at the time of release. Sansec, which specialises in ecommerce security, went further: in its analysis the public exploits do not work against a default PHP installation, mass exploitation looks less likely than it first expected, and stores do not need to go offline.

Government advice is more cautious. The UK's National Cyber Security Centre tells organisations to find every system running PHP, internet-facing ones first, update them, and to consider taking a system offline if it can be neither updated nor mitigated quickly. CERT-EU has given similar advice. CISA added both CVEs to its Known Exploited Vulnerabilities catalogue on 26 October, the list of flaws it has evidence are being exploited.

The numbers since then are mostly attempts. Zscaler counted 1,156 exploitation attempts from 156 attacker IP addresses against 70 organisations in the first 48 hours after disclosure, on decoy systems it runs. On 30 October Hunt.io reported the first confirmed production compromises: internet-facing Palo Alto firewalls, rooted. Shells have otherwise been confirmed only on honeypots and sensors, and Hunt.io says there is still no evidence of reliable mass compromise on the open internet.

Step 1: find the PHP version your site runs

On managed or shared hosting, the control panel shows it. In cPanel it is under MultiPHP Manager or Select PHP Version; in Plesk, under the domain's PHP settings. Note the exact version, including the last number, for every site you have. If the panel lets you pick a PHP version per site, check each one: a host can patch its default version while a site pinned to an older one stays behind.

On your own server, beware of one trap. The version that the php -v command prints in a terminal can belong to a different installation from the one serving web pages; Qualys flags this in its guidance. Ask the web-facing PHP directly, and check the package changelog rather than the version number, because Linux distributions often patch a package without changing its upstream version.

# Debian / Ubuntu: does the installed PHP package include the fix?
zgrep -l CVE-2026-109618 /usr/share/doc/php*/changelog.Debian.gz

# Red Hat, AlmaLinux, Rocky
rpm -q --changelog php-fpm | grep CVE-2026-109618

# The FPM binary's own version (name varies: php-fpm on Red Hat)
php-fpm8.3 -v

# Is Apache loading mod_php? Any output means yes.
apachectl -M 2>/dev/null | grep -i php
A changelog match means the package is fixed. No match means it is not, whatever the version number says.

Step 2: update PHP

On managed hosting this is your host's job. Do not assume it has been done. Ask in writing, and ask a question that cannot be answered vaguely:

Is the PHP serving my site a build that includes the fixes for CVE-2026-109618 and CVE-2026-109619, and have its workers been restarted since it was installed?

The question to send your host

On your own server, install your distribution's updated packages, then restart PHP. The restart is not optional. A worker started before the update keeps running the old code in memory, and these flaws live in exactly those long-running workers.

# PHP-FPM (Debian/Ubuntu naming; php-fpm on Red Hat)
sudo systemctl restart php8.3-fpm

# mod_php: PHP lives inside Apache, so restart Apache (httpd on Red Hat)
sudo systemctl restart apache2

If you run PHP in Docker, rebuild from a fixed base image and redeploy; restarting an old container changes nothing. Sansec notes the official PHP image on Docker Hub gets no fix for 8.1 or older. Then run the checks from step 1 again against what is running.

Step 3: interim measures if you cannot update today

Everything in this section reduces exposure. None of it removes it, and the PHP advisory says so in as many words. Use these to buy hours, not weeks.

Put the site behind a web application firewall

Cloudflare switched on rules for PHP2Shell at 03:02 UTC on 21 October, before the fixes were public, on every plan including the free one, with nothing for the customer to enable. On paid plans, check that the Cloudflare Managed Ruleset is set to block rather than log. This only protects traffic that goes through Cloudflare, so it does nothing if your server can also be reached directly by its IP address.

Change three PHP settings

The PHP advisory lists settings that block the attack routes confirmed so far. They must go in php.ini or the PHP-FPM pool file, which take effect before PHP reads the request. Setting them from code with ini_set(), or in a .user.ini file, is too late.

; php.ini or the PHP-FPM pool file. Then restart every worker.
session.upload_progress.enabled = 0
fatal_error_backtraces = 0     ; PHP 8.5 only
post_max_size = 8M             ; 32M if the site takes uploads
Keep upload_max_filesize below post_max_size. Turning session upload progress off only affects upload progress bars that read PHP's session data.

On 23 October the PHP project added a notice about the first of those settings. It suggests keeping session upload progress off until the next regular bugfix release, because of a third issue, CVE-2026-115560, which only occurs when an application switches its session serializer at runtime. PHP calls that setup unlikely, and says applications that never do it can keep the feature on. If you already turned it off, leave it off.

The advisory also suggests removing the memory limit, so PHP never hits the out-of-memory path the first flaw needs. It has a cost: with no limit, a single request can use all of the server's memory and take the site down by itself. If you use it, set it so applications cannot override it, and put the limit back after updating.

; PHP-FPM pool file. Applications cannot override php_admin_value.
php_admin_value[memory_limit] = -1

For PHP-FPM, Qualys also suggests pm.max_requests = 1, which retires each worker after a single request so no request can inherit another's leftover state. Every request then pays for starting a fresh worker, so expect the site to slow down under load.

Block file-upload requests at the web server

Most of the attack routes confirmed so far start with a multipart request, the format browsers use for file uploads. Amazon and Sansec both suggest refusing them before PHP sees them. Sansec's rules:

# Nginx: in each server block that passes requests to PHP
if ($http_content_type ~* "multipart/form-data") {
    return 403;
}

# Apache: in each VirtualHost that serves PHP
RewriteEngine On
RewriteCond %{HTTP:Content-Type} multipart/form-data [NC]
RewriteRule ^ - [F]
This breaks every upload form, including product images in your admin. Some checkouts submit as multipart too, so place a test order straight after adding it.

If none of this can be applied and the server cannot be updated, the NCSC's advice is to consider taking the site offline until it can. Sansec, looking specifically at online stores, does not think that is necessary. The deciding question is whether the server runs mod_php or an unsupported PHP version: those two are where the confirmed routes are shortest and where no fix is coming.

Step 4: check whether anyone got in

Amazon recommends looking back to 17 October, the earliest attempt it recorded, not to the date the fixes came out. The signals researchers have published:

  • POST requests whose body contains PHP_SESSION_UPLOAD_PROGRESS, the request pattern Amazon saw. Ordinary access logs do not store request bodies, so this check needs firewall logs or body logging. Cloudflare customers can see matches in the security events for the rules above.
  • Out-of-memory errors right after unusual uploads, repeated 500 errors, unexplained PHP worker restarts, and unusually large PHPSESSID cookies in responses. These are the signals Wiz published; the cookie one matters because one of the bugs leaks server memory into it.
  • New or changed files and unexpected processes on the server, the classic sign that someone has left a way back in.
# PHP out-of-memory errors (log paths vary by server)
grep -h "Allowed memory size" /var/log/php*-fpm.log /var/log/apache2/error.log 2>/dev/null

# PHP files created or changed under the web root since 17 October
find /var/www -type f -name '*.php' -newermt 2026-10-17
Plugin and core updates since 17 October will show up in the second list too. Look for names and locations that do not belong to anything you installed.

Rapid7 makes the point that matters most here: an empty log is not proof of safety, because these bugs act below the level most logging sees. If you do find something, treat the server as compromised. Rebuild it from a backup taken before 17 October rather than cleaning it in place, and change every secret the site holds: database passwords, payment and shipping API keys, and admin passwords. Wiz showed the flaws can leak server memory, and memory is where those secrets sit while the site runs. The NCSC recommends an assured incident response provider if you do not have the skills in-house.

Sites on PHP 8.1 or older

There is no official update to install. PHP 7.4, 8.0 and 8.1 have source patches that a developer can build, and some Linux distributions and long-term support vendors ship patched packages, so check yours first. PHP 7.3 and older have nothing. For those sites the real fix is a move to a supported version, which is a development job rather than a setting, because older plugins and themes often break on newer PHP. Until it is done, the interim measures in step 3 are carrying all of the weight.

Plan the move to PHP 8.3 or newer while you are at it. The PHP project ends security support for PHP 8.2 on 31 December 2026, so a site moved to 8.2 today faces this same question again in eight weeks.

What to change after this

Amazon's first recorded attempt came four days before the fixes were public, and it reports new proof-of-concept code being used against its sensors within hours of appearing. Three habits close most of that gap for next time.

  1. Know your PHP version for every site, and keep the list current. Step 1 above is the one part of this response you can finish before the next advisory arrives.
  2. Stay on a supported PHP branch. A third of PHP sites are on versions that receive no fix at all, and those are the ones still exposed after the patches ship.
  3. Keep a web application firewall in front of the site. Cloudflare's free plan had rules in place before the fixes were published. It did not fix anything, and it bought time.

One structural point, for pages that do not need it: a page that is built in advance and served as a static file has no PHP running when a visitor requests it, so there is nothing for an attack like this to reach. This site ran on WordPress until August 2026 and is now built in advance and served as static files, so on 21 October it had no PHP to patch. A checkout, an account area or a CMS admin still needs a server-side language. A brochure page, a blog or a landing page usually does not.

This is what we do. Ecommerce web development

Want this done properly?

The first consultation is free, and there are no charges for the first month.