On October 21, 2026, the PHP project shipped an emergency security release fixing two critical remote code execution flaws, CVE-2026-109618 and CVE-2026-109619 (dubbed "PHP2Shell" by researchers). Both score CVSS 9.2 and allow an unauthenticated attacker to run code on your server. Patched releases went out for every supported branch: 8.2.35, 8.3.36, 8.4.27, and 8.5.12, and exploitation attempts have already been seen in the wild.
But if your server runs PHP 8.1, 8.0, or 7.4, there is no official release for you — the PHP project only patches supported branches. This guide covers your three paths: Option A — a vendor or distro backport, Option B — upgrade to PHP 8.4, and Option C — temporary mitigations if you cannot move right now. Written for Ubuntu 22.04/24.04, with cPanel notes where relevant.
Prerequisites
- A server running PHP 8.1 or older (Ubuntu 22.04 or 24.04 in this guide).
- Root or sudo access.
- Know which SAPI serves your web traffic: PHP-FPM, Apache
mod_php, or something else. The risk is highest formod_php, where researchers demonstrated RCE before application code even runs, but PHP-FPM is affected too. - A full backup of your site files and databases before you touch anything.
- A list of the PHP extensions your applications actually use.
Step 0: Find out exactly what you are running
Before choosing a path, confirm your PHP version and how the web server uses it. The CLI version and the web version can differ.
php -v
php -m | sort
php -v shows the CLI version; php -m lists loaded extensions so you know what must exist on the new version later.
dpkg -l | grep -E 'php8\.[01]|php7\.4' | awk '{print $2}'
This lists every installed PHP 8.1/8.0/7.4 package on Debian/Ubuntu systems, which becomes your shopping list for the upgrade.
Then check what the web server actually runs: create a temporary file with <?php phpinfo(); in your web root, load it in a browser, and read the "PHP Version" line. Delete the file immediately afterwards. If the web version differs from the CLI version, the web one is what matters for this vulnerability.
Step 1 (Option A): Take a vendor or distro backport
If your PHP comes from your OS vendor or hosting panel, the fix may already be available as a backported patch: the vendor applies the security fix to their existing package without bumping the version number. Your php -v may still say 8.1.x after patching, so confirm with the vendor rather than trusting the version string alone.
Debian / Ubuntu
Check whether your distribution's security team has shipped the backport:
sudo apt update
apt list --upgradable 2>/dev/null | grep -i php
apt list --upgradable filtered for php shows pending PHP package updates from your configured repositories, including security backports.
If updates appear, install them and restart every PHP worker, because running processes keep the old, vulnerable code in memory:
sudo apt upgrade -y
sudo systemctl restart php8.1-fpm
sudo systemctl restart apache2 2>/dev/null; sudo systemctl reload nginx 2>/dev/null
This upgrades the packages, then restarts PHP-FPM and your web server so no worker keeps running the old build.
cPanel / WHM
cPanel backported the fix to its PHP 7.4, 8.0, and 8.1 packages in EasyApache 4 (alongside ea-php82 8.2.35 and the newer ea-php83/84/85 builds). Update through WHM > Software > EasyApache 4, or from the command line on AlmaLinux/RHEL-based servers:
sudo dnf upgrade 'ea-php*'
/scripts/restartsrv_httpd
/scripts/restartsrv_apache_php_fpm
The first command upgrades all EasyApache PHP packages, and the two cPanel scripts restart Apache and the PHP-FPM pools so the patched code takes effect.
If no backport exists for your setup, move on to Option B. Do not assume you are covered because "the host handles it" — ask your host or vendor explicitly whether CVE-2026-109618 and CVE-2026-109619 are patched in your exact package build.
Step 2 (Option B): Upgrade from PHP 8.1 to PHP 8.4
PHP 8.4 is the recommended target: a supported branch whose fixed 8.4.27 release (and everything newer) contains both CVE fixes, and the jump from 8.1 is small enough that most applications migrate cleanly. The ondrej/php PPA provides current 8.4 builds for Ubuntu.
2.1 Back up everything
sudo mkdir -p /backup/php-upgrade
sudo tar -czf /backup/php-upgrade/www-$(date +%F).tar.gz /var/www/html
sudo mysqldump -u root -p --all-databases > /backup/php-upgrade/all-databases.sql
This archives your web root and dumps every MySQL/MariaDB database with today's date in the filename, so you have a restore point before anything changes.
2.2 Inventory your extensions
php -m | sort > /backup/php-upgrade/extensions-81.txt
cat /backup/php-upgrade/extensions-81.txt
Saving the extension list gives you a checklist: every extension your app needs on 8.1 must have a php8.4-* counterpart installed later.
2.3 Add the PHP PPA
sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:ondrej/php
sudo apt update
software-properties-common provides add-apt-repository; the second command adds the Ondrej Sury PHP PPA, the de-facto standard source for current PHP builds on Ubuntu; the third refreshes the package lists.
2.4 Install PHP 8.4 with matching extensions
sudo apt install -y php8.4 php8.4-fpm php8.4-cli php8.4-common \
php8.4-mysql php8.4-curl php8.4-xml php8.4-mbstring php8.4-zip \
php8.4-gd php8.4-intl php8.4-bcmath php8.4-opcache php8.4-readline
This installs PHP 8.4 plus FPM and the most common extensions. Compare against your saved 8.1 list and add any missing ones (for example php8.4-redis or php8.4-imagick) before continuing.
2.5 Compare and carry over configuration
diff /etc/php/8.1/fpm/php.ini /etc/php/8.4/fpm/php.ini | head -60
diff shows what changed between your tuned 8.1 config and the fresh 8.4 defaults. Manually port your custom settings (memory limits, upload sizes, timezone, opcache tuning, FPM pool files) into the 8.4 files rather than copying the old files over, since defaults sometimes change between versions.
2.6 Point the web server at PHP 8.4
For Nginx with PHP-FPM, update the socket path in your site configs:
grep -rn "fastcgi_pass" /etc/nginx/sites-enabled/
sudo sed -i 's|unix:/run/php/php8.1-fpm.sock|unix:/run/php/php8.4-fpm.sock|' /etc/nginx/sites-enabled/*
sudo nginx -t && sudo systemctl reload nginx
The grep finds every fastcgi_pass line, sed rewrites the socket path to the 8.4 pool, and nginx -t validates the config before reloading.
For Apache with PHP-FPM:
sudo a2disconf php8.1-fpm
sudo a2enconf php8.4-fpm
sudo systemctl restart apache2
This disables the old FPM proxy config, enables the 8.4 one, and restarts Apache so it connects to the new pool.
For Apache with mod_php:
sudo a2dismod php8.1
sudo a2enmod php8.4
sudo systemctl restart apache2
This swaps the loaded PHP module from 8.1 to 8.4 and restarts Apache.
2.7 Test before you celebrate
php8.4 -v
ls /run/php/
sudo systemctl status php8.4-fpm --no-pager | head -12
These confirm the 8.4 binary version, that the FPM socket exists, and that the 8.4 FPM service is running. Then reload your temporary phpinfo() page in the browser and confirm it now reports PHP 8.4. Walk through your application's critical paths (login, checkout, uploads) and watch the error log:
sudo tail -f /var/log/php8.4-fpm.log
2.8 Remove the old version (after a soak period)
Keep PHP 8.1 installed for 24–48 hours in case you need to roll back. Once traffic is clean, remove it:
sudo apt purge 'php8.1*'
sudo apt autoremove -y
Step 3 (Option C): If you cannot move right now
Sometimes an upgrade is blocked: a legacy app, a frozen change window, a vendor that has not shipped a backport. PHP is explicit that these are incomplete mitigations, not fixes — updating remains the only complete fix. But they reduce exposure while you plan the move.
Apply these in php.ini (or a conf.d snippet), then restart FPM/Apache:
session.upload_progress.enabled=0
memory_limit=-1
Disabling session upload progress removes the code path confirmed exploitable for CVE-2026-109619 on PHP-FPM. Setting memory_limit=-1 only makes sense together with a host-level memory cap, otherwise a runaway process can exhaust the box:
sudo systemctl edit php8.1-fpm
Add the following lines in the editor that opens, then save:
[Service]
MemoryMax=2G
This caps the whole PHP-FPM service at 2G of RAM via systemd, so the unlimited PHP memory limit cannot take down the server.
At the reverse proxy, block multipart uploads on endpoints that do not need them. In Nginx, for example, reject multipart POSTs on a login or API path that should never receive file uploads:
location /api/ {
if ($content_type ~* "multipart/form-data") { return 444; }
# ... existing proxy/fastcgi config
}
This drops the connection for multipart requests to that location before they reach PHP, shrinking the attack surface described in the advisories.
Finally, isolate the server from untrusted traffic: firewall off everything except 80/443, put admin panels behind an IP allowlist or VPN, and keep a WAF in front if you have one. None of this replaces the patch; it buys time.
Verify it worked
- Check the version through the web server, not just the CLI. Reload your
phpinfo()page (then delete it). The CLI can report 8.4 while a stale FPM pool still serves 8.1. - Confirm every worker restarted. After any update, restart the FPM pool and the web server. Running workers keep the old vulnerable code.
- Confirm CVE coverage. Supported branches need 8.2.35+, 8.3.36+, 8.4.27+, or 8.5.12+. On 8.1 or older, get vendor confirmation that their backport covers both CVEs. The version number alone may not prove it.
- Watch the logs for 24 hours.
sudo tail -f /var/log/php*-fpm.logand your web server error log. A clean log plus passing smoke tests means the migration held.
Migration checklist
- Full file + database backup taken and restorable.
- Extension inventory saved; all required
php8.4-*extensions installed. - Custom
php.iniand FPM pool settings ported to 8.4. - Web server points at the 8.4 socket/module; old 8.1 pool stopped or removed.
phpinfo()via the browser confirms 8.4.27 or newer.- Application smoke tests pass; error logs clean for 24h.
- Temporary mitigations reverted or re-applied intentionally on the new version.
- Old PHP 8.1 packages removed after the soak period.
Rollback notes
If the application breaks on 8.4, roll back in minutes: re-point Nginx/Apache at the 8.1 socket or module (reverse the Step 2.6 commands), restart the web server, and confirm via phpinfo(). Keep the 8.1 packages installed until the soak period ends. The most common 8.1 → 8.4 breakages are dynamic property deprecations and extensions with no 8.4 build yet — both fixable without abandoning the upgrade.
Common issues & fixes
1. add-apt-repository: command not found
Install the package that provides it, then retry:
sudo apt install -y software-properties-common
2. 502 Bad Gateway right after switching FPM versions
Almost always a socket path mismatch. Check which sockets exist and compare with your Nginx config:
ls /run/php/
grep -rn "fastcgi_pass" /etc/nginx/sites-enabled/
If Nginx still points at php8.1-fpm.sock while only php8.4-fpm.sock exists, re-run the sed from Step 2.6, then sudo nginx -t && sudo systemctl reload nginx.
3. A PHP extension has no 8.4 package
Check availability before panicking:
apt-cache policy php8.4-imagick
If the extension truly has no 8.4 build in the PPA yet, install it via PECL (sudo pecl install imagick) or check whether your application can run without it temporarily.
4. Apache still serves the old PHP after the switch
You probably enabled the new module without disabling the old one, or forgot the restart:
apache2ctl -M | grep -i php
sudo a2dismod php8.1 && sudo a2enmod php8.4 && sudo systemctl restart apache2
5. Flood of deprecation warnings in the logs
PHP 8.2+ deprecates dynamic class properties, which some older code relies on. As a short-term measure, keep display_errors=Off in production and log instead:
display_errors=Off
log_errors=On
error_log=/var/log/php_errors.log
Then fix the underlying code — silencing deprecations is not a long-term strategy, and PHP 9 will turn several of them into fatal errors.
Conclusion
The October 2026 PHP RCE flaws are as serious as it gets: unauthenticated remote code execution, a 9.2 CVSS score, and active exploitation in the wild. If you are on PHP 8.1 or older, no official patch is coming — your paths are a vendor backport, an upgrade to PHP 8.4, or hardening mitigations while you plan the move. The upgrade is the only one that fully closes the hole.
Need help with a PHP upgrade on production servers? XpertBees handles server migrations, hardening, and emergency patching with zero-downtime cutover.

