TL;DR
- PHP2Shell [1] is two critical, unauthenticated remote code execution bugs in the PHP runtime, CVE-2026-109618 and CVE-2026-109619, fixed on 21 October 2026 in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 [2,3].
- Both bugs live in the interpreter's own memory handling [2,3].
- What a kernel-level LSM engine can do is cap what the compromised worker does next: no shell, no dropped binaries, no persistence writes, no bind shell, no injection into sibling workers.
- That matters most where patches arrive late or never: container images that bundle PHP, and embedded devices running PHP admin interfaces on end-of-life branches.
What happened
On 21 October 2026 the PHP project shipped a coordinated security release for two bugs its security team rates CVSS 9.2 [1,2,3]. Details leaked the day before and a proof-of-concept tool nicknamed "PHP2Shell" circulated [4]. Amazon's honeypots logged exploitation attempts from 17 October, four days before disclosure [5], and Cloudflare reported early attacks on the 21st [6]. Its CEO put the volume at thousands of attempts across Cloudflare's network in the 10 hours before disclosure, tens of thousands in the 45 minutes after, hundreds of thousands within two hours and millions since [7]; the PHP advisories themselves make no statement on in-the-wild use [2,3,4].
- CVE-2026-109618, "RCE via OOM corruption". When a request trips PHP's memory_limit, out-of-memory handling can leave request memory in an invalid state that request shutdown then processes [2].
- CVE-2026-109619, "RCE via stale global state". Request-owned state can survive into the next request handled by the same worker, leading to a use-after-free. The session upload-progress feature, on by default, is one validated path into it [3].
Both are reachable without authentication and before any application code runs [4], so a WAF or application-level filter offers little. The result in both cases is code execution as the web worker account [2,3].
Fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, plus the 8.6.0 RC4 pre-release. PHP 8.1 and older get no official release, only minimal source backports from the security team for 7.4 through 8.1 that distributions may ship [4].
Why "just patch" takes longer than a day
The fix is a runtime update, not an application change, and it only takes effect once every long-running worker has restarted. Across a fleet that is a schedule, not a command.
- Container images bundle their own PHP. A host update does nothing for them; each image has to be rebuilt, rescanned and redeployed, and the vulnerable image keeps serving traffic until then.
- Distribution packages on 8.1 and older depend on the security team's source-only backport reaching a distro build, and the result will never read 8.2.35.
- Embedded and edge devices are the long tail. Routers, NAS boxes, cameras, printers and industrial HMIs ship PHP-based admin interfaces, often on 7.x or 8.0, with firmware cycles measured in months or years. Many will never see this fix at all.
For that window, and for that tail, the useful question changes: assuming the exploit lands, what can the attacker actually do with it?
The first hop is a syscall
A successful exploit runs the attacker's code inside the PHP worker process that served the request, with that worker's privileges. The reported chains hijack a function call rather than inject shellcode, so there is nothing to see at the memory-protection level. The first observable effect is whatever the attacker's code asks the kernel for:
- A shell. Every PHP shell-out primitive, system(), exec(), shell_exec(), passthru(), popen(), proc_open(), forks and execs /bin/sh -c. An in-process reverse shell calls execve directly.
- A file write. A webshell under the docroot, or persistence in /etc/cron.d, ld.so.preload, a php.ini drop-in, an ssh key.
- A network call. A reverse shell or C2 beacon out, a bind shell in.
- A ptrace attach to a sibling worker, to outlive the end of the request.
Each of those crosses a Linux Security Module hook, and that is where Photon sits. Photon, Exein's runtime eBPF LSM engine, compiles TOML rules into eBPF programs on the device and attaches them behind hooks.
One kernel detail makes the first hop attributable without any process-tree tracking: the exec hook fires before the kernel swaps the task's memory map. At that moment the acting process still carries the php-fpm image, even when injected code calls execve in place rather than forking.
What Photon stops at each step
A containment policy follows the attacker through the steps that come after the exploit lands, with a kernel-level control at each one:
- Getting a shell. When the worker tries to start a shell or a download tool, Photon kills it. The PHP-FPM master then starts a clean replacement.
- Running a second stage. Programs launched from temporary directories, the docroot or memory-only files are blocked, whichever process launches them.
- Persistence. If the worker tries to write to system locations such as cron, the dynamic loader config or ssh keys, the write is blocked. Changes to PHP or web-server config files and new files dropped in the docroot raise an alert.
- Opening a bind shell. The worker cannot listen on any port other than its own.
- Calling home. Outbound connections from the worker to unexpected addresses, and from shells or netcat, raise an alert.
- Moving into sibling workers. Attempts to attach to another PHP worker and inject code into it are blocked.
The whole policy is about a dozen rules. Because the rules match on the worker process itself, the first step can be attributed without tracking the process tree.
What this does not do
- It does not fix the bug. The worker is compromised for the duration of the request, and anything it can legitimately read in-process, database credentials in config files, that worker's session data, is exposed. No rule can deny reads the application itself performs.
- It does not see the HTTP request. Photon has no visibility into request bodies, so it cannot tell an exploit attempt from a large upload. Only the patch closes the door.
- Killing workers that spawn a shell has one known false positive. PHP's mail() runs sendmail through /bin/sh -c, and so does any application that shells out to ImageMagick or ffmpeg. Sites that do either should run that rule in alert mode first, identify the legitimate callers, then enforce.
Patch, and bridge the gap with the official mitigations
- Update to 8.5.12, 8.4.27, 8.3.36 or 8.2.35 [8] and restart Apache, PHP-FPM and every other long-running worker. Rebuild container images that bundle PHP; a host update does not reach them.
- Until then, apply what the PHP advisories recommend, knowing none of it is complete: enforce memory_limit=-1 through php_admin_value, keep post_max_size small, block multipart at the frontend if the application does not use it, set session.upload_progress.enabled=0, and on 8.5 set fatal_error_backtraces=0. Restart workers after each change; ini_set() and .user.ini are not enough [2,3,4].
- Put a containment policy in front of the workers you cannot patch on your schedule, and leave it there after patching. The next PHP runtime bug will land in the same place, and its first hop will look exactly the same.
If you run PHP on devices you cannot patch, that last point is the whole argument for enforcing at the kernel rather than scanning for a version string.
References
[1] php2shell Vulnerability Website, php2shell — https://www.php2shell.com/
[2] GHSA-w8hw-w9fx-j79w: CVE-2026-109618, RCE via OOM corruption (php-src advisory) — https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
[3] GHSA-6wmf-4rv5-p3rp: CVE-2026-109619, RCE via stale global state (php-src advisory) — https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp
[4] Tenable: PHP2Shell frequently asked questions — https://www.tenable.com/blog/php2shell-cve-2026-109618-cve-2026-109619-frequently-asked-questions-about-critical-php-remote
[5] Amazon Threat Intelligence: PHP2Shell exploitation prior to public disclosure in MadPot — https://aws.amazon.com/blogs/security/amazon-threat-intelligence-identifies-php2shell-exploitation-prior-to-public-disclosure-in-madpot/
[6] Recorded Future: PHP2Shell exploitation (Patchstack and Cloudflare reports) — https://www.recordedfuture.com/blog/php2shell-vulnerability-exploitation
[7] Matthew Prince (Cloudflare CEO) on X — https://x.com/eastdakota/status/2113079352682570051
[8] PHP security release announcement, php.net — https://www.php.net/

.png)

