A patched PHP package that has not restarted its workers is still running vulnerable code. That is the detail most upgrade guides do not mention — and it is the most common reason PHP2Shell (CVE-2026-109618) continues to trigger on servers whose administrators believe the problem is already fixed.
This runbook covers the complete php2shell patch process for every major environment: cPanel/WHM with EasyApache 4 and MultiPHP, Plesk, Ubuntu/Debian, RHEL/Alma/Rocky Linux, and Docker. It also covers what to do if you cannot patch right now, and the SimpleXML regression in PHP 8.4.27 and 8.5.12 that you need to test for before promoting either version to production.
If you have not yet confirmed which PHP version your server runs, is my website vulnerable to PHP2Shell takes about five minutes and does not require developer access.
Patched? Prove it. Upgrading the package is step one. A PHP Scan confirms the fix is actually running — not just installed. Verify my patch →
Upgrade to PHP 8.2.35, 8.3.36, 8.4.27, or 8.5.12 using your environment’s package manager or control panel, then restart every PHP worker process — PHP-FPM, Apache, or LiteSpeed — because running processes keep the old binary in memory until explicitly restarted. Confirm the active version with php –version after the restart.
No patch goes into production without a tested rollback path. Before touching PHP on any live server, complete these steps:
For managed WordPress hosting, cPanel-hosted shared accounts, or other environments not covered here, check whether your host has published a specific advisory. Many managed hosting providers began rolling out patched PHP packages within hours of the official release.
cPanel/WHM manages PHP through EasyApache 4 (EA4). Each PHP branch is a separate EA4 package, so updating PHP 8.3.x to 8.3.36 updates an existing package rather than switching branches.
Via the WHM interface (recommended):
WHM will pull the latest available ea-php packages.
Via the command line:
# Update all installed EA4 PHP packages to the latest available version:
yum update ea-php* -y
# Or target a specific branch:
yum update ea-php83 ea-php83-php ea-php83-php-fpm -y
Restart Apache and PHP-FPM (required):
/scripts/restartsrv_apache
/scripts/restartsrv_apache_php_fpm
MultiPHP environments: If you serve multiple domains on different PHP versions, open WHM → Software → MultiPHP Manager and confirm each domain’s assigned version is a patched release. The yum update ea-php* command above updates all installed EA4 PHP branches simultaneously.
Rollback: Re-provision your previous EA4 profile, or downgrade the specific package: yum downgrade ea-php83-8.3.<previous_version>.
Plesk includes its own PHP version manager, and the recommended path is through the Plesk installer to keep PHP under Plesk’s management layer.
Via the Plesk UI:
Via the command line:
# Upgrade to the latest available PHP 8.3 component:
plesk installer –select-release-current \
–install-component php8.3
# Repeat for each active PHP branch on the server.
Restart PHP-FPM:
plesk svc –restart php-fpm
If Plesk runs per-domain PHP-FPM service handlers, also check Domains → [your domain] → PHP Settings to confirm which handler each domain uses and restart accordingly.
Rollback: Re-run the Plesk installer with the previous version number, or restore from your pre-patch server snapshot.
Ubuntu and Debian ship PHP through their own repositories, which may trail the upstream PHP release by several days. For time-sensitive security updates, the ondrej/php PPA (Ubuntu) and deb.sury.org (Debian) typically carry patched releases sooner.
Check your current PHP source:
php –version
apt-cache policy php8.3 # shows which repository provides the package
Upgrade using apt:
sudo apt update
sudo apt install –only-upgrade php8.3 php8.3-fpm php8.3-cli
Replace php8.3 with your active branch (php8.2, php8.4, or php8.5).
If you use the ondrej/php PPA and it is not already configured:
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt upgrade php8.3
Restart PHP-FPM:
sudo systemctl restart php8.3-fpm
For Apache mod_php configurations (less common on Ubuntu 22.04 and later):
sudo systemctl restart apache2
Verify:
php8.3 -v
Rollback: Pin the previous version with sudo apt-mark hold php8.3 before the upgrade, so you can unhold and downgrade if needed.
Default AppStream modules on RHEL-family systems often ship older PHP versions. For PHP 8.2, 8.3, 8.4, or 8.5, the Remi repository provides current upstream packages.
Update via dnf (if Remi is already configured):
# Select the correct Remi module stream for your target branch:
sudo dnf module reset php
sudo dnf module enable php:remi-8.3
# Update PHP and PHP-FPM:
sudo dnf update php php-fpm -y
Replace remi-8.3 with remi-8.2, remi-8.4, or remi-8.5 as required.
If the Remi repository is not yet configured (RHEL 9 / AlmaLinux 9 / Rocky 9):
sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-9.rpm
sudo /usr/bin/crb enable
sudo dnf module reset php
sudo dnf module enable php:remi-8.3
sudo dnf install php php-fpm -y
Restart PHP-FPM:
sudo systemctl restart php-fpm
sudo systemctl status php-fpm
Verify:
php –version
Rollback: sudo dnf downgrade php php-fpm returns to the previously installed version, or restore from your pre-patch snapshot.
A running container that has not been rebuilt continues to execute the old PHP binary regardless of what is installed on the host. Patching Docker environments means updating the base image in your Dockerfile, rebuilding the image, and redeploying.
Update your Dockerfile:
# Replace your existing php:* tag with a patched version:
FROM php:8.3.36-fpm
# or:
FROM php:8.2.35-apache
# or:
FROM php:8.4.27-cli
Pull, rebuild and redeploy:
# Pull the patched official image:
docker pull php:8.3.36-fpm
# Rebuild your application image (–no-cache ensures a clean build):
docker build –no-cache -t myapp:latest .
# Docker Compose environments:
docker compose pull
docker compose up -d –force-recreate
# Kubernetes:
kubectl rollout restart deployment/my-php-deployment
Confirm the running container is on the patched version:
docker exec my-php-container php -v
For Alpine-based PHP images, check Alpine’s package tracker for patched php8x packages before rebuilding.
Package managers update files on disk. They do not stop or restart processes already running in memory. A PHP-FPM pool that started before your upgrade is still executing the old binary until you explicitly restart it.
This is the most common reason PHP2Shell remains exploitable on servers that appear to have already applied the php2shell patch. The installed package shows the new version number; the running process does not reflect it.
Confirm which binary a running PHP-FPM process is using (Linux):
# Find the PHP-FPM master process ID:
cat /run/php/php8.3-fpm.pid
# Confirm the binary path that process is using:
ls -la /proc/<PID>/exe
If the symlink still points to the old version’s directory, the restart has not occurred.
Restart commands by environment:
| Environment | Restart command |
| Ubuntu / Debian — PHP-FPM | sudo systemctl restart php8.3-fpm |
| RHEL / AlmaLinux / Rocky — PHP-FPM | sudo systemctl restart php-fpm |
| cPanel / WHM — Apache | /scripts/restartsrv_apache |
| cPanel / WHM — PHP-FPM | /scripts/restartsrv_apache_php_fpm |
| Plesk — PHP-FPM | plesk svc –restart php-fpm |
| Apache mod_php (general) | sudo systemctl restart apache2 or sudo systemctl restart httpd |
| LiteSpeed | sudo /usr/local/lsws/bin/lswsctrl restart |
| Docker | Rebuild image and redeploy container |
LiteSpeed note: LiteSpeed runs PHP through its own LSAPI handler. A full restart through the LiteSpeed WebAdmin Console — or the command above — is required. Restarting PHP-FPM alone is not sufficient on LiteSpeed deployments.
Upgraded packages don’t protect you until workers restart.
A PHP Scan checks what your server is actually running — not just what the package manager reports. Use it after every patch wave to confirm the fix is live on every host.
After upgrading packages and restarting workers, confirm the fix is active before closing the change ticket.
Post-patch verification checklist:
Important: A phpinfo() page exposes server configuration to anyone who can reach its URL. Delete it immediately after verification and never commit it to source control.
If a maintenance freeze, application compatibility issue, or unsupported PHP version is blocking immediate patching, three php.ini settings can reduce your exposure. Note the limitations — these are delay tactics, not fixes.
| php.ini setting | Directive | Limits which CVE | Limitation |
| Disable session upload progress | session.upload_progress.enabled = 0 | CVE-2026-109618 | Reduces the upload-based attack surface; does not close the underlying vulnerability [3] |
| Cap memory limit | memory_limit = 256M (never -1) | CVE-2026-109619 | Slows memory-leak exploitation; does not prevent it [3] |
| Disable fatal error backtraces | fatal_error_backtraces = 0 | CVE-2026-109619 | PHP 8.5 only; reduces information disclosure in error output [3] |
| WAF virtual patch | Block payloads matching PHP2Shell patterns | CVE-2026-109618 | Signature-based; can be bypassed by obfuscated payloads [4] |
Apply php.ini changes with a service reload (not a full restart, to minimise downtime):
sudo systemctl reload php8.3-fpm
# or for Apache mod_php:
sudo systemctl reload apache2
For a full discussion of your options when upgrading is not immediately possible — including long-term compensating controls and migration planning — see end-of-life PHP options.
PHP 8.4.27 and 8.5.12 patch both CVE-2026-109618 and CVE-2026-109619, but also introduce a regression in SimpleXML processing tracked in the php-src issue tracker as issue #24488. [2]
Applications that parse XML using simplexml_load_string(), simplexml_load_file(), or the SimpleXMLElement class may encounter unexpected behaviour with certain XML inputs after upgrading to these versions.
Before promoting PHP 8.4.27 or 8.5.12 to production:
Monitor the php-src GitHub repository (github.com/php/php-src) and the PHP releases page at php.net/releases for a follow-up point release addressing the regression.
Related reading: If you need to determine whether a server was compromised before or during the patch window, detect a web shell covers the specific indicators of compromise for PHP2Shell — including memory artefacts you should capture before restarting services.
Use a PHP Scan after each patch wave to confirm nothing was missed — including hosts that were updated by a different team member or an automated process.
Run a post-patch verification scan →
If you manage a distributed or multi-tenant environment, SureShield’s Managed Security Services can help coordinate patch verification across complex infrastructure at scale.
About SureShield: SureShield strengthens cybersecurity resilience through governance, risk, compliance (GRC) and cyber maturity solutions, combining technology and advisory expertise to help organisations build sustainable programs aligned with business goals. Based in Atlanta, Georgia. Learn more about SureShield