PHP2Shell (CVE-2026-109618 / 109619): critical PHP RCE, patch out today at 14:00 UTC

Mitigation is in progress, so this quick post was generated with help of Claude Code CLI.

If you run anything on PHP (WordPress, Nextcloud, Matomo, phpMyAdmin, a cPanel box, that old homelab dashboard you forgot about), today is patch day.

Two critical flaws in PHP core, CVE-2026-109618 and CVE-2026-109619 (CVSS v4.0 9.2), leaked ahead of coordinated disclosure. They can allow remote code execution, possibly without authentication. PHP moved its emergency release up to Wednesday 21 Oct, 14:00 UTC (10:00 AM ET) and has said it may ship earlier if exploitation starts.

  • watchTowr says it reproduced CVE-2026-109618.
  • A public “PoC” is circulating, and it is disputed. Please don’t run random exploit code from GitHub or X on your own boxes.
  • No confirmed in-the-wild exploitation yet, but Sansec expects mass scanning within ~15 minutes of the release.

Only supported branches get a fix! = PHP 8.2, 8.3, 8.4, 8.5.

8.1, 8.0, 7.x and 5.x are end-of-life and get nothing. If you’re on one of those, upgrading is the fix. Your distro or panel vendor (Remi, CloudLinux/TuxCare, Ubuntu ESM, etc.) may backport on its own schedule, but don’t count on it.

The php.ini stopgap (and why it’s not enough)

The widely shared mitigation is:

session.upload_progress.enabled = 0
session.use_strict_mode = 1

It’s harmless for most sites, so it’s worth applying. But GMO Flatt expects bypasses, and a PHP core developer put it bluntly: “the only mitigation is patching/upgrading PHP.” Also check that it applies to the SAPI actually serving traffic (FPM/mod_php), not just the CLI:

php-fpm -i | grep -E 'upload_progress.enabled|use_strict_mode'

What I did late last night

I manage a few dozen clients servers that this would affect, so last night looked like this:

  • Applied the stopgap on every PHP server (one Termius snippet: drop the ini file, reload FPM/Apache, print versions)
  • Inventoried PHP versions everywhere and found the EOL stragglers (7.2, 7.4, 8.1)
  • Moved what I could to 8.3 overnight; scheduled the rest
  • Set a script to poll php.net’s release JSON plus the package repos every 15 min overnight and notify me if there was an early release.

Today at release: dnf/yum/apt update the PHP packages, reload FPM, confirm php -v everywhere, then watch for PHP workers spawning shells.

Quick checklist

  • php -v on every box, and note any EOL versions
  • Apply the stopgap now
  • Patch as soon as packages land
  • Plan upgrades for anything older than 8.2
  • Watch logs for php-fpm / httpd spawning sh, curl, wget, etc.

Reading

What PHP versions are you still finding in the wild?

2 Likes

Update: the patch is out (released ~09:40 ET, earlier than announced)

Fixed versions: 8.2.35, 8.3.36, 8.4.27, 8.5.12. Distros backported to their own version numbers:

  • Ubuntu 24.04: php8.3 8.3.6-0ubuntu0.24.04.13
  • Ubuntu 22.04: php8.1 8.1.2-1ubuntu2.28 (yes, Ubuntu patched 8.1)
  • cPanel EA4 pushed an “expedited” update around 10:09 ET. Most servers patched themselves.
  • Ondřej’s PPA has 8.2.35 for 22.04, but Launchpad is throwing 503s under load (see the retry loop below).

1. Find every PHP on the box (not just the CLI)

for p in /usr/bin/php[0-9]* /usr/sbin/php-fpm* /opt/cpanel/ea-php*/root/usr/bin/php /opt/remi/php*/root/usr/bin/php /usr/local/bin/php; do
  [ -x "$p" ] && printf '%-45s %s\n' "$p" "$($p -v 2>/dev/null | head -1)"
done
# which one actually serves traffic?
systemctl list-units --type=service --state=running | grep -Ei 'php|fpm'
apachectl -M 2>/dev/null | grep -i php     # mod_php = highest risk per the advisory

2. Patch

# Debian/Ubuntu (only upgrades PHP packages you already have)
sudo apt update && sudo apt install --only-upgrade $(dpkg -l 'php*' | awk '/^ii/{print $2}')
# RHEL/Alma/Rocky (Remi modules)
sudo dnf --refresh upgrade 'php*'
# cPanel
/usr/local/cpanel/scripts/upcp --security && /scripts/restartsrv_apache_php_fpm

# restart FPM so workers actually load the new build
sudo systemctl restart 'php*-fpm.service'

PPA 503s? Retry until the index downloads:

until sudo apt update 2>&1 | tee /tmp/apt.log >/dev/null; ! grep -q 503 /tmp/apt.log; do sleep 30; done

3. Verify the fix is in the package, not just the version string

apt changelog php8.3-common 2>/dev/null | grep -m2 -E 'CVE-2026-10961[89]'
rpm -q --changelog ea-php83-php-common | grep -m2 -E 'CVE-2026-10961[89]'
# and check the stopgap on the SAPI that serves traffic, not the CLI:
php-fpm8.3 -i | grep -E 'upload_progress.enabled|post_max_size'

4. Extra mitigation from PHP’s advisory (until you can patch)

  • post_max_size = 32M if you need uploads (8M if not), with upload_max_filesize below it.
    Set it as php_admin_value in the FPM pool so apps can’t override it.
  • Don’t “fix” it with memory_limit=-1 or RLIMIT_AS; the advisory says both can still reach the bug.
  • session.upload_progress.enabled=0 must be in php.ini or the pool, not ini_set() or .user.ini.

5. Quick compromise check

# web workers that have spawned a shell or downloader
pstree -ap | grep -A3 -E 'php-fpm|apache2|httpd|lsphp' | grep -E '\b(sh|bash|dash|curl|wget|nc|python3?|perl)\b'
# PHP files changed since the release
find /var/www /home/*/public_html -name '*.php' -newermt '2026-10-21 13:00' -ls 2>/dev/null | head -50

Still on 7.x / 8.0 / 8.1 from upstream? No fix is coming. Upgrade, or move to a distro that backports (Ubuntu’s 8.1 got patched).


Saved myself for last. Linuxblog.io was down for ~ 1 hour. I was too tired last night to start Ubuntu 20.04 → 20.04 → 24.04 LTS at 3:30am… so just completed that now, started it right when the release went live. Back online now.

1 Like