PHP2Shell (CVE-2026-109618 and CVE-2026-109619): What It Is and How to Patch and Protect Your Servers

Two critical PHP vulnerabilities, nicknamed PHP2Shell, can allow unauthenticated remote code execution. Here is what is affected, how to patch every common setup, what to do if you cannot patch today, and how to check for compromise.

On 21 October 2026 the PHP project released emergency security updates for two critical vulnerabilities that can allow unauthenticated remote code execution (RCE). The issues have been nicknamed PHP2Shell and are tracked as CVE-2026-109618 and CVE-2026-109619. Both are rated CVSS v4.0 9.2 (Critical).

Security researchers at watchTowr report that they are already seeing active exploitation attempts, and the UK’s National Cyber Security Centre (NCSC) has issued an alert. If you run WordPress, WooCommerce, Magento, Drupal, Laravel or any other PHP application, treat this as an emergency.

This guide explains what is affected and gives step-by-step instructions for patching the most common setups. It also covers what to do if you cannot patch today and how to check whether a server was compromised.

Short version: update PHP to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 (or your distribution’s patched package), then restart every PHP worker. Configuration changes alone do not make a server safe.

What is PHP2Shell?

PHP2Shell is the name for two related memory-safety bugs in the PHP engine. Both are fixed in the same releases.

CVE-2026-109618 CVE-2026-109619
PHP name RCE via OOM corruption RCE via stale global state
Advisory GHSA-w8hw-w9fx-j79w GHSA-6wmf-4rv5-p3rp
Severity CVSS v4.0 9.2, Critical CVSS v4.0 9.2, Critical
High-level cause Out-of-memory handling can interrupt PHP while internal request data is only partly initialized, and request cleanup may then treat that invalid data as valid Internal state belonging to one request can survive after its memory is freed, and a later request handled by the same worker may use it (use-after-free)
Result Possible remote code execution with the web server/worker’s privileges Possible remote code execution with the web server/worker’s privileges

The important part for site owners: these bugs live in PHP itself, not in WordPress, Magento or your plugins. PHP processes the attacker’s request, so even a fully updated application is exposed if the PHP runtime underneath is vulnerable. According to the PHP advisory, an exploit was demonstrated against Apache mod_php in which an unauthenticated request triggers the attack before any application code runs.

Which versions are affected?

PHP branch Vulnerable Fixed in
8.5 before 8.5.12 8.5.12
8.4 before 8.4.27 8.4.27
8.3 before 8.3.36 8.3.36
8.2 before 8.2.35 8.2.35
8.1, 8.0, 7.4 Yes No official release. Minimal source backports from the PHP security team, or vendor/LTS backports
Older (7.3 and below, 5.x) Assume yes No fix. Upgrade

Note that PHP 8.2 reaches end of life on 31 December 2026, so plan an upgrade to 8.4 or 8.5 after patching.

Which setups are at risk?

According to the PHP advisory, all PHP installations serving web requests are at risk. This includes:

  • Apache with mod_php: highest risk, with a demonstrated pre-application exploit
  • PHP-FPM (Nginx, Apache with proxy_fcgi, Caddy and others)
  • php-cgi
  • FrankenPHP
  • LiteSpeed (LSAPI)

Shared hosting, managed WordPress hosting, VPSs, containers and Windows servers are all in scope if they run a vulnerable PHP version for web requests.

Step 1: Find every PHP installation

You cannot patch what you do not know about. Make a list of all servers, containers and hosting accounts running PHP, starting with internet-facing ones.

Check the PHP version on the command line:

php -v

The CLI version can differ from the version serving your website. Also check the web server’s PHP:

  • PHP-FPM: php-fpm8.3 -v (Debian/Ubuntu naming), or php-fpm -v
  • List installed PHP packages (Debian/Ubuntu): dpkg -l | grep -E '^ii\s+php'
  • List installed PHP packages (RHEL/Alma/Rocky): rpm -qa | grep -i php
  • In WordPress: Tools → Site Health → Info → Server shows the PHP version used by the site
  • In Magento: check with your host or on the server, since several PHP versions are often installed side by side

Do not forget staging servers, old test sites, internal tools, monitoring dashboards and forgotten subdomains. Attackers find those too.

Step 2: Update PHP

Linux distributions and LTS vendors received the patches in advance, so patched packages should be available or arriving soon. Always check your vendor’s security tracker for the exact package version that contains the fix. Distribution packages often keep the old version number and add a patch suffix. For example, Ubuntu or Debian may ship a fixed “8.3.x” package that does not say 8.3.36. Check your distribution’s changelog or security notice for the CVE IDs.

