Skip to content
Katio TechBlog

Software and web

PHP2Shell: Who needs to act and how to check the update

The critical PHP vulnerabilities of October 2026: what the hosting provider takes care of, what server operators have to do themselves, and why the version number on Ubuntu stays the same after the update.

Paul-Harald KatioUpdated 10 min read

WordPress and every plugin are up to date, yet the website can still be attacked through the PHP it runs on. On October 21, 2026, the PHP project closed two critical security vulnerabilities known as PHP2Shell (CVE-2026-109618 and CVE-2026-109619). They let someone run their own code on a web server without logging in. Every server that delivers web pages with an unpatched PHP version is affected, whether it runs WordPress, Joomla, Drupal, or Shopware.

Contents

The short answer

Updating WordPress, plugins, or themes won’t help here. The vulnerabilities can only be closed by updating PHP itself: to 8.5.12, 8.4.27, 8.3.36, or 8.2.35, or to a Linux distribution package that contains the fix. On a web hosting plan, the hosting provider installs the update; on a self-managed server, whoever runs it does. After that, every PHP process has to restart. The PHP project no longer provides updates for PHP 8.1 and older.

Attack attempts have been seen since October 21, and Germany’s Federal Office for Information Security (BSI) says action is needed immediately.

Quick test: does the website run on PHP?

The quick test fetches a website once and uses headers, cookies, and other public clues to tell whether it runs on PHP and with what, such as WordPress, Joomla, or Shopware. It reports the exact version if the server shows it in a header.

PHP detection

Reads headers, cookies, and public page features, the way a browser does. No security scan, no active test.

The result is only a clue. Often the version number stays hidden, and even a visible one says nothing about the patch on its own: Ubuntu, for example, keeps the same number after the fix. The only reliable check happens on the server itself, as described in How to check whether the update took effect.

Who needs to act: hosting provider, server operator, or manufacturer

Web hosting plan: the hosting provider installs the update

On shared hosting, the provider runs PHP, and only the provider can update it. The provider’s status page shows whether that has happened; otherwise, ask support.

The status page is the fastest place to look. IONOS, Hetzner, and Mittwald posted their progress there with timestamps, Strato in its help pages. The all-clear covers web hosting only, not VPS, and not always every old PHP version: Mittwald excluded versions below 5.6.

Customers who still have PHP 8.1 or older selected in the control panel have to act themselves. Those versions are only protected if the hosting provider patched them on its own. Switching to 8.3 or newer is safer. It pays to test first, ideally on a copy of the website, because older plugins and themes can throw errors on a newer PHP version.

Going by the PHP project’s lists of changes, I would expect warnings rather than a broken site when moving from 8.1 to 8.3, most likely about dynamic properties, which PHP has flagged as deprecated since 8.2. In WordPress, WP_DEBUG and WP_DEBUG_LOG in wp-config.php write these messages to wp-content/debug.log along with the file path, which points to the plugin or theme behind them. That belongs on the copy, not on the live site.

Treat emails that push an urgent PHP update with a link or attachment with suspicion. Real updates come through the hosting provider or the operating system’s package repositories.

For the website from the introduction, that leaves two things: ask the hosting provider, and check the PHP version in the control panel.

Self-managed server or VPS: the operator installs the update

Anyone who manages a server, whether rented or on premises, installs the update themselves. On Ubuntu and Debian it comes through the regular security repositories; on Ubuntu 20.04, only with Ubuntu Pro. For a managed server, the contract determines whether the provider maintains the operating system. When in doubt, ask.

Containers: rebuild the image

A container image ships its own PHP, so updating the host changes nothing inside it. The image has to be rebuilt on a current base image and redeployed. The official PHP images on Docker Hub are available in the fixed versions, such as php:8.4.27-fpm. A Dockerfile pinned to an older version like php:8.4.26-apache needs to be bumped.

Devices and software with built-in PHP: up to the manufacturer

PHP also runs inside finished products, such as the admin interfaces of network equipment or applications that ship with their own PHP. Only the manufacturer can update those. Until then, such interfaces should not be reachable from the internet. According to the BSI, network equipment manufacturers are publishing their own advisories, and the Dutch NCSC keeps a list of affected and unaffected products on GitHub.

What makes PHP2Shell dangerous

