PHP2Shell CVE-2026-109618 and CVE-2026-109619: Unauthenticated RCE in PHP Core, Patch Every Web Server
Introduction
PHP pushed an emergency release on October 21 for two core memory-safety bugs, CVE-2026-109618 and CVE-2026-109619, nicknamed "PHP2Shell". Both score CVSS v4.0 9.2 and both lead to unauthenticated remote code execution as the web worker — on Apache with mod_php the trigger fires before any application code runs. The CVE IDs leaked a day early, a PoC demo video followed, and CISA told everyone to patch immediately. Update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 today; if you cannot, apply the ini mitigations below and take EOL PHP off the internet.
What Happened
The two flaws, per the PHP Foundation and the GitHub advisories:
- CVE-2026-109618 (GHSA-w8hw-w9fx-j79w) — memory corruption in out-of-memory handling. If a request hits
memory_limitat the wrong moment, PHP can leave half-initialized internal data that cleanup later treats as valid. On Apache mod_php, an unauthenticated request triggers it before application code runs, and the reporter demonstrated full RCE with default settings. RCE was also confirmed on PHP-FPM through application-level code paths. - CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp) — use-after-free from stale global state. A fatal error at the wrong point can leave internal state pointing at a previous request's freed memory; the next request on the same worker then uses it. Confirmed worker crash and memory disclosure, with RCE demonstrated against a real-world application on mod_php.
The OOM bug was reported by Ryan A at Calif on August 11, 2026, under its Patch the Planet audit, with independent reports from Wiz (August 24) and OpenAI Codex Security (September 18). Early signs of the root cause had actually been spotted in 2024 during the Quarkslab audit funded through OSTIF and the Sovereign Tech Agency.
The disclosure did not go to plan:
| Time (UTC) | Event |
|---|---|
| Oct 20, ~15:00 | Both CVE IDs circulate on forums and social media with a wrong date and an incorrect CVSS 10.0 |
| Oct 20, 19:30 | PHP publishes its pre-announcement early; release moved from Oct 22 to Oct 21 |
| Oct 20, ~20:00 | Calif mistakenly posts a video of its PoC hitting several targets |
| Oct 21, 07:41 | Chainguard ships fixed images six-plus hours before the coordinated release |
| Oct 21, 14:00 | PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 released; CISA alert the same day |
After release, Calif and Wiz published technical write-ups, with Wiz showing unauthenticated RCE against WordPress, Drupal and Joomla. Exploitation status as of October 22 is mixed: the PHP security team found no functional public exploits at release, CISA had not observed exploitation, Huntress saw none across its partner base, and Rapid7 said public PoCs only work against narrow OS/version/server combinations. Qualys, however, cited Cloudflare seeing attack traffic aimed at the flaws, and Rapid7 has seen reports of attempts. Treat it as weaponization in progress.
Why It Matters
This is the PHP interpreter, not a plugin. Every WordPress, Drupal, Joomla, Magento, Laravel and Nextcloud install inherits it, as do the hosting panels, admin consoles and appliances that embed PHP quietly — Cisco has already published a product advisory. On mod_php there is no application-level control that helps, because the bug fires during request startup.
Shared hosting is the worst case. A single worker process serves many tenants in sequence, CVE-2026-109619 is literally about one request touching another request's memory, and a webshell on a cPanel or Plesk box is a foothold into every site on it. Add a long tail of PHP 7.4/8.0/8.1 installs that will never get a distro update, and this has the shape of a months-long mass-exploitation campaign once a reliable chain lands.
Who Is Affected
- Every PHP installation serving web requests below the fixed builds: PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed.
- Highest risk: Apache mod_php (both CVEs, pre-application trigger). PHP-FPM is confirmed for CVE-2026-109618 via application paths.
- Fixed upstream releases:
| Branch | Fixed in |
|---|---|
| 8.5 | 8.5.12 |
| 8.4 | 8.4.27 |
| 8.3 | 8.3.36 |
| 8.2 | 8.2.35 |
| 8.1 and older | EOL — minimal source backports exist for 7.4, 8.0, 8.1; otherwise vendor LTS or upgrade |
- Distribution and LTS vendors received patches before publication — check your vendor's advisory. Remi's repository (
rpms.remirepo.net) did not have builds on release day. - Products that bundle PHP (network appliances, panels, NAS UIs) — follow each vendor's advisory.
How to Protect Yourself
1. Inventory every PHP that answers HTTP
Include containers and the PHP embedded in other products. Check the binary the web server actually loads, not just the CLI on $PATH:
php -v
php-fpm -v 2>/dev/null; ls /usr/sbin/php-fpm* 2>/dev/null | xargs -I{} sh -c '{} -v'
# is mod_php loaded?
apachectl -M 2>/dev/null | grep -i php
httpd -M 2>/dev/null | grep -i php
# distro package versions
dpkg -l | grep -E '^ii\s+php[0-9.]*-(common|fpm|cgi)|libapache2-mod-php'
rpm -qa | grep -Ei '^php|mod_php'
# containers
docker ps --format '{{.Names}} {{.Image}}' | while read n i; do echo "$n: $(docker exec "$n" php -r 'echo PHP_VERSION;' 2>/dev/null)"; done
2. Patch to a fixed build and restart workers
# Debian / Ubuntu
sudo apt update && sudo apt install --only-upgrade 'php*'
sudo systemctl restart 'php*-fpm' apache2
# RHEL / Alma / Rocky
sudo dnf upgrade 'php*'
sudo systemctl restart php-fpm httpd
# Docker: bump the base image and rebuild, e.g. php:8.4.27-fpm / php:8.3.36-apache
grep -rnE '^FROM .*php:' --include=Dockerfile* .
Only an update containing both fixes fully remediates. Prioritize internet-facing mod_php hosts first.
3. If you cannot patch today, apply the interim mitigations
These reduce exposure; none of them is a fix. Set them at the server level (php.ini, FPM pool, or vhost config) — ini_set() and .user.ini are applied too late to help.
; blocks the known session path for CVE-2026-109619
session.upload_progress.enabled = 0
; PHP 8.5 only
fatal_error_backtraces = 0
; keep request bodies small
post_max_size = 8M
upload_max_filesize = 8M
Rapid7 also documents setting memory_limit=-1 administratively to remove the predictable OOM the CVE-2026-109618 path relies on — weigh that against your memory headroom. Don't use cgroup kills or RLIMIT_AS / RLIMIT_DATA as a substitute: they can push PHP into the vulnerable path. Silencing errors (display_errors, @) does nothing. At the edge, cap request size, multipart part counts and header sizes, and block multipart entirely where the app does not take uploads.
If you run PHP 8.1 or older with no vendor fix, CISA's guidance is blunt: take it offline or put it behind a VPN or WAF until it is upgraded.
4. Hunt for post-exploitation
The tell is a PHP worker spawning things PHP workers should not spawn. Huntress recommends alerting on php-fpm, php-cgi, httpd and apache2 parenting shells, interpreters or download tools:
# live: children of web/PHP workers
ps -eo pid,ppid,user,comm,args --forest | grep -A3 -E '[p]hp-fpm|[a]pache2|[h]ttpd|[p]hp-cgi' | grep -E 'sh |bash|python|perl|curl|wget|nc |mkfifo|/dev/tcp'
# auditd: commands executed by the web user since disclosure
sudo ausearch -ua www-data -sc execve -ts 10/20/2026 -i 2>/dev/null | grep -E 'proctitle=.*(whoami|id|uname|curl|wget|bash|sh -c)'
# new or changed PHP files in web roots since the leak
find /var/www /srv /home/*/public_html -name '*.php' -newermt '2026-10-20' -type f 2>/dev/null
# persistence
sudo ls -la /etc/cron.* /var/spool/cron/crontabs 2>/dev/null; crontab -u www-data -l 2>/dev/null
Also watch error logs for worker segfaults, which is what today's unreliable PoCs produce:
sudo grep -hE 'child [0-9]+ exited on signal (11|6)|SIGSEGV|segfault' /var/log/php*-fpm.log /var/log/apache2/error.log /var/log/httpd/error_log 2>/dev/null
dmesg -T | grep -Ei 'php|apache2|httpd' | grep -i segfault
If you find a hit, isolate the host, preserve web server and PHP logs, and look for webshells, new accounts and scheduled tasks. Rotate anything the web user could read — wp-config.php, .env, database credentials, API keys — before you bring it back.
5. Get off end-of-life PHP
Moving to 8.4 or 8.5 is the only path that will keep getting fixes like this one. Use the backports for EOL branches strictly as a bridge.
Source
- PHP Foundation — Today's PHP Security Release, and How We're Strengthening PHP Security
- CISA — Critical Vulnerabilities in PHP Require Immediate Patching
- Rapid7 — CVE-2026-109618 and CVE-2026-109619: Critical Unauthenticated Remote Code Execution in PHP
- Huntress — Rapid Response: php2shell, Leaked Critical PHP Vulnerabilities
- Qualys — Two Critical PHP Flaws Could Hand Attackers Your Web Servers
- Cisco — Vulnerabilities in PHP Affecting Cisco Products: October 2026