Debian and Ubuntu

sudo apt update
apt list --upgradable 2>/dev/null | grep -i php
sudo apt install --only-upgrade 'php*'

Confirm the installed package mentions CVE-2026-109618 / CVE-2026-109619 in its changelog:

apt changelog php8.3-fpm | head -40

(Replace php8.3-fpm with your package name.)

If you use a third-party PHP repository (for example a PPA or a Sury repository), check that repository for updated packages as well.

RHEL, AlmaLinux, Rocky Linux, CentOS Stream

sudo dnf check-update 'php*'
sudo dnf upgrade 'php*'

Important if you use the Remi repository (rpms.remirepo.net): the PHP project states that this volunteer-maintained repository will not have updates on the release day. They recommend switching to distribution packages or building from source so you can patch immediately. Check whether Remi has published fixed packages since then. If it has not, do not wait.

Docker and containers

Updating the host does not fix PHP inside containers. You have to rebuild images:

  1. Update the base image tag to a patched version, for example php:8.3.36-fpm or php:8.4.27-apache (or the 8.x tag once it points to the fixed release)
  2. Rebuild without cache so the new base is pulled:
docker build --pull --no-cache -t your-app:patched .
  1. Redeploy every container and check the version inside:
docker exec <container> php -v

Also check images you do not build yourself, such as official WordPress, Nextcloud or vendor images, and update them as soon as patched versions are published.

Shared and managed hosting

  • Check your hosting control panel (cPanel, Plesk, DirectAdmin) for the PHP version per site
  • Ask your host directly whether their PHP builds include the fixes for CVE-2026-109618 and CVE-2026-109619, and when they were deployed
  • If your site runs on PHP 8.1 or older, switch to a supported version now (test on staging if you can, but do not delay for weeks)

cPanel/EasyApache, Plesk and other panels

Panel vendors ship their own PHP builds. Run the panel’s normal update process and check the vendor’s announcement for the patched build versions.

Windows

Download the patched Windows builds from the official PHP downloads page, replace the PHP directory (keep your php.ini), and restart IIS or the PHP service.

Building from source

Download 8.5.12, 8.4.27, 8.3.36 or 8.2.35 from php.net. For PHP 7.4, 8.0 and 8.1, the PHP security team has published minimal source backport branches linked from the official advisory. Use them only as a temporary bridge to a supported version.

Step 3: Restart every PHP worker

This is the step people forget. PHP-FPM pools, Apache with mod_php and other long-running PHP processes keep the old code in memory until they are restarted.

# PHP-FPM (Debian/Ubuntu, adjust the version)
sudo systemctl restart php8.3-fpm

# PHP-FPM (RHEL family)
sudo systemctl restart php-fpm

# Apache with mod_php
sudo systemctl restart apache2   # Debian/Ubuntu
sudo systemctl restart httpd     # RHEL family

# LiteSpeed
sudo systemctl restart lsws

If you run several PHP versions side by side (for example php8.2-fpm and php8.3-fpm), patch and restart all of them.

Step 4: Verify

  • Run php -v and the FPM binary’s -v again
  • Create a temporary phpinfo() page on a non-public path, check the version, and delete it immediately
  • In WordPress Site Health or your application’s system info, confirm the new version
  • In containers, check inside each running container

If you cannot patch today: interim mitigations

The PHP project is very clear: only an update is a complete solution. The measures below reduce exposure to the known attack paths. They do not make a server safe. Use them only as a bridge of hours or days, not weeks.

Reduce exposure first

  • Restrict internet access to PHP systems you cannot patch immediately. Use a VPN or IP allowlisting for admin panels and internal tools
  • For non-essential systems, consider taking them offline until they are patched, as the UK NCSC advises where immediate remediation is not possible

For CVE-2026-109618 (OOM corruption)

  • Set memory_limit=-1 in a way applications cannot override, for example with php_admin_value[memory_limit] = -1 in the FPM pool or php_admin_value memory_limit -1 in Apache configuration. Check that no pool, directory or application setting puts a finite limit back
  • Because this removes PHP’s own memory cap, use a container or cgroup memory limit as the safety boundary. Do not use RLIMIT_AS or RLIMIT_DATA for this. The advisory warns they can cause the vulnerable allocation failure
  • Lower post_max_size. The advisory suggests 8M for applications without uploads and 32M where uploads are needed, with upload_max_filesize below post_max_size
  • Enforce request size, field count, multipart part count, header count and nesting limits at the web server, proxy or WAF level, including for requests without a usable Content-Length

