As of 23 October 2026, 9:30 AM IST. Version numbers and commands come from php.net, the GitHub security advisories, and the vendor and distribution notices listed under Sources.
This is a hands-on guide to fixing PHP2Shell, the two critical PHP flaws disclosed on 21 October 2026. If you want the news background first, read our report: "PHP2Shell": AI-found PHP flaws force government websites offline across Europe.
The short version
- The bugs: CVE-2026-109618 (GHSA-w8hw-w9fx-j79w, "RCE via OOM corruption") and CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp, "RCE via stale global state"). The PHP project rates both 9.2 (critical) on CVSS v4.0.
- The fix: PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or a distribution or host package that contains the backported patch.
- The step people forget: restart every PHP worker (PHP-FPM, Apache, LiteSpeed) or rebuild your containers. Until you do, the old code is still running.
- Can't patch today? CISA and CERT-EU advise taking internet-facing PHP systems offline or isolating them until they are fixed. php.net lists some partial mitigations, covered below, but says plainly that only an update is a complete fix.
Step 1: Check whether you're affected
Affected and fixed versions (official)
These are the branch versions as listed by php.net, CERT-EU and the Canadian Centre for Cyber Security:
| PHP branch | Vulnerable | Fixed upstream release |
|---|---|---|
| 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 and older (end of life) | all | No new upstream release. php.net published minimal source backports for 7.4, 8.0 and 8.1, and some distributions and LTS vendors ship patched packages. Otherwise, upgrade. |
Per php.net, every PHP installation that serves web requests is at risk, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. The PHP team rates mod_php as the highest-risk setup.
Important: distribution version numbers can look "old" and still be patched
Ubuntu, Debian, Red Hat, AlmaLinux and cPanel often backport security fixes into their existing package version instead of moving to the new upstream number. Ubuntu 24.04's patched package, for example, is 8.3.6-0ubuntu0.24.04.13, not 8.3.36. If your PHP came from your OS or your host, check the package version against your vendor's advisory (see Step 2). The upstream number alone won't tell you.
How to see what you're running
- Command line:
php -v. The CLI can be a different build from the one serving your website, so also check the web-facing binary. On Debian/Ubuntu that is, for example,php-fpm8.3 -v; on RHEL-family systems,php-fpm -v. - Installed packages:
- Ubuntu suggests
apt list '?installed ?name(^php[0-9.]+$)'. - On any Debian/Ubuntu system,
dpkg -l | grep phplists the full package versions. - On RHEL, Alma or Rocky, run
rpm -q php-common(AlmaLinux's own instruction).
- Ubuntu suggests
- Through the web server: create a temporary file containing
<?php phpinfo();, load it in a browser, and note the version and "Server API" line. Delete the file straight away. - Hosting panel: in cPanel, open MultiPHP Manager (or Select PHP Version on CloudLinux hosts) to see which PHP version each domain uses. On managed WordPress hosts, look for a "PHP version" setting or ask support directly whether the PHP2Shell patches are installed.
- Hidden PHP: CISA notes that PHP is often bundled inside other software. CERT-EU points to the NCSC-NL php2shell repository, which tracks third-party products that embed PHP.
Step 2: Patch or upgrade, by setup
Ubuntu (official archive)
Ubuntu published USN-8948-1 for supported releases and USN-8948-2 for ESM releases. Ubuntu's own recommendation is a full upgrade:
sudo apt update && sudo apt upgradePatched versions per USN-8948-1:
| Ubuntu release | Package | Fixed version |
|---|---|---|
| 26.10 | php8.5 | 8.5.9-0ubuntu2.1 |
| 26.04 LTS | php8.5 | 8.5.4-0ubuntu1.5 |
| 24.04 LTS | php8.3 | 8.3.6-0ubuntu0.24.04.13 |
| 22.04 LTS | php8.1 | 8.1.2-1ubuntu2.28 |
| 20.04 / 18.04 / 16.04 / 14.04 | php7.4 / 7.2 / 7.0 / php5 | Fixed through Ubuntu Pro (ESM); see USN-8948-2 |
To upgrade only PHP, name the packages you actually use. --only-upgrade skips anything that isn't installed. For example, on 24.04:
sudo apt update
sudo apt install --only-upgrade php8.3-cli php8.3-common php8.3-fpm php8.3-cgi libapache2-mod-php8.3Ubuntu notes that unattended-upgrades applies security updates automatically within about 24 hours. Affected services still need a restart, though.
Debian
| Debian release | Package | Fixed version | Advisory |
|---|---|---|---|
| 13 (trixie) | php8.4 | 8.4.27-1~deb13u1 | DSA-6574-1 |
| 12 (bookworm) | php8.2 | 8.2.35-1~deb12u1 | DLA-4848-1 |
sudo apt update && sudo apt upgradeThen confirm with dpkg -l | grep php8 that the installed version matches the table.
Ondřej Surý's PPA (ppa:ondrej/php) and packages.sury.org
Many servers run newer PHP branches from this third-party repository. Launchpad lists builds such as 8.4.27-1+ubuntu24.04.1+deb.sury.org+1 and 8.3.36-1+ubuntu24.04.1+deb.sury.org+1. Update the same way as above, naming your branch:
sudo apt update
sudo apt install --only-upgrade php8.4-cli php8.4-common php8.4-fpm libapache2-mod-php8.4Then confirm the result. php8.4-fpm -v should report 8.4.27, and the equivalent check should show 8.3.36, 8.2.35 or 8.5.12 on other branches. We confirmed the Ubuntu PPA builds on Launchpad. If you use the Debian repository at packages.sury.org, check that the installed version also reports the fixed upstream number.
RHEL, AlmaLinux and Rocky Linux
- Red Hat rated its updates "Important". It released fixes including:
- RHSA-2026:87080 for the php:7.4 module on RHEL 8.
- RHSA-2026:87073 for the php:8.2 module on RHEL 8.
- RHSA-2026:87151, which also lists both CVEs.
- AlmaLinux says patched packages for every PHP stream on AlmaLinux 8, 9 and 10 are in its production repositories. These include streams for which Red Hat had not yet shipped a fix at the time of AlmaLinux's post.
- Rocky Linux published RLSA-2026:87080 for Rocky 8.
AlmaLinux's published commands:
sudo dnf clean metadata && sudo dnf upgrade 'php*'
sudo systemctl restart php-fpmThen confirm with rpm -q php-common. You can also check that the package changelog mentions the fix:
rpm -q --changelog php-common | grep -m1 CVE-2026-109618Again, expect backported version strings. AlmaLinux 9's patched PHP 8.3 stream, for example, is php-8.3.33-1.module_el9.8.0+328+1fdeb728.alma.1.
Remi's repository (RHEL-family and Fedora)
Remi Collet announced on 22 October that RPMs of 8.5.12, 8.4.27, 8.3.36 and 8.2.35 are available in remi-modular, and as Software Collections in remi-safe. Earlier, CERT-EU had warned that this volunteer-run repository would not have updates on release day, so make sure you actually received the new build:
sudo dnf upgrade --refresh 'php*'
php -vIf you are on PHP 8.1 or older from Remi, that branch is end of life. Remi's documented way to switch the default PHP to a supported branch on Enterprise Linux is:
sudo dnf module switch-to php:remi-8.4/commonTest your application before doing this on production. A branch upgrade is a bigger change than a patch.
Windows and XAMPP
- Official Windows builds of the fixed releases are on windows.php.net:
php-8.5.12-Win32-vs17-x64.zipphp-8.4.27-Win32-vs17-x64.zipphp-8.3.36-Win32-vs16-x64.zipphp-8.2.35-Win32-vs16-x64.zip
- XAMPP: at the time of writing, the Apache Friends download page still listed XAMPP for Windows with PHP 8.2.12, which is vulnerable. There was no fixed XAMPP installer yet. Swapping in a newer PHP build by hand is possible but unofficial; the steps are below.
To replace XAMPP's PHP manually:
- Stop Apache in the XAMPP Control Panel.
- Back up the whole
C:\xampp\phpfolder. - Extract
php-8.2.35-Win32-vs16-x64.zipover it, keeping your existingphp.ini. - Start Apache and confirm the version with
C:\xampp\php\php.exe -vand a phpinfo page.
XAMPP is designed for local development. If a XAMPP install is reachable from the internet, take it offline first.
Docker (official php images)
Docker says its Official Images and Hardened Images were updated within 24 hours of the upstream release. Fixed tags on Docker Hub include, for example:
php:8.5.12-fpmphp:8.4.27-fpmphp:8.4.27-apachephp:8.3.36-fpmphp:8.3.36-fpm-alpinephp:8.2.35-fpm
Pin a fixed tag in your Dockerfile:
FROM php:8.4.27-fpmThen rebuild and recreate the containers. Pulling the image is not enough on its own:
docker compose build --pull
docker compose up -d --force-recreate
docker compose exec <service> php -vIf you use floating tags like php:8.4-fpm, --pull picks up the patched image, but only for that rebuild. Scan your registry for older images that are still deployed somewhere. If you run Laravel in containers, our Docker Compose setup guide for Laravel shows where the PHP base image is defined.
cPanel/WHM servers and shared hosting
cPanel lists these patched EasyApache 4 packages:
- ea-php85 8.5.12
- ea-php84 8.4.27
- ea-php83 8.3.36
- ea-php82 8.2.35
- ea-php81 8.1.34-5
- ea-php80 8.0.30-12
- ea-php74 7.4.33-19
Note that the 7.4, 8.0 and 8.1 fixes keep their old version numbers. For servers you administer, cPanel's instructions are:
# CentOS/RHEL-based: yum clean all && yum makecache
# Ubuntu-based: apt clean && apt update
/scripts/update-packagesCheck each installed branch, not just the default. Replace php81 with each version you have:
rpm -q --changelog ea-php81-php-cli | grep -m1 CVE-2026-109618
# Ubuntu-based cPanel:
zgrep -E 'CVE-2026-109618' /usr/share/doc/ea-php81-php-cli/changelog.Debian.gzThen restart PHP-FPM and Apache:
/scripts/restartsrv_apache_php_fpm
/scripts/restartsrv_httpdcPanel's notice points to TuxCare's Extended Lifecycle Support for PHP versions older than 7.4. CloudLinux's alt-php packages are tracked separately on CloudLinux's status page.
If you're a shared-hosting customer, you can't patch the PHP binary yourself. What you can do:
- In MultiPHP Manager (or Select PHP Version), move each site off end-of-life versions to 8.2 or newer.
- Ask your host in writing to confirm that the PHP2Shell patches are installed and that PHP workers have been restarted.
Built from source
Download 8.5.12, 8.4.27, 8.3.36 or 8.2.35 from php.net/downloads, rebuild with your usual configure flags, and reinstall. For 7.4, 8.0 or 8.1, php.net says its security team published minimal source backports. Treat these as a stopgap while you migrate.
Then restart everything that runs PHP
A running FPM child or Apache process keeps the old code in memory. Use the commands for your setup:
- PHP-FPM on Debian/Ubuntu:
sudo systemctl restart php8.3-fpm(use your branch number). - PHP-FPM on RHEL/Alma/Rocky:
sudo systemctl restart php-fpm. - Apache with mod_php:
sudo systemctl restart apache2on Debian/Ubuntu, orsudo systemctl restart httpdon RHEL-family systems. - Nginx: Nginx doesn't run PHP itself; restarting PHP-FPM is what matters.
sudo systemctl reload nginxis harmless if you also changed configuration. - LiteSpeed / OpenLiteSpeed: restart the web server, typically
sudo systemctl restart lsws, so that lsphp processes are respawned. - Can't tell what's still running old code? Ubuntu's advice is simply to reboot.
Finally, verify through the web server, not just the CLI. Load a temporary phpinfo page, check the version or package, then delete the page.
Step 3: Temporary mitigations if you truly can't patch yet
The first choice, per CISA, CERT-EU and the Canadian Centre for Cyber Security, is to take unpatched internet-facing PHP offline or restrict access to it, for example behind a VPN or IP allow-list. CISA says a web application firewall "may provide some protection" until you update. Everything below comes from php.net's advisory, which states that these measures "reduce exposure to specific attack paths but do not make an installation safe".
Against CVE-2026-109618 (OOM corruption)
- Set
memory_limit=-1in a way applications can't override. In an FPM pool, usephp_admin_value[memory_limit] = -1; in Apache, usephp_admin_value memory_limit -1. Then make sure no pool, directory or application setting restores a finite limit. php.net warns that an underlying allocation failure can still reach the bug. - Lower
post_max_size:8Mif the app doesn't take uploads,32Mif it does. Keepupload_max_filesizebelow it. - Enforce limits at the web server or proxy on decoded request size, input fields, multipart parts, headers and nesting depth, including for requests without a usable Content-Length.
- Use a container or cgroup memory limit as the availability backstop, ideally one that kills only the affected worker. Do not use
RLIMIT_ASorRLIMIT_DATA, because php.net says they can trigger the vulnerable path.
Against CVE-2026-109619 (stale global state)
- Set
session.upload_progress.enabled=0inphp.ini, the FPM pool or the server configuration, then restart every worker.ini_set()and FPM.user.inifiles apply too late. php.net says this blocks the confirmed session paths but not other variants. - On PHP 8.5 only, set
fatal_error_backtraces=0and restart. - Remove invalid or deprecated per-request INI settings that produce warnings before a request starts. Places to look:
php_valuelines in.htaccessunder mod_php.PHP_VALUEparameters passed by Nginx to FPM.
error_reporting,display_errorsor@does not help. - Fix fatal errors and timeouts that attackers can trigger, such as failing upload or import handlers.
Example FPM pool entries (for instance in /etc/php/8.3/fpm/pool.d/www.conf), followed by an FPM restart:
php_admin_value[memory_limit] = -1
php_admin_flag[session.upload_progress.enabled] = off
php_admin_value[post_max_size] = 8M
php_admin_value[upload_max_filesize] = 6MRemoving the memory limit lets a runaway script consume the whole machine. Treat these settings as a bridge of hours or days and undo them after you patch.
Step 4: Check whether you were already compromised
Patching closes the door, but it doesn't remove anyone who got in first. CISA's alert said it had not seen exploitation at publication. Other reports conflict on this point. Amazon, quoted by Reuters in our news report, said the flaws were being broadly exploited, while the Canadian Centre noted a public proof of concept. Given that, assume an internet-facing server that sat unpatched after 21 October needs checking. The official guidance is to look for:
- PHP workers spawning shells or downloading tools (CISA). Inspect the process tree with
ps -ef --forestand look forsh,bash,curl,wgetor unknown binaries underphp-fpm,apache2/httpdorlsphp. - Unexpected files (Canadian Centre). List PHP files changed recently in your web root, adjusting the path and date:
Also check upload, cache and tmp directories forsudo find /var/www -type f -name '*.php' -newermt '2026-10-15' -ls.phpfiles that shouldn't be there. Look for code that useseval(,base64_decode(,assert(orsystem(on request input; these are typical web-shell patterns, though legitimate code uses some of them too. On WordPress,wp core verify-checksums(WP-CLI) compares core files with the official release. - New accounts, cron jobs and SSH keys. Check
crontab -lfor the web user (www-data,apacheornginx),/etc/cron.*and~/.ssh/authorized_keys, plus admin users in your CMS. - Outbound connections (Canadian Centre).
sudo ss -tnpshows established connections and the process that owns each one. - Logs. Review web server, PHP-FPM, authentication and endpoint logs. Look for bursts of large multipart POSTs, repeated "Allowed memory size exhausted" or segmentation-fault messages, and requests to files you don't recognise.
If you find signs of compromise, don't just delete the shell. Take the server offline and preserve logs. Rebuild from a known-clean source or backup, patch before reconnecting, and rotate every secret the web user could read:
- database passwords in
wp-config.phpor.env - app keys and API tokens
- SMTP credentials
- cloud keys
- SSH keys
Report the incident to your national CERT where that applies. In India, that is CERT-In.
Step 5: Hardening checklist
- Inventory every PHP runtime, including appliances and vendor products that embed it (see the NCSC-NL list).
- Get off end-of-life PHP. PHP 8.1 and older receive no upstream fixes. php.net also notes that 8.2 reaches end of life on 31 December 2026, so plan the next upgrade now. Our guide to what PHP 8.3 and 8.4 change for Laravel developers covers the code side of the move.
- Automate security updates and the restart. Unattended-upgrades or
dnf-automaticinstall packages but don't always restart PHP. On Debian/Ubuntu, theneedrestarttool flags services still running old libraries. - Prefer PHP-FPM over mod_php where you can. The PHP team rated mod_php the highest-risk setup for this flaw, and FPM lets each site run in its own pool and as its own user.
- Least privilege. Never run PHP as root. The web user shouldn't be able to write to application code, only to specific upload or cache folders, and those folders should not execute PHP.
- Keep per-request INI overrides clean. Audit
.htaccessphp_valuelines and NginxPHP_VALUEparameters for deprecated or invalid settings. - Sensible request limits at the proxy and in
post_max_size, even after patching. php.net says these reduce denial-of-service risk. - Put a WAF or CDN in front of public sites, and make sure the origin accepts traffic only from it.
- Watch the right feeds: php.net news, your distribution's security list, and CERT-In, CISA or CERT-EU advisories.
- Have tested backups and central logs. They make Step 4 possible. For Laravel apps, see our 12 security checks to run before launch.
What we couldn't confirm
- Exploitation status: CISA (21 October) had not observed exploitation; Amazon, as reported by Reuters, said it was broad. Treat the risk as active.
- Exact release time: php.net had scheduled the release for 14:00 UTC; CERT-EU recorded 13:30 UTC.
- Third-party packages: availability for every package and mirror can lag. Always confirm the version you actually have installed.
- XAMPP: the manual PHP swap described above is not an Apache Friends procedure.
Sources
- php.net: Security advisory, critical remote code execution vulnerabilities, update now (21 Oct 2026)
- php.net: PHP 8 ChangeLog (8.5.12 / 8.4.27 entries)
- GitHub php-src advisory GHSA-w8hw-w9fx-j79w (CVE-2026-109618)
- GitHub php-src advisory GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)
- The PHP Foundation: Today's PHP security release
- CISA: Critical vulnerabilities in PHP require immediate patching
- CERT-EU Security Advisory 2026-018
- Canadian Centre for Cyber Security: AL26-026
- NCSC-NL: php2shell repository
- Ubuntu: php2shell fixes available and USN-8948-1
- Debian security tracker: CVE-2026-109618
- Red Hat: RHSA-2026:87073 and RHSA-2026:87080
- AlmaLinux: php2shell patched PHP packages released
- Rocky Linux: RLSA-2026:87080
- Remi's RPM repository: PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12
- Launchpad: Ondřej Surý PHP PPA
- Docker: Security update on PHP2Shell
- cPanel: Critical PHP security release
- windows.php.net: PHP for Windows downloads
- Apache Friends: XAMPP downloads