Security Digest · Oct 21, 2026 · Vulnerability · Language runtime

PHP2Shell: Critical Unauthenticated RCE in PHP

Two PHP engine bugs allow unauthenticated RCE on PHP serving web requests. Fixed in 8.5.12/8.4.27/8.3.36/8.2.35. Attacks seen. Patch today.

Our verdict

Act now

If PHP answers HTTP requests anywhere you run it, patch or apply a vendor fix today; this is pre-application, unauthenticated, and attack traffic started before the patch shipped.

Who must act: Anyone running PHP behind a web server (mod_php, PHP-FPM, php-cgi, FrankenPHP, LiteSpeed), including WordPress, Drupal, Magento, Laravel and appliance or container images that bundle PHP.

Who can relax: Hosts where PHP is only used from the command line (scripts, cron, Composer) and never handles untrusted HTTP requests, and RHEL 7 or older, which Red Hat says ships unaffected PHP.

Affected
PHP 8.5.x before 8.5.12
PHP 8.4.x before 8.4.27
PHP 8.3.x before 8.3.36
PHP 8.2.x before 8.2.35
PHP 7.4, 8.0, 8.1 (EOL; source backports only)
PHP 5.4 through 7.3 (EOL; no upstream fix)
Fixed in
PHP 8.5.12
PHP 8.4.27
PHP 8.3.36
PHP 8.2.35
Debian 13 php8.4 8.4.27-1~deb13u1 (DSA-6574-1)
Debian 12 php8.2 8.2.35-1~deb12u1 (DLA-4848-1)
Ubuntu 24.04 php8.3 8.3.6-0ubuntu0.24.04.13
Ubuntu 22.04 php8.1 8.1.2-1ubuntu2.28
Official Docker php images rebuilt Oct 21, 2026
CVSS
9.2 (v4.0, vendor)
EPSS
Not yet scored
CISA KEV
Not listed
Exploitation
Exploited in the wild
Severity
Critical

What to do

  1. Inventory every PHP that serves HTTP: servers, containers, appliances, shared hosting.
  2. Upgrade to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or install your distribution's fixed package, then restart every PHP worker (php-fpm, Apache).
  3. Rebuild and redeploy container images from refreshed php:* or distro base images; do not just restart old containers.
  4. For PHP 7.4-8.1, use a vendor/LTS backport or the PHP team's source backport branches, or upgrade.
  5. If you cannot patch today: set session.upload_progress.enabled=0, enforce memory_limit=-1, set fatal_error_backtraces=0 on 8.5, block multipart/form-data where unused, and keep WAF rules on; otherwise take the site offline.
  6. Verify the version actually serving requests, not just the CLI binary.

How to check if you are affected or compromised

  • Check the running version from a web request (phpinfo behind auth, or the X-Powered-By header if enabled) and compare packages with dpkg -l 'php*' or rpm -qa 'php*'.
  • Look for bursts of multipart POSTs containing the upload-progress field followed by HTTP 500s or memory-limit errors.
  • Watch for unexplained PHP worker churn, segfaults, or oversized or malformed PHPSESSID cookies in responses.
  • Treat any exposed, unpatched host as possibly compromised: hunt for new PHP files, web shells, and unexpected child processes of php-fpm or httpd.

What happened#

On October 21, 2026, PHP shipped 8.5.12, 8.4.27, 8.3.36 and 8.2.35 to fix two engine bugs that "can allow unauthenticated remote code execution." CVE-2026-109618 ("RCE via OOM corruption") is a fault in out-of-memory handling: PHP bails out mid-initialization and request shutdown then trusts half-built state. CVE-2026-109619 ("RCE via stale global state") lets request state outlive its freed memory so the next request on the same worker uses it. Both are use-after-free class bugs, rated CVSS 4.0 9.2 by PHP. Red Hat scores it 8.1 on CVSS 3.1 and notes NVD's 9.8.

Wiz Research found the bugs, with Calif and OpenAI also credited as reporters. Wiz confirmed unauthenticated RCE against Drupal and WordPress in August. The triggering code dates to PHP 5.4 (2012), and a plain "Hello World" app is enough. Sansec lists demonstrated RCE against Magento, WordPress, Drupal, Joomla, MediaWiki, Nextcloud, phpMyAdmin, Laravel and Symfony.

Who is affected#

PHP says every installation serving web requests is at risk, whether it runs mod_php, PHP-FPM, php-cgi, FrankenPHP or LiteSpeed. The advisories rank the exposure by SAPI:

  • Apache mod_php: most exposed. RCE is confirmed with default limits, and the trigger fires while the request body is parsed, before any application code runs.
  • PHP-FPM: one path is blunted because FPM kills a child whose startup fails. Session-lifecycle RCE was still validated against FPM.
  • FrankenPHP and LiteSpeed (LSAPI): source analysis says likely susceptible, but this has not been validated.

PHP 8.1 and older get no upstream release. PHP published source backports for 7.4, 8.0 and 8.1. Versions 5.4 through 7.3 have no fix.

Do you really need to act?#

