The PHP2Shell Postmortem: What CVE-2026-109618 and CVE-2026-109619 Actually Tell Us
I made a 6-minute video breakdown of this on YouTube — this is the written version for readers who prefer text. Same facts, same angles, better for linking in Slack or coming back to later. On October 17, 2026 — four days before the patch shipped — AWS's MadPot honeypot caught something unusual: one HTTP request, no login, no session, no account. The server came back wrong. Three days later, the CVE numbers for CVE-2026-109618 and CVE-2026-109619 leaked on Hacker News, roughly 22 hours before the planned embargo lift. By the time PHP 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 went out, the exploit was already in the wild. This post walks through four things I think are worth sitting with: the attack shape, the attacker fingerprint, the leak chain, and the 22-year pattern underneath. The video covers all of this visually; this is the "I want to re-read something while I'm waiting on a patch window" version. 1. One request, no login PHP2Shell is a pre-auth remote code execution. That matters because the entire category of "we require authentication before the vulnerable endpoint is reachable" mitigation disappears. There is no login to brute, no session cookie to steal, no CSRF token to extract. A bare HTTP request walks a specific allocator path inside the PHP runtime, hits a use-after-free, and the attacker gets execution in the context of whatever user runs PHP — typically www-data or equivalent. The affected surface is the awkward part. Three CMS platforms — WordPress, Drupal, Joomla — account for the largest slice of the PHP-serving web. Industry estimates put that combined share at roughly 70% of PHP-hosted content sites. That is the number people were trying to figure out during the embargo scramble: how many sites, exactly, were sitting on a vulnerable interpreter. The patch landed cleanly across the four supported PHP branches. What is not getting patched: PHP 5.x through 8.1, all of which are past end-of-life. If you are running any of those in production, this is not a vulnerability you mitigate. It is an upgrade you plan. 2. The attacker's fingerprint was pre-knowledge The MadPot capture is the interesting read. One IP, one request, and the path the request took through the allocator was already correct — not fuzz-like, not a scanner walking endpoint variations, not a crash-driven feedback loop. The request went to the vulnerable path on attempt number one. That is a fingerprint. Fuzzing produces thousands of near-misses before the bug surfaces. Exploit-development frameworks produce a telltale sequence of pre-flight probes. This produced neither. The person on the other side of that request knew the trigger pattern and the memory layout. Which means two things worth internalizing: The hunt window starts when exploitation started, not when the patch shipped. AWS saw it October 17. The patch landed October 21. If you are hunting for compromise, your logs from October 17 through October 20 are the window where a competent adversary was already live. Logs from October 21 onward are the window where every scanner on the internet started probing. Different signals, different noise levels, different conclusions. At least one party had the vulnerability before the official embargo started circulating it. That is uncomfortable to sit with, but it is the shape of what the MadPot data implies. Which brings us to the second interesting failure. 3. The embargo leaked before it lifted Every coordinated disclosure sits on a specific premise: a controlled set of hands holds the details for a known window, and the window ends when all the affected parties have shipped patches. The window's security is the aggregate security of every hand that holds the data. What happened here is that the CVE numbers appeared in a Hacker News thread about 22 hours before the planned embargo lift. The thread was not a leak in the traditional sense of a vendor publishing early — someone had the detail and posted it. By the time maintainers noticed, the thread had hundreds of replies. The structural point: an embargo does not degrade linearly with time. It degrades per-hand. Every additional party added to the coordinated-disclosure list adds exactly one new leak surface. The reason major embargoes still hold is not that the list is small — it is that the list is screened and the parties on it have specific professional incentives not to break the window. For maintainers running coordinated disclosure, this has a practical implication. The list of hands that hold the pre-embargo detail is the risk model. Not the window. Not the embargo lift date. Not the public advisory text. The headcount is the number to manage. 4. 22 years of the same bug class The PHP maintainers' postmortem used a specific phrase: "structural failure." That is unusual language for a patch advisory, and it was chosen carefully. The specific bug in question is a use-after-free in an allocator-adjacent path, and the bug class — mark-then-free races with a "counter after allocation" pattern — has been showing up in various forms since the mid-2000s. The fix landed in days. The class has survived decades. That is worth distinguishing from "PHP has memory bugs." The question is not whether the interpreter has had UAFs. Every language runtime that manages memory directly has had UAFs. The question is whether the surface where this specific class keeps re-appearing is architectural or incidental. The maintainers' own admission suggests architectural: the structural-failure language points at the allocator-mark-then-free pattern as the thing that needs rework, not any specific instance. That is a hard thing to do mid-decade on a runtime that serves this much of the web. It is also a signal that senior engineering teams running PHP services should take seriously. The specific vulnerability you patched this cycle is fixed. The class is not. Monday checklist If you are patching production this week: Patch to 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35. These are the four supported branches. Anything older does not get this fix. Add a WAF rule for the trigger pattern. Public exploit code is circulating; the pattern is well-known at this point. Even post-patch, blocking at the edge is a cheap belt-and-suspenders move. Hunt logs from October 17 onward, not October 21. The exploitation window started before the patch window. Your most interesting signal lives in the days before most hunters would look. If you are on an EOL PHP version (5.x through 8.1), plan the upgrade now. There is no patch coming for your branch. This is a planning item, not a mitigation item. Further reading CVE-2026-109618: NIST NVD CVE-2026-109619: NIST NVD PHP release notes: ChangeLog-8 AWS MadPot program: AWS Security I cover this kind of thing in ~6 minutes of architecture-diagram video every week or so on The Dev Stack — security postmortems, system-design walkthroughs, industry-pulse explainers for senior engineers. If you liked the written version, the video has a bunch of the memory-layout and timeline detail visualized, which reads easier than prose.
This is a summary aggregated from Dev.to. Read the complete article on the original site:
Read full article at Dev.to