Both vulnerabilities allow remote code execution: an attacker sends a crafted request to the web server and gets PHP to run their commands, with the permissions of the user account PHP runs under. That is enough to change the website’s files, read credentials from its configuration, or download further programs. Even without running code, an attacker could read memory holding passwords, tokens, and API keys from other requests. The PHP project rates both vulnerabilities 9.2 out of 10 under CVSS 4.0.

Servers where PHP runs as a module inside the Apache web server (mod_php) are most at risk. On those, the PHP project reproduced a complete attack over the network that works before the application has run a single line of its own code. An attack has also been demonstrated against PHP-FPM, the common setup with separate PHP processes behind Nginx or Apache. Wiz, one of the teams that found the vulnerabilities, writes that even a plain “Hello World” application can be vulnerable.

The details were scheduled for October 22. Because the CVE numbers and a video showing an attack were already circulating online on October 20, the PHP project released the updates a day early. watchTowr and Cloudflare have reported attack attempts since October 21. The US agency CISA had not yet seen successful exploitation when it issued its first warning. Since October 26, it has listed CVE-2026-109618 and CVE-2026-109619 in its Known Exploited Vulnerabilities catalog, which means it has reliable evidence that both are being exploited. The BSI has issued a cybersecurity warning.

Technically, the first vulnerability (CVE-2026-109618) occurs when PHP runs out of memory while setting up a request: internal data is left half built, and the cleanup at the end of the request treats it as valid. In the second (CVE-2026-109619), leftovers from one request stay behind in a PHP process that handles many requests in a row, and they point to memory that has already been freed.

Which versions contain the fix

PHP branch Fixed version Security updates until
8.5 8.5.12 Dec 31, 2029
8.4 8.4.27 Dec 31, 2028
8.3 8.3.36 Dec 31, 2027
8.2 8.2.35 Dec 31, 2026
8.1 and older none ended

Because the vulnerabilities are so severe, the PHP security team published only minimal source code fixes for 7.4, 8.0, and 8.1. They are meant for people who compile PHP themselves and are not a ready-made update. Anyone running one of these branches needs a package from their distribution or from a vendor with extended support, or a move to a supported branch. Since 8.2 reaches end of life at the end of 2026, 8.3 or newer is the better choice.

Linux distributions often keep their own version number and backport only the fix. What counts then is the package version (as of October 26, 2026):

System Package Fixed version
Ubuntu 26.04 LTS php8.5 8.5.4-0ubuntu1.5
Ubuntu 24.04 LTS php8.3 8.3.6-0ubuntu0.24.04.13
Ubuntu 22.04 LTS php8.1 8.1.2-1ubuntu2.28
Ubuntu 20.04 LTS php7.4 7.4.3-4ubuntu2.29+esm5, Ubuntu Pro only
Debian 13 php8.4 8.4.27-1~deb13u1
Debian 12 php8.2 8.2.35-1~deb12u1

How to check whether the update took effect

On Ubuntu, the version number doesn’t reveal whether the fix is installed. php -v shows “PHP 8.3.6” before and after the update, and so does the website, because Ubuntu backports the fix into the existing version instead of moving to 8.3.36. Debian ships the PHP project’s versions here (8.4.27 and 8.2.35), so on Debian the number is accurate.

The procedure below therefore checks the packages themselves. It was tested on October 26, 2026, in a freshly installed Ubuntu 24.04 VM with Apache and mod_php as well as PHP-FPM: first with the unpatched package 8.3.6-0maysync1 that Ubuntu 24.04 shipped with at release, then with the update 8.3.6-0ubuntu0.24.04.13.

  1. List the installed PHP packages

    This command lists every installed package with “php” in its name, along with its version. Compare the versions with the table above.

    dpkg -l '*php*' | awk '/^ii/ {print $2, $3}'
  2. Search the changelog for the vulnerability

    Ubuntu and Debian record fixed vulnerabilities in the package changelog. The command counts how often the identifier appears there; 0 means the fix is missing. In the test, the count was 0 before the update and 2 after it. Adjust the version number in the path to match the installed one, for example php8.4-common.

    zgrep -c CVE-2026-109618 /usr/share/doc/php8.3-common/changelog.Debian.gz
  3. Find every PHP version on the server

    php -v only shows the version used on the command line. If several versions are installed, the website may be using a different one. These two commands show the running FPM services and any PHP module loaded in Apache. Every version they turn up needs the update.

    systemctl list-units --type=service 'php*-fpm*'
    ls /etc/apache2/mods-enabled/ | grep php
  4. Check that everything has restarted

    Running processes keep using the code they loaded when they started. In the test, the package manager restarted Apache and PHP-FPM on its own during the update. If that didn’t happen, for instance because restarts were suppressed during the update, needrestart lists the affected services, in the test “apache2.service” and “php8.3-fpm.service”. The tool comes preinstalled on Ubuntu Server and can be added on Debian. Restarting the listed services fixes it.

    sudo needrestart -r l
    sudo systemctl restart apache2 php8.3-fpm