For CVE-2026-109619 (stale global state)

  • Set session.upload_progress.enabled=0 in php.ini, the FPM pool or server configuration (not with ini_set() or .user.ini), then restart every worker. The advisory suggests keeping this off even after patching if you do not need upload progress
  • On PHP 8.5, set fatal_error_backtraces=0 and restart every worker
  • Remove invalid or deprecated per-request PHP settings that produce warnings before request initialization. Hiding warnings with display_errors or error_reporting does not help
  • Fix fatal errors and execution timeouts that attackers can trigger, for example in upload or import handling

Example for a PHP-FPM pool file (/etc/php/8.3/fpm/pool.d/www.conf):

php_admin_value[memory_limit] = -1
php_admin_value[post_max_size] = 8M
php_admin_value[upload_max_filesize] = 6M
php_admin_flag[session.upload_progress.enabled] = off

Test on staging first. A memory_limit of -1 combined with a missing container or cgroup limit can let a single runaway script use all of the server’s memory.

Step 5: Check for signs of compromise

Exploitation attempts are already being observed, so patching alone is not enough for internet-facing servers that were exposed. Before making big changes, preserve evidence: copies of web server and PHP logs, configuration and suspicious files.

Then check for:

  • New or modified PHP files, especially in upload folders where no PHP should exist:
find /var/www -type f -name "*.php" -mtime -7
find /var/www -path "*/uploads/*" -name "*.php"
  • Web shells: small PHP files with obfuscated code, eval, base64_decode, system, shell_exec or assert in unusual places
  • Unexpected cron jobs, especially for the web server user:
sudo crontab -l -u www-data
ls -la /etc/cron.* /var/spool/cron/ 2>/dev/null
  • New system or application accounts: new WordPress or Magento admin users, new SSH keys in ~/.ssh/authorized_keys
  • Unusual processes or outbound connections running as the web server user:
ps -u www-data -f
sudo ss -tunp | grep -E 'php|www-data|apache|nginx'
  • Web server errors and crashes: a spike in PHP-FPM worker crashes (segfaults) or out-of-memory errors in the logs can point to exploitation attempts

If you find signs of compromise, treat the server as untrusted. Rotate all credentials it had access to (database, API keys, SSH keys, payment integrations) and consider rebuilding from a clean state and restoring data from a backup taken before the compromise. My WordPress malware cleanup guide and server backup strategy cover these steps.

Quick checklist

Step Done?
Inventory all PHP servers, containers and hosting accounts
Update PHP to 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 or patched vendor package
Rebuild and redeploy container images
Restart all PHP-FPM pools, Apache and LiteSpeed
Verify the running version on every site
Disable session.upload_progress if not needed
Restrict or isolate systems that cannot be patched
Check logs, files, cron and accounts for compromise
Plan upgrade off PHP 8.2 and older

Lessons for the future

PHP2Shell is a reminder that application updates are not enough. The runtime (PHP, web server, OS libraries) needs the same attention:

  • Automate security updates for PHP packages, with monitoring that alerts you when a restart is pending
  • Stay on supported PHP versions
  • Know your inventory: which sites run which PHP version where
  • Keep tested, off-site backups
  • Prefer PHP-FPM over mod_php for new setups, with separate pools and users per site

My Linux server hardening checklist explains how to make this routine.

Frequently asked questions

Is WordPress (or Magento, Laravel, Drupal) vulnerable to PHP2Shell?

The vulnerabilities are in PHP itself, not in the applications. Any of these applications running on a vulnerable PHP version is exposed through PHP. Updating WordPress or plugins does not fix it. You have to update PHP.

I updated PHP. Why does my site still show the old version?

The PHP-FPM or Apache process has not been restarted, or the site uses a different PHP version or pool than the one you updated. Restart all PHP services and check per site.

Is changing php.ini enough?

No. The PHP project states that configuration changes reduce exposure to specific attack paths but do not make an installation safe. Update.

My server runs PHP 7.4 or 8.1. What now?

Those versions no longer get official PHP releases. Check whether your OS vendor or an LTS provider offers a backported fix. The PHP project has published minimal source backports for 7.4, 8.0 and 8.1. The real solution is upgrading to a supported version (8.4 or 8.5) as soon as possible.

Does a WAF protect me?

A web application firewall can block some known attack patterns and enforce request limits, which reduces risk. It is not a replacement for patching.

Is my shared hosting safe?

Only if your host has deployed patched PHP builds and restarted its PHP workers. Ask them directly and get a confirmation in writing.

Need help patching your servers?

I help businesses inventory, patch and harden PHP servers running WordPress, WooCommerce, Magento and custom applications, including container rebuilds and compromise checks. See my servers and backups service or request urgent help.

Sources