Yes, today, if PHP is reachable over HTTP. The attack needs no login and no plugin bug, because it lands in the engine before your code runs. Updating WordPress or your framework does nothing. Exploitation has started. Cloudflare saw attack traffic, including payloads mutated to evade its rules, after details leaked ahead of the release. watchTowr reports exploitation attempts, according to Tenable. Exploits are build-specific (the CVSS vector says "high complexity"), but public tooling closes that gap quickly. These CVEs were not in CISA KEV at the time of writing.

  • Distro PHP (Debian/Ubuntu/RHEL): watch for backported fixes that keep the old version string. Debian fixed trixie (8.4.27-1~deb13u1, DSA-6574-1) and bookworm (8.2.35-1~deb12u1, DLA-4848-1). Ubuntu fixed 24.04 (php8.3 8.3.6-0ubuntu0.24.04.13) and 22.04 (php8.1 8.1.2-1ubuntu2.28), with 20.04 and older through Ubuntu Pro. Red Hat lists RHEL 8, 9 and 10 as affected with updates rolling out, and RHEL 7 as unaffected. Sansec warns that the Remi repository had not shipped fixes on day one.
  • Containers: the official php images were rebuilt on October 21. Pull, rebuild and redeploy. Restarting an old image does not patch it.
  • Managed WordPress and shared hosting: the host owns PHP. Confirm with them in writing. Self-managed VPS installs are on you.
  • CLI-only PHP (cron, Composer, CI) is not on the documented attack path. Patch it on your normal cycle.
  • Behind Cloudflare: WAF rules help, but only for traffic that actually passes through Cloudflare. They are not a fix.

What to do now#

  1. Inventory every PHP install that answers HTTP, including ones bundled inside appliances. The UK NCSC stresses this step.
  2. Upgrade to a fixed release or your vendor's package (apt-get install --only-upgrade 'php8.*', dnf update 'php*'), then restart all workers: systemctl restart php8.3-fpm apache2.
  3. Verify from the web side, not the shell. php -v reports the CLI binary. Check dpkg -l 'php*' or rpm -qa 'php*', and confirm the version a live request reports.
  4. If you can't patch yet, apply PHP's temporary mitigations administratively and restart: session.upload_progress.enabled=0, enforced memory_limit=-1 (watch RAM), and fatal_error_backtraces=0 on 8.5. Block multipart/form-data where you don't use it. PHP says none of these is a complete fix, so failing that, take the site offline as Qualys and NCSC suggest.
  5. Do not use RLIMIT_AS/RLIMIT_DATA as a mitigation. PHP warns they can trigger the vulnerable path.

How to tell if you were hit#

Wiz notes that application logs may show little, because the bugs run below the app layer. Look for multipart POSTs carrying the upload-progress field followed by 500s or memory-limit errors, unusual PHP worker churn, and oversized or malformed PHPSESSID cookies. Any internet-facing host that was unpatched after October 20 deserves a hunt: new .php files in web roots, web shells, and unexpected shells or network tools spawned by php-fpm or httpd. Rotate the secrets those workers could read, because the bugs also leak process memory.

Timeline#

  • — Calif reports a first bug to PHP (per Sansec).
  • — Wiz reports its findings to PHP.
  • — CVE IDs leak around 15:00 UTC, and a researcher's exploit video is briefly posted. PHP moves the release up from Oct 22 to Oct 21, 14:00 UTC (Socket).
  • — Cloudflare rules go live at 03:02 UTC. Chainguard ships patched images at 07:41 UTC, which the PHP Foundation calls an embargo break. Fixed releases, the GHSAs and the Wiz write-up are published at 14:00 UTC. Debian and Ubuntu ship fixes, and the official Docker images are rebuilt.

Vulnerability records

  • CVE-2026-109618 · PHP uses longjmp() for out-of-memory (OOM) errors to exit the current context and abort handling of the request.
  • CVE-2026-109619 · PHP has various global state that temporarily points into request memory.

Sources

Original sources first: vendor and project advisories, CVE and government records, the discoverers’ write-ups. Every claim above links to one of these. See how the Security Desk works.

Original and primary sources

  1. PHP — Security advisory for PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 (Oct 21, 2026) php.net
  2. PHP — Upcoming critical PHP security release (Oct 20, 2026) php.net
  3. PHP / GitHub — GHSA-w8hw-w9fx-j79w: RCE via OOM corruption (CVE-2026-109618) github.com
  4. PHP / GitHub — GHSA-6wmf-4rv5-p3rp: RCE via stale global state (CVE-2026-109619) github.com
  5. Wiz Research — PHP2Shell wiz.io
  6. Tenable — PHP2Shell FAQ tenable.com
  7. Sansec — PHP2Shell: Critical PHP RCE sansec.io
  8. Cloudflare — Cloudflare deploys protections against php2shell blog.cloudflare.com
  9. Qualys — PHP2Shell: PHP patches two critical RCE vulnerabilities blog.qualys.com
  10. Debian security tracker — CVE-2026-109618 security-tracker.debian.org
  11. Ubuntu — CVE-2026-109618 ubuntu.com
  12. Red Hat — RHSB-2026-013 access.redhat.com
  13. Red Hat — CVE-2026-109618 access.redhat.com
  14. Docker official images — Update php to 8.5.12, 8.4.27, 8.3.36, 8.2.35 (#22541) github.com
  15. UK NCSC — Critical security issue affecting PHP ncsc.gov.uk
  16. Socket — PHP Foundation says Chainguard broke security embargo socket.dev