If the first step still shows the old package version after the update, a setting may be holding the update back. The package manager doesn’t upgrade packages pinned with apt-mark hold, and apt-mark showhold lists them. Ubuntu’s automatic updates also skip anything listed under Package-Blacklist in /etc/apt/apt.conf.d/50unattended-upgrades.

When the update can’t happen right away

According to the PHP project, no setting closes the vulnerabilities completely. If a server can’t be updated soon, or runs PHP 8.1 or older, CISA advises taking it offline until then. Whether that is acceptable for an online store or a customer portal is for management to decide.

If the server stays online, these measures block known attack paths, but they only reduce the risk:

  • session.upload_progress.enabled = 0 turns off progress tracking for file uploads, which is on by default. The PHP project recommends leaving it off after the update as well if the application doesn’t need it.
  • On PHP 8.5, also set fatal_error_backtraces = 0.
  • Keep post_max_size small: 8M for applications without file uploads, 32M with uploads, and upload_max_filesize below that in either case.
  • A web application firewall (WAF) in front of the website filters out known attack patterns. Cloudflare has turned on rules for this on every plan that includes a WAF, the free plan among them; on paid plans, the managed ruleset should be set to block.

The PHP project also mentions memory_limit = -1. Without a memory limit, though, a single request can take up all of the server’s RAM, so the project also recommends a limit at the container or cgroup level. That is more a job for experienced administrators.

The settings belong in the php.ini that the web server reads, or in the FPM pool configuration. Set in .user.ini or with ini_set() in code, they take effect too late. On Ubuntu and Debian, each way of running PHP has its own files. In the test, the website reported the value 0 for Apache after the change, while php -i on the command line still showed “On”, because the command line reads its own configuration.

/etc/php/8.3/apache2/conf.d/99-php2shell.ini
session.upload_progress.enabled = 0

For PHP-FPM, the file goes in /etc/php/8.3/fpm/conf.d/. Then restart Apache or PHP-FPM.

The third vulnerability (CVE-2026-115560): the same setting helps

On October 23, the PHP project disclosed another vulnerability. Anyone who has already set session.upload_progress.enabled = 0 from the previous section has nothing more to do. This one is also in upload progress tracking, and according to Cloudflare it affects the newly fixed versions such as 8.5.12 too. It can only be exploited with an unusual combination: the application sets session.serialize_handler to php_binary or php_serialize in its configuration and then switches it to php in code before session_start(). The PHP project considers this unlikely. It will close the vulnerability in the next regular release and recommends exactly this setting until then.

If the server may already have been compromised

The update closes the vulnerabilities, but it doesn’t remove anything an attacker placed on the server before. For publicly reachable servers that were still unpatched after October 20, it’s worth checking for the signs that security firms and authorities describe:

  • PHP or web server processes that launch a shell, a script interpreter, or tools such as curl and wget
  • new or modified PHP files in the website’s directory, new cron jobs, or new user accounts
  • clusters of status 500 errors and out-of-memory messages in the logs

This command finds PHP files changed since October 20; the path is the default on Ubuntu and Debian. A match isn’t automatically suspicious, since updates to WordPress or plugins change files too.

sudo find /var/www -name '*.php' -newermt 2026-10-20 -ls

If a server sat unpatched on the internet for days after October 21, the credentials in the website’s configuration should be replaced, such as the database password: the vulnerabilities also allowed reading memory that contained passwords.

If there are traces of an attack, the server should go offline. The logs should be preserved, and the cleanup is best left to incident response specialists. If personal data was accessible, such as an online store’s customer records, a report to the data protection authority may be required: under Art. 33 GDPR within 72 hours of becoming aware of the breach, unless it is unlikely to result in a risk to the people affected.

Sources33

Further reading

More articles

Request an intro call