2026.10.24 · 5 min · security · backend · php · news
PHP2Shell: the PHP bug that lives between requests.
Two critical PHP engine bugs (CVSS 9.2) where one request leaves broken state behind and a later request on the same worker can turn it into remote code execution, before your app code runs. Who's affected, which versions fix it, how to check what's really serving your site, and what the stopgaps don't cover. As of 2026.10.
Your PHP code can be perfect and your site can still be exposed. PHP2Shell is two critical bugs in PHP itself, CVE-2026-109618 and CVE-2026-109619, and they sit in the runtime, before your app code even runs. PHP runs about 69% of sites with a known server-side language: WordPress, Laravel, Magento, shared hosting. The fix is to patch PHP, not your app.
Watch the 60-second version on Instagram.
What it is
"PHP2Shell" is the industry's name for the pair. php.net and the PHP Foundation don't use it; it came from a leaked proof of concept and video on 2026.10.20, and PHP shipped the security release on 2026.10.21.
- CVE-2026-109618: out-of-memory handling leaves request data half-built, and cleanup trusts it. The result is remote code execution.
- CVE-2026-109619: request state outlives its freed memory, and the next request on the same worker uses it: a use-after-free.
Both are CVSS v4.0 9.2. A "10.0" spread during the leak; it's wrong.
Why "between requests"
PHP workers are reused. One request finishes and the same worker picks up the next. In the use-after-free case, the first request leaves state behind, its memory is freed, and a later request on that worker reaches the stale state inside the engine. The figure is simplified on purpose: it shows where in time the bug sits, not how it's triggered.
That's why "my code is secure" doesn't help, and why an app-level WAF doesn't either: all of this happens inside PHP, before your code and before anything your code does to filter requests.
Who's affected
Every PHP serving web requests: PHP-FPM, mod_php, php-cgi, FrankenPHP and LiteSpeed. mod_php is the worst case: unauthenticated remote code execution before any app code was demonstrated there. The vulnerable code goes back to PHP 5.4, from 2012.
Which versions fix it
The readout at the top of the figure is an example server (8.3.35 to 8.3.36); the table is php.net's fix list.
| Branch | Fix |
|---|---|
| 8.5 | 8.5.12 |
| 8.4 | 8.4.27 |
| 8.3 | 8.3.36 |
| 8.2 | 8.2.35 |
| 7.4 to 8.1 | Source backports only: get them from your distro or an LTS vendor |
| 7.3 and older | No fix |
If you run the official Docker php image, note that it has no fix for 8.1 or older.
Check the PHP that serves your site
The trap here: php -v in your terminal shows the CLI binary, which may not be the one serving the web. Check the web side with phpinfo() or your package manager.
php -r 'echo PHP_VERSION;' # CLI only; verify the web SAPI via phpinfo()
# php.ini / FPM pool, then restart workers:
session.upload_progress.enabled = 0The last line is the interim mitigation, and it is partial. Set session.upload_progress.enabled = 0 in php.ini or the FPM pool, then restart the workers; ini_set and .user.ini don't count. On 8.5, also set fatal_error_backtraces=0. Upload progress is one path to the bug, not the only one, so patch anyway. (watchTowr calls .ini changes ineffective; php.net lists them as a partial mitigation. I follow php.net: partial, and patch.)
As a WAF stopgap, every known trigger uses multipart/form-data. Blocking it also breaks uploads and some checkouts, so it's a short-term trade, not a fix.
On a client project I'd treat this as a same-day runtime upgrade, and check the version the web server reports rather than trusting php -v on the box.
Is it being exploited?
Amazon, Cloudflare and watchTowr report exploitation attempts; Amazon saw one on 2026.10.17, before disclosure. As of 2026.10.23 it isn't in CISA's KEV catalogue. Sansec found that the public proofs of concept fail on default installs (most need an extra file-inclusion bug), so mass exploitation is "less likely" in their words. Less likely is not never.
What people get wrong
- "My code is secure, so I'm fine." The bug is in PHP, before your code runs.
- "I'll add a WAF rule." An app-level WAF runs after the engine. The only fix is upgrading PHP.
- "
php -vsays I'm patched." That's the CLI. Check the SAPI that serves the web. - "The patch closes it for good." Don't assume it: one researcher (Abstract Security) claims RCE on patched 8.2.35. It's unconfirmed; watch for follow-ups.
- "Raise
memory_limitto -1 to dodge the out-of-memory bug." That lets a single request eat all your RAM. - "Grab a PoC and test it." Unverified PoC code may contain malware.
Two more notes. A follow-up, CVE-2026-115560 (2026.10.23), is a separate and niche upload-progress issue. And the "1.3M exposed hosts" figure you may see is one researcher's estimate.
Isn't the answer to switch stacks?
No. Node.js fixed 10 CVEs the same day (4 high), including a Brotli zlib RCE and three TLS hostname-check bypasses, fixed in 26.12.1, 24.22.1 and 22.23.4. Node is also built in C and C++, and its long-lived process shares module-level state across all requests by design, so cross-request leaks are a known Node app bug too. Every runtime ships fixes. What a modern setup gives you is making the upgrade routine: pinned versions, containers rebuilt in CI, automated update PRs.
The short version
- PHP2Shell is CVE-2026-109618 and CVE-2026-109619, CVSS 9.2 each, in PHP itself.
- One request leaves broken state on a reused worker; a later one can turn it into RCE before app code runs.
- Upgrade to 8.5.12, 8.4.27, 8.3.36 or 8.2.35; 7.4 to 8.1 need a distro or LTS backport; 7.3 and older get no fix.
- Check the web SAPI's version, not
php -v. session.upload_progress.enabled = 0is a partial stopgap; patch anyway.
Sources: PHP News Archive 2026, 21 Oct security release · PHP Foundation, Today's PHP security release · Tenable, PHP2Shell FAQ · watchTowr, PHP2Shell RCE Exploited · Sansec, PHP2Shell · Node.js, October 2026 Security Releases · Abstract Security, PHP2Shell