PHP2Shell: Critical Unauthenticated RCE in PHP — What to Do
Two critical vulnerabilities disclosed this week in the PHP engine itself — CVE-2026-109618 and CVE-2026-109619, together nicknamed PHP2Shell — let an anonymous attacker run their own code on your server before your application code even executes. Both are rated CVSS v4.0 9.2 out of 10, both need no authentication, and the flaws have shipped in every PHP release since 5.4 (2012). Roughly 70 percent of the web runs on PHP. Your own code being clean does not protect you.
How the week unfolded
Details leaked on social media ahead of a coordinated disclosure planned for October 22, so the PHP team moved the emergency release forward to October 21, 14:00 UTC. Attack traffic was already arriving before the patch existed — Cloudflare logged probes at 07:43 that morning, six hours earlier. A public exploit tool is expected imminently.
CVE-2026-109618: code execution through memory exhaustion
When a memory allocation fails in the middle of a request, PHP can abandon the request while its internal data structures are only partially initialized. The cleanup routines then run anyway — and treat that invalid, half-built data as if it were valid. An attacker forces this state with a crafted multipart request that exhausts memory while appearing to fit your configured size limits.
Under Apache mod_php, cleanup runs even when request startup fails, so the exploit fires before any line of your application executes — over plain HTTP, with default limits, across every prefork worker.
CVE-2026-109619: code execution through stale state
Internal state that belongs to one request can survive after its backing memory is freed. The next request handled by the same worker may consume that stale state before normal initialization resets it — a use-after-free turned into code execution, validated against both mod_php and PHP-FPM.
The confirmed trigger paths need nothing exotic: session upload progress (enabled by default — the application never has to call session_start()) and, on PHP 8.5, fatal-error backtraces (also default-on).
Who is affected
Every PHP installation that serves web requests — PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed — with mod_php rated highest risk. Unauthenticated code execution was demonstrated against real software: Magento 2.4.9, WordPress 7.1.2, Drupal 11.4.3, Joomla 6.1.4, MediaWiki, Roundcube, phpMyAdmin, Nextcloud, Laravel, Symfony and WHMCS. Because the flaw is in the engine, an application being bug-free changes nothing.
It is not only code execution. Researchers also demonstrated unauthenticated disclosure of worker memory — passwords, session tokens, API keys and TLS private keys — reachable through a PHP session cookie. Treat any pre-patch exposure as a potential secrets leak.
What does not protect you
The first 24 hours produced a wave of advice that ranges from useless to actively harmful. The documented failures:
RLIMIT_AS / RLIMIT_DATA limits. Actively harmful — they can cause the exact allocation failure that triggers CVE-2026-109618. The vendor warns against them explicitly.
Hiding errors with error_reporting, display_errors or @. That changes what you see, not what the engine does. Hiding errors does not prevent stale-state access.
Setting session.upload_progress.enabled=0 via ini_set() or .user.ini. Too late — those apply after request parsing has already touched the vulnerable path. The setting must be made administratively, before parsing, then workers restarted.
A container or cgroup memory limit as the fix. Allocation failures remain possible; at best it is an availability boundary, and if workers are not isolated it can kill the master and every worker at once.
Trusting the WAF. The exploit rides crafted but ordinary-looking multipart traffic within normal size limits; Cloudflare already observed evasion attempts. A WAF is defense in depth, not remediation.
“No suspicious logs, so we are safe.” Absence of log entries is not evidence of safety — successful memory-corruption exploitation leaves no tell-tale PHP error.
Waiting for the next patch window. Attack traffic predates the patch itself; this is an emergency, out-of-cycle update.
How to protect yourself
One sentence from the official advisory governs everything: there are no complete mitigations — updating is the only safe choice. Update to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 depending on your branch — released October 21, available from php.net, your Linux distribution or LTS vendor, and the official Docker images. PHP 8.1, 8.0 and 7.4 have source-only backports; Remi’s repository has nothing for this.
After patching: restart every PHP worker and verify the running version, not the package version (php-fpm -i or a phpinfo() page). Then rotate the secrets your web tier can reach — database passwords, API keys and, if pre-patch exposure is plausible, TLS private keys. Check web roots for unexpected files, and plan the exits: PHP 8.2 reaches end of life on December 31, 2026.
If you cannot patch today
These reduce specific attack paths while you schedule the update; they do not make an unpatched installation safe. Apply them at the administrative layer (php.ini, FPM pool or Apache config) so applications cannot override them, restart workers, and remember each has costs.
; --- CVE-2026-109618: remove the predictable OOM trigger ---
memory_limit = -1 ; admin-level only; verify nothing restores a finite limit
post_max_size = 8M ; 32M if you need uploads; keep upload_max_filesize below it
; --- CVE-2026-109619: close the confirmed stale-state paths ---
session.upload_progress.enabled = 0
fatal_error_backtraces = 0 ; PHP 8.5 only
; optional, at a performance cost:
; pm.max_requests = 1 ; FPM: fresh worker per request Where to read more
The authoritative source is the official announcement on php.net, with the individual advisories GHSA-w8hw-w9fx-j79w and GHSA-6wmf-4rv5-p3rp. First-responder analysis worth reading: Qualys, Rapid7, Sansec, watchTowr, CERT-EU 2026-018 and the NCSC-UK notice.