PHP2Shell: what WordPress, Joomla, and Matomo site owners should do now
· Witen Labs · Security advisory
Updated : PHP’s October 23 advisory: keep session upload progress off until the next PHP release. Also Sury and Remi package status, how to check backported builds, and what to do after patching.
What happened
If your WordPress, Joomla, or Matomo site runs on PHP, update PHP today or ask your host to do it. On October 21, 2026, PHP released emergency fixes for two critical flaws, together called PHP2Shell (CVE-2026-109618 and CVE-2026-109619), that let an attacker run their own code on a server without logging in.
- Who is affected: essentially every site that serves web pages with PHP 5.4 or later, whatever your web server setup (BleepingComputer).
- Why it’s urgent: details leaked a day early, and Cloudflare saw attack traffic before the fix shipped. One day on, Sansec reports that the public exploits don’t work against a default PHP installation and need specific conditions on the target, so mass exploitation looks less likely than first feared (Sansec). That buys you hours, not weeks.
- It can leak secrets, too: the researchers also demonstrated reading PHP’s memory, which can hold passwords, API keys, and session tokens, without running any code on the server (PHP2Shell researchers).
- The hard part: new official releases exist only for PHP 8.2, 8.3, 8.4, and 8.5. For 7.4, 8.0, and 8.1, PHP has published minimal source backports, and some vendors ship backported packages. PHP itself publishes nothing for 7.3 and older.
- Update, October 23: PHP disclosed a related, much narrower flaw (CVE-2026-115560) that the October 21 releases don’t fix. Update anyway, then keep
session.upload_progress.enabled=0until the next PHP release (details below).
The flaw is in PHP itself, not in WordPress, Joomla, or Matomo, so updating those alone does not fix it.
Step 1: Find your PHP version
You need the full version number, such as 8.3.36, not just “8.3”. For official PHP releases, the last number tells you whether the fix is installed. Linux distributions, Sury, and Remi backport the fix without changing that number, so on those builds you also need the package version (see If your server gets PHP from Sury and If your server gets PHP from Remi).
- WordPress: Tools → Site Health → Info tab → Server → PHP version.
- Joomla: System → System Information → PHP Version.
- Matomo: Administration → System → System Check → PHP version.
- Hosting control panel: cPanel’s “Select PHP Version” or “MultiPHP Manager”, or Plesk’s PHP settings for your domain. These often show only “8.3”, so check inside your site as well.
If your site is managed by a developer or agency, send them this page and ask them to confirm the exact version.
Step 2: What your version means
These releases, and anything newer on the same branch, contain the fixes for both PHP2Shell vulnerabilities: 8.5.12, 8.4.27, 8.3.36, and 8.2.35 (PHP security advisory). A fixed version closes these two flaws; it doesn't make a site safe in general.
| Your PHP version | Status | What to do |
|---|---|---|
| 8.5.12+, 8.4.27+, 8.3.36+, 8.2.35+ | Fixed | Nothing for PHP2Shell. If on 8.2, plan a move: it stops getting security fixes on December 31, 2026. |
| Older 8.2, 8.3, 8.4, or 8.5 | Vulnerable, fix available | Update today. Ask your host if you can’t do it yourself. If the number looks old but PHP comes from your Linux distribution, check the package first (see below). |
| 8.1, 8.0, 7.4 | Vulnerable, no official release | Install a backported package from your Linux vendor, Sury, or Remi, or ask your host for one; PHP has published minimal source backports for these branches. The version number doesn’t change, so confirm the package. Then plan a move to 8.3 or newer. |
| 7.3 or older | Vulnerable, no official fix | Sury and some paid long-term vendors have backported the fix as far as 5.6. Install one if you can, and move to a supported version as soon as possible. |
Before switching PHP versions on a site that has been on old PHP for a long time, take a full backup and update your themes and plugins first. Old extensions are the usual reason a site breaks after an upgrade.
Patching does not remove an attacker who got in before you patched. If your site was exposed, read the section on signs of compromise below.
If your server gets PHP from Sury
Many Debian and Ubuntu servers, and the hosts and panels built on them, install PHP from Ondřej Surý’s free, volunteer-run packages: packages.sury.org for Debian, and the ppa:ondrej/php archive on Launchpad for Ubuntu. Sury shipped fixes for every branch from 5.6 to 8.5, including the end-of-life branches the PHP project no longer releases. Its changelog entries for the fix are dated October 20 and 21, before PHP’s public release at 14:00 UTC on October 21.
- Ubuntu PPA (ppa:ondrej/php): fixed for every branch on Ubuntu 22.04 and 24.04, on every architecture, published on October 21 between 15:46 and 20:56 UTC.
- packages.sury.org on amd64 (ordinary Intel and AMD servers): fixed for every branch on Debian 11, 12, and 13 and Ubuntu 22.04 and 24.04. The 7.2 to 8.5 package files are dated October 21, before PHP’s release; 5.6, 7.0, and 7.1 were rebuilt again on October 22.
- packages.sury.org on ARM (arm64 and armhf): many branches still serve builds from before the fix. Mattias Geniar flagged the gap on the older branches; when we read the repository’s own indexes on October 22 (dated 14:36 to 16:01 UTC, and unchanged when we checked again at 17:20 UTC), it ran through the supported branches too. On arm64, only 8.5 on Debian 12 and 8.2 on Ubuntu 22.04 had fixed 8.2 to 8.5 builds. Debian 12 arm64 still offered 8.3.35 and 8.4.26.
ARM covers AWS Graviton, Ampere, Oracle and Hetzner ARM servers, and Raspberry Pi. Builds are landing hour by hour (Debian 12’s arm64 8.5 build arrived at 13:45 UTC on October 22), so treat this snapshot as a reason to check, not as your answer:
| packages.sury.org release | arm64: no fix yet | armhf: no fix yet |
|---|---|---|
| Debian 12 (bookworm) | 5.6, 7.0, 7.1, 8.0, 8.1, 8.2, 8.3, 8.4 | 7.3, 8.1, 8.2, 8.3, 8.4, 8.5 |
| Debian 13 (trixie) | 7.2, 7.3, 7.4, 8.1, 8.2, 8.3, 8.4, 8.5 | 5.6, 7.0, 7.2, 7.4, 8.1, 8.2, 8.3, 8.5 |
| Debian 11 (bullseye) | 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5 | 5.6, 8.0, 8.1, 8.2, 8.5 |
| Ubuntu 24.04 (noble) | 7.0, 7.1, 7.2, 8.0, 8.2, 8.3, 8.4, 8.5 | 5.6, 7.0, 7.1, 7.2, 8.1, 8.2, 8.4, 8.5 |
| Ubuntu 22.04 (jammy) | 5.6, 7.3, 7.4, 8.1, 8.3, 8.4, 8.5 | 7.1, 8.1, 8.2, 8.3, 8.4, 8.5 |
The first fixed Sury package on each branch is below. Your installed version must be this or later; the part after the + varies by release and repository.
| PHP branch | First fixed Sury package |
|---|---|
| 8.5 | 8.5.12-1 |
| 8.4 | 8.4.27-1 |
| 8.3 | 8.3.36-1 |
| 8.2 | 8.2.35-1 |
| 8.1 | 8.1.34-9 |
| 8.0 | 1:8.0.30-25 |
| 7.4 | 1:7.4.33-31 |
| 7.3 | 7.3.33-35 |
| 7.2 | 7.2.34-66 |
| 7.1 | 7.1.33-80 |
| 7.0 | 7.0.33-92 |
| 5.6 | 5.6.40-104 |
Check your own server
On old branches the PHP version doesn’t change when the fix arrives. Sury’s fixed 8.1 still reports 8.1.34, exactly like the vulnerable one, and WordPress Site Health will show the same number. The same goes for distribution packages: Ubuntu 24.04’s fixed PHP still reports 8.3.6, as Mattias Geniar pointed out. The package version is what tells them apart. Run these over SSH:
# Which architecture is this server?
dpkg --print-architecture
# Which PHP packages are installed, at which versions?
dpkg -l | grep -E 'php[0-9.]+-(fpm|common)|libapache2-mod-php'
# Where does a package come from? Use your branch in place of 8.3.
apt-cache policy php8.3-fpm
# Does the installed package record the fix? Any output means yes.
zgrep -E 'CVE-2026-10961[89]' /usr/share/doc/php8.3-common/changelog.Debian.gzapt-cache policylists the source of each version.packages.sury.orgorppa.launchpadcontent.net/ondrej/phpmeans Sury;deb.debian.org,security.debian.org, orarchive.ubuntu.commeans your distribution.- A packages.sury.org version looks like
8.1.34-9+0~20261021.82+debian12~1.gbp4e430a, and a PPA version like8.1.34-9+ubuntu24.04.1+deb.sury.org+1. In both,8.1.34-9is the part to compare with the table above.8.1.34-8is vulnerable. - Distribution fixes: Debian 12 ships
8.2.35-1~deb12u1and Debian 138.4.27-1~deb13u1in their security archives (Debian tracker). Ubuntu 24.04 ships8.3.6-0ubuntu0.24.04.13and Ubuntu 22.048.1.2-1ubuntu2.28(Ubuntu security). - Check the package that serves your site, usually
php8.x-fpmorlibapache2-mod-php8.x. The command-line PHP is a separate package and can be at a different version. - Mattias Geniar also found a quick test: fixed 8.2 to 8.5 builds know a new setting, so
php -r 'var_dump(ini_get("memory_hard_limit_percent"));'printsstring(0) ""instead ofbool(false). Sury’s backports to 8.1 and older don’t add that setting, so use the changelog there.
Then update and restart. The fix only takes effect once PHP restarts:
sudo apt update && sudo apt upgrade
sudo systemctl restart php8.3-fpm # or: sudo systemctl restart apache2If you’re on ARM and your branch has no fixed build yet, don’t wait on it. On Ubuntu, switch to the PPA, which is fixed for ARM. On Debian, the quickest fixed option is usually the distribution’s own PHP (8.2 on Debian 12, 8.4 on Debian 13) or a Sury branch that is already fixed for your architecture. Until then, apply the interim settings below.
Witen’s Vulnerability Intel judges Linux packages against the Debian, Ubuntu, Alpine, Red Hat, and Gentoo security trackers. Sury and Remi aren’t among those trackers, so for their builds the package changelog and the tables on this page are the answer.
If your server gets PHP from Remi
On RHEL, AlmaLinux, Rocky Linux, and Fedora, many servers get PHP from Remi Collet’s free, community-run repository. PHP’s advisory warned it would not have updates on October 21, but the fixed packages were in the repository that afternoon: the package files are dated 13:34 to 13:53 UTC, and the repository metadata about 14:07 UTC, minutes after PHP’s release. Remi announced them on its blog on October 22.
- What’s fixed: 8.2, 8.3, 8.4, and 8.5, plus backports to 7.4, 8.0, and 8.1, on Enterprise Linux 8, 9, and 10 and Fedora 43 and 44, for x86_64 and aarch64 (ARM). Fedora 45 offers 8.2 to 8.5 only, all fixed. ARM got its builds at the same time as x86_64.
- Both install styles: the module streams in remi-modular, which replace the system
phppackages, and the parallel packages named likephp81-php-common, which install beside them. - Not fixed yet: 7.2 and 7.3 on Enterprise Linux 8, still at builds from August, and the parallel 5.6, 7.0, and 7.1 packages there, from July.
Remi’s backports keep the upstream number too. The fixed 8.1 is 8.1.34-6 and the vulnerable one is 8.1.34-5; both report PHP 8.1.34. A module stream package looks like php-common-8.1.34-6.module_php.8.1.el9.remi and a parallel one like php81-php-common-8.1.34-6.el9.remi. Compare the part before .module or .el with this table:
| PHP branch | First fixed Remi package |
|---|---|
| 8.5 | 8.5.12-1 |
| 8.4 | 8.4.27-1 |
| 8.3 | 8.3.36-1 |
| 8.2 | 8.2.35-1 |
| 8.1 | 8.1.34-6 |
| 8.0 | 8.0.30-21 |
| 7.4 | 7.4.33-31 |
# Module stream install (remi-modular): which PHP, from which repository?
rpm -q php
dnf info php
# Parallel (SCL) install: use your branch in place of 81.
rpm -q php81-php-common
# The newest changelog entries. A backport names both CVEs;
# 8.2 to 8.5 say "Update to" the fixed release.
rpm -q --changelog php | headThen run sudo dnf upgrade and restart PHP: sudo systemctl restart php-fpm for a module stream, php81-php-fpm for a parallel install, or httpd if Apache runs PHP itself.
Step 3: Ask your host
On shared or managed hosting, your host controls the PHP build, so you need them to confirm the fix. If your server gets PHP from Sury or Remi, the sections above show how to check the package yourself. Many hosts will patch without being asked, but a short ticket gets you a clear answer. Copy, fill in the brackets, and send:
Subject: PHP2Shell (CVE-2026-109618 / CVE-2026-109619) on [your domain]
Hi,
My site [your domain] runs PHP [your version]. PHP released fixes for
PHP2Shell on October 21, 2026 (8.5.12, 8.4.27, 8.3.36, 8.2.35).
1. Has the PHP serving my site been updated to a fixed release, or a
build with the fixes backported? If so, which version or build?
2. If not, when will it be, and can I switch my site to a fixed version
now?
3. Have you applied any interim protection (for example WAF rules) in
the meantime?
4. Is session.upload_progress.enabled set to 0, as PHP recommends until
its next release (CVE-2026-115560)?
Thanks,
[your name]If the answer is vague, ask again for the exact version. “We’re aware of it” is not the same as “you’re patched.”
If you can’t update right away
None of these make a site safe; they buy time until you can update. The PHP team says only updating is a complete fix (PHP security advisory).
If you run your own server or VPS, PHP’s interim settings reduce exposure to the confirmed attack paths. Set them in php.ini or the FPM pool config, then restart every PHP worker:
session.upload_progress.enabled=0. Setting it withini_set()or a.user.inifile does not work. Leave this one off after you update, too (see After you patch).post_max_sizeof 8M if the site doesn’t take file uploads, 32M if it does, withupload_max_filesizebelow it.- On PHP 8.5 only,
fatal_error_backtraces=0. - The advisory also covers
memory_limitand container limits. Read it before changing those, since the wrong setting can make things worse. - If the site takes no file uploads, reject
multipart/form-datarequests at the web server; Sansec notes every known trigger uses that format. Syhunt’s php2shell-protection has Apache rules and a test to confirm they work.
If you’re on shared hosting, you usually can’t change these yourself. Your options:
- Put the site behind a web application firewall. Cloudflare has deployed rules that block known PHP2Shell exploit methods on every plan with its WAF, including Free, though it describes them as temporary (Cloudflare). As Zacharias Creutznacher points out, a WAF only helps if attackers can’t go around it: make sure no DNS record (staging, ftp, direct) points at your server without the proxy.
- Turn off what you don’t need. Disable contact forms, upload forms, and unused plugins until you’re patched.
- Take the site offline if it handles payments or personal data and you can’t patch soon. The UK’s National Cyber Security Centre advises updating immediately or taking systems offline until patched. Sansec’s October 22 assessment is that most sites don’t need to go that far, so weigh it against what the site holds.
Keep backups current either way, stored somewhere the site itself can’t reach.
After you patch
- Restart every PHP process. PHP-FPM, Apache, and long-running workers keep running the old code until they restart.
- Put a real
memory_limitback if you set it to-1as a stopgap. As Mattias Geniar showed in testing the fixed builds, the fix turnsmemory_limitinto a soft limit with a hard one above it: twice the limit up to 1G, and the limit plus 1G above that.-1switches both off. A request that reaches the hard limit ends its PHP worker on the spot, with no error page and no line in the PHP error log, only “exited with code 137” in the PHP-FPM log. Turn oncatch_workers_output = yesin your FPM pools to see which script did it, size memory for the hard limit, and leavememory_hard_limit_percentat its default. - Keep
session.upload_progress.enabled=0until the next PHP release. On October 23, PHP confirmed a separate flaw, CVE-2026-115560, that can still lead to code execution on the fixed releases, 8.5.12 included, and asked everyone to leave upload progress off until its next regular release (PHP advisory). Few sites are exposed: PHP’s configuration has to setsession.serialize_handlertophp_binaryorphp_serialize, and the application then has to switch it tophpwithini_set()before starting a session. PHP says sites that never change the handler can leave the feature on, but you can’t easily rule that out for every plugin, and almost no site uses upload progress tracking, so turn it off in php.ini or the FPM pool. If you already set it for PHP2Shell, leave it in place. These are the conditions Felipe Daragon of Syhunt described for his proof of concept on 8.5.12 (Syhunt). Florian Roth separately relayed a trusted contact’s claim of working exploitation against 8.2.35 and 8.5.12 that this setting blocks; he said he hadn’t reproduced it. On shared hosting, ask your host to keep it off. - Don’t roll back if something crashes. PHP has confirmed a regression in 8.4.27 and 8.5.12 that crashes some code using SimpleXML (php-src #24488). It was fixed in PHP’s source on October 22 and isn’t in a release yet. It is a crash, not a security hole; going back to an unfixed PHP is worse.
- Optional: set
expose_php = 0so your server stops advertising its PHP version, and use AppArmor or SELinux to limit what PHP can run. Neither fixes PHP2Shell; both are cheap hardening.
About online checkers: Assetnote’s scanner, and Aikido’s web checker built on its approach, test by pushing PHP toward its memory limit, so the deeper checks can crash a worker. Only run them against sites you own. A clean result doesn’t prove you’re patched: Aikido’s Philippe Dourassov says their checker works up to a memory_limit of about 900 MB, and Assetnote documents false alarms on fixed PHP in some low-memory configurations. The installed package is the answer; a checker is a second opinion.
Signs your site may already be compromised
Attacks began before the fix was released, so a site that was exposed on October 20–21 is worth checking even after patching. An attacker who succeeds runs code with your site’s own permissions, so they can change your site’s files and read its configuration, including database passwords.
What to check:
- Admin or user accounts you didn’t create.
- PHP files you don’t recognize, especially in upload folders (
wp-content/uploadson WordPress,imagesortmpon Joomla), where PHP files rarely belong. Watch for double extensions such asphoto.php.jpg. - Core, theme, or plugin files changed recently when you didn’t update anything.
- Redirects to other sites, spam pages, or new links you didn’t add.
- New scheduled tasks or cron jobs, or a sudden jump in outgoing email.
- Warnings from Google Search Console, your browser, or your host.
- On your own server: new SSH keys in
authorized_keys, a burst of “Allowed memory size exhausted” errors or PHP worker crashes around October 20–21, and the web server starting shells or download tools such ascurlorwget. Elastic Security Labs notes that last one is how PHP break-ins usually show up, whatever the flaw. None of these prove an attack on their own.
If you find any of these:
- Put the site into maintenance mode or take it offline, and tell your host.
- Restore from a verified clean backup taken before the compromise. If you can't tell when that was, choose one from before October 20, 2026, when attacks began. Patch PHP before bringing the site back.
- Change every password: hosting, control panel, database, FTP/SFTP, and all site admins.
- Replace secret keys stored in configuration (WordPress salts in
wp-config.php, Joomla’ssecretinconfiguration.php) and any API keys the site holds. - If the site handles customer data or payments, get professional help; you may have notification obligations.
Found nothing? Rotate your secrets anyway if the site ran unpatched PHP while attacks were under way. The memory leak leaves almost nothing to find, so a clean check can’t rule it out. Changing the database password, salts, and API keys costs an hour.
No clean backup? Your host’s security team or an incident response service can help with cleanup.
Free help from Witen
Updating PHP is the fix; nothing we offer replaces it. Blocking known attackers is useful defense in depth while you get there, and these are free:
- Witen Blocker for WordPress: blocks IPs our sensors have seen attacking sites, plus login lockout and two-factor sign-in.
- Warden for Linux servers: blocks attackers at the server firewall.
- IP reputation lookup: check an address from your logs against what we’ve observed.
Questions about this guide: support@witenlabs.com.
Sources
- PHP security advisory, October 21, 2026
- PHP informational advisory on session upload progress, October 23, 2026
- PHP ships emergency patches for critical PHP2Shell flaws (BleepingComputer)
- PHP2Shell: Critical PHP RCE (Sansec)
- PHP2Shell (the researchers’ site)
- Sury PHP repository for Debian and Ubuntu (packages.sury.org)
- Sury PHP PPA for Ubuntu (ppa:ondrej/php)
- Remi’s RPM repository (rpms.remirepo.net)
- PHP version 8.2.35, 8.3.36, 8.4.27 and 8.5.12 (Remi’s blog)
- Debian security tracker: CVE-2026-109618
- Ubuntu security: CVE-2026-109618
- PHP’s new memory_hard_limit_percent setting (Mattias Geniar)
- Cloudflare deploys protections against php2shell vulnerability
- php2shell: Assessing Elastic detection coverage (Elastic Security Labs)
- php2shell-protection (Syhunt)
- php2shell-scanner (Assetnote)
- SimpleXML regression in 8.4.27 and 8.5.12 (php-src #24488)