PHP2Shell is the name for two remote code execution vulnerabilities in PHP core, CVE-2026-109618 (memory corruption when PHP runs out of memory mid-request) and CVE-2026-109619 (request state that survives into the next request on the same worker). Both are rated 9.2 on CVSS v4, need no authentication, and trigger during request parsing, before application code runs. Fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 on October 21, 2026; exploitation attempts were seen before disclosure.
What PHP2Shell is
PHP2Shell covers two bugs in the PHP interpreter, not in any framework or plugin. That is what makes it so broad: PHP serves most websites with a known server-side language, including WordPress, Drupal, Joomla, Magento and Laravel apps, and it is bundled with control panels such as cPanel and Plesk.
- CVE-2026-109618, "RCE via OOM corruption." PHP handles out-of-memory errors with a
longjmp()that aborts the current context. If that happens while PHP is still building request data, such as parsing a multipart upload, the abort leaves structures half-initialized. Request cleanup then treats the invalid data as valid, which gives an attacker a memory-corruption primitive. The patch removeslongjmp()for out-of-memory errors. - CVE-2026-109619, "RCE via stale global state." PHP keeps some request-owned internal state alive after its memory is freed. A later request handled by the same worker can use that stale state before normal initialization resets it. Confirmed paths are
session.upload_progress, which is enabled by default, and, on PHP 8.5, fatal-error backtraces.
The two advisories share a root cause and are tracked together. Both are scored 9.2 (Critical) on CVSS v4; the attack complexity is rated high, which is why some researchers could not reproduce code execution on every default install. Treat that as a reason for urgency, not comfort.
How the attack works
The entry point is an ordinary HTTP request. The project's own advisory describes a demonstrated exploit against Apache with mod_php where an unauthenticated request triggers the attack before any application code runs. Shown for defensive context, the shape a defender should recognize is:
- A `multipart/form-data` POST to any PHP endpoint, including ones that never expect uploads, built to push PHP to its
memory_limitwhile the body is being parsed. - Requests that carry a `PHP_SESSION_UPLOAD_PROGRESS` field, which drives the default-on upload-progress tracking involved in CVE-2026-109619.
- Repeated attempts against the same worker pool, since the stale-state path depends on a later request landing on the same PHP worker.
Every common deployment is in scope: PHP-FPM, Apache mod_php (rated highest risk), php-cgi, FrankenPHP and LiteSpeed. Amazon threat intelligence reported an exploitation attempt in its honeypots on October 17, 2026, four days before the fixes shipped, and broad exploitation attempts followed disclosure.
How to check if you are exposed
Check the PHP binary that actually serves traffic, on every host and inside every container image:
- Version:
php -v, or for FPMphp-fpm -v. Vulnerable if below 8.2.35, 8.3.36, 8.4.27 or 8.5.12 on those branches. Branches 8.1 and older have no official upstream fix. - Upload progress:
php -i | grep session.upload_progress.enabled. A value of On means the CVE-2026-109619 path is open. - Distribution packages: your OS vendor may ship a patched build with an older-looking version number. Check the vendor advisory for the package release that contains the fix.
- Logs to hunt: multipart POSTs followed by
Allowed memory size exhaustedfatal errors, bursts of HTTP 500s, or PHP-FPM workers exiting onSIGSEGV. Any web server process spawningsh,curlorwgetis a strong compromise signal.
How to fix and mitigate
Upgrading PHP is the only complete fix, according to the project's advisories. Upgrade to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 (or your vendor's patched build), restart every PHP worker and rebuild container images.
If you cannot patch immediately, the advisories list partial mitigations. Set them in php.ini, the FPM pool or server config, not with ini_set() or .user.ini, because they must apply before request parsing:
- Set `session.upload_progress.enabled=0` if you do not use upload progress. On PHP 8.5, also set
fatal_error_backtraces=0. - Set `memory_limit=-1` administratively (for example
php_admin_value) so attackers cannot trigger the out-of-memory path, and cap memory with a container or cgroup limit instead. Do not useRLIMIT_ASorRLIMIT_DATA. - Keep `post_max_size` conservative and enforce request size, part count and header limits at the reverse proxy.
- Block `multipart/form-data` at the edge on applications that never accept uploads.
Once patched, assume earlier probing may have succeeded and hunt for web shells and unexpected outbound connections.
References
- [1]PHP security advisory GHSA-w8hw-w9fx-j79w (CVE-2026-109618)(PHP)
- [2]PHP security advisory GHSA-6wmf-4rv5-p3rp (CVE-2026-109619)(PHP)
- [3]NVD: CVE-2026-109618(NIST NVD)
- [4]NVD: CVE-2026-109619(NIST NVD)
- [5]PHP 8 ChangeLog(PHP)
- [6]AWS Security Blog: PHP2Shell exploitation prior to public disclosure(AWS)
- [7]MITRE ATT&CK: Exploit Public-Facing Application (T1190)(MITRE)