跪拜 Guibai
← All articles
PHP · Security

PHP2Shell: PHP Engine's 9.2 CVEs Are Live, and nginx Had Its Own Three 9.2s the Same Week

By 程序员天天困 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

All PHP runtimes below 8.2.35, 8.3.36, 8.4.27, or 8.5.12 are exposed to unauthenticated RCE, and public scanning started within minutes of the patch release; shared hosting makes the memory disclosure a tenant-to-tenant risk. The fix is a runtime upgrade, not a WordPress or WAF change, and sites that stayed exposed until patching should rotate secrets.

Summary

PHP2Shell is a pair of CVEs in PHP's engine, CVE-2026-109618 and CVE-2026-109619, rated 9.2. They turn allocation failures during multipart request parsing and cleanup into an unauthenticated remote code execution chain, plus a memory leak that can expose passwords, tokens, API keys, and certificates by URL-encoding freed memory into a PHPSESSID cookie. WordPress, Drupal, and Joomla are all in the demonstration targets, but the bugs are in PHP itself, so core, theme, plugin, or WAF updates cannot reach them.

The disclosure timeline broke early: CVE numbers leaked on Oct 20 with an incorrect 10.0 score, a Calif researcher's PoC video spread, and Chainguard published patched images about six hours before the official release. The PHP Foundation says a known OOM issue from its 2024 external audit stayed unfixed for months because every fix route touched compatibility, DoS surface, or third-party extensions, and the team decides by consensus. An Aug 11, 2026 RCE report from Ryan A, with independent reports from OpenAI and Wiz, made it the top priority.

The same patch week included two separate issues: nginx fixed three CVSS 9.2 memory bugs in 1.30.6 and 1.31.7, and Node.js fixed a Brotli decoder out-of-bounds write. A Go x509 certificate-chain issue is frequently miscalled RCE but is actually a MITM-capable missing intermediate-CA check. Immediate mitigation is version-specific: upgrade PHP to 8.2.35, 8.3.36, 8.4.27, or 8.5.12, use memory_limit=-1 and a smaller post_max_size for 109618, restart workers, and inspect logs for signs of exploitation.

Takeaways
— CVE-2026-109618 and CVE-2026-109619 are two PHP engine memory-corruption bugs rated CVSS 9.2, and attackers can trigger both without authentication.
— The real attack surface is PHP's early RFC 1867 multipart parsing: an allocation failure during request cleanup leaves global state pointing at freed memory, and the next request on the same worker can reuse that memory.
— A second primitive leaks memory by putting a freed PS(id) pointer into the PHPSESSID response cookie after URL encoding, defeating ASLR even when the app never calls session_start().
— CVE-2026-109619 also reaches a stale fatal-error backtrace and an OPcache type confusion in zend_accel_script_persist(), so fixing a single worker process is not enough.
— Patched versions are 8.2.35, 8.3.36, 8.4.27, and 8.5.12; PHP 7.4, 8.0, and 8.1 got minimal source backport branches, and distro or LTS vendors may have backported packages.
— The official temporary mitigation for 109618 is memory_limit=-1 set in the FPM pool or Apache php_admin_value, plus a smaller post_max_size; session.upload_progress.enabled=0 only covers part of 109619.
— nginx is not part of PHP2Shell, but nginx 1.30.6 and 1.31.7 fixed three separate CVSS 9.2 memory bugs: CVE-2026-15176, CVE-2026-93479, and CVE-2026-97205.
— Node.js fixed a Brotli decoder out-of-bounds write, CVE-2026-111497, in versions 22.23.4, 24.22.1, and 26.12.1.
— Go's CVE-2026-111943 is a missing x509 known-compromised intermediate-CA check allowing MITM, not an RCE; it is fixed before versions 1.26.10 and 1.27.3.
— If warning signals such as large form submissions, PHPSESSID cookie anomalies, or worker restarts appeared between Oct 21 and patching, rotate database passwords, API keys, and session keys.
Conclusions

A leaked PoC video and a wrong 10.0 score expanded the attack window as much as the vulnerabilities themselves; Dutch government services went offline before a patch existed because after public disclosure, inaction was riskier than downtime.

The PHP Foundation's postmortem puts the decade-long gap on process and staffing, not detection: the 2024 external audit surfaced the OOM issue, but consensus-based security decisions with no clear exploitation path let it sit until external RCE reports forced a priority change.

Wiz's claim that one researcher in one week reproduced what used to take a team months is the concrete reason exploit complexity is no longer a valid risk-assessment defense.

The memory disclosure path has a wider blast radius than the RCE path on shared hosts: victims get no crash or error, and an oversized PHPSESSID cookie is the only clue that another tenant's memory just crossed the request.

Concepts & terms
PHP2Shell
The name Wiz gave to the combined exploitation chain for CVE-2026-109618 and CVE-2026-109619, which lets an unauthenticated attacker run commands on a server running a vulnerable PHP runtime.
Use-after-free (UAF)
A memory-safety bug where a program keeps using a pointer after the memory it points to has been freed. An attacker can reallocate that region with controlled data, turning the stale reference into a write or read primitive.
OPcache
PHP's shared-memory cache for compiled script structures. Multiple PHP workers share it, so a corrupted entry can spread across requests and processes.
RFC 1867
The specification for multipart/form-data, the encoding used by HTTP file uploads. PHP parses it at request startup, before regular module initialization, which is why upload-progress session handling runs in a very early attack window.
ASLR
Address Space Layout Randomization, a defense that randomizes memory addresses. The PHPSESSID memory leak in the exploit chain defeats ASLR by disclosing internal pointers, making the memory-corruption bugs reliably exploitable.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