I've spent a good chunk of this week reading about PHP2Shell. Partly because it's serious, and partly because it's a genuinely strange bug.
The headlines are about remote code execution, which is fair. If someone can get your web server to run their code without signing in, that's not exactly a minor problem. But the part I keep coming back to is how one of these vulnerabilities can get PHP to send back pieces of its own memory in a session cookie.
A session cookie. Of all things.
PHP2Shell was disclosed on October 21, 2026, and covers two critical vulnerabilities, CVE-2026-109618 and CVE-2026-109619. Both received CVSS 4.0 scores of 9.2. I'll get to the remote code execution part, but I think the memory disclosure is worth understanding first. It explains a lot about why these bugs are interesting and why ordinary security controls aren't always where the answer is.
First, what actually is a memory disclosure attack?
When a website processes a request, it needs somewhere to work. Maybe it's looking up an account, checking a session, talking to a database, or making a call to another service. Much of the information it needs along the way lives temporarily in RAM.
That could include session identifiers, API keys, authentication tokens, database credentials, or bits of data from another person's request. It's not inherently a problem for that information to be in memory. That's what memory is for.
The expectation, of course, is that the next person visiting the website doesn't get to read any of it.
A memory disclosure attack is what happens when that expectation breaks. Some part of the software reads memory it shouldn't and reveals the contents to somebody who wasn't meant to see them.
I think of it a bit like finishing with a customer's paperwork, clearing the desk, and moving on to the next customer. Except something wasn't actually cleared, and the next person finds a piece of the previous customer's information mixed into their own documents.
The person didn't need to break into a filing cabinet. The information came to them because of a mistake in how it was handled.
There is one terminology trap here. A memory leak usually means software keeps allocating RAM and doesn't release it properly. A memory disclosure means information escapes from memory. You can have one without the other.
What bothers me about disclosure bugs is how unremarkable they can look from the outside. The application can keep running. No malware needs to appear on disk. Nobody necessarily gets an interactive shell. A server might simply put something sensitive into a response it should never have sent.
Which is why I wouldn't want an investigation to start and end with, "Did we see someone executing commands?"
How does PHP get itself into that situation?
PHP is doing a lot of housekeeping when it processes a web request. It allocates memory, creates internal objects, keeps references to those objects, and eventually cleans up. Most of the time, nobody has a reason to care about any of it.
But what if the request runs out of memory partway through?
PHP needs to stop the operation safely. In these vulnerabilities, that cleanup could go wrong. Depending on the path, PHP might leave partially initialized internal data behind or hold onto a reference to memory that had already been freed.
That second problem is called use-after-free, and the name is refreshingly literal. The software releases some memory and then tries to use it again.
Picture having a storage locker number written down. You move out, hand the locker back, and eventually it gets rented to someone else. The old number is still in your notebook, but the contents behind it have changed.
A computer can make a similar mistake with what's called a stale pointer. The pointer still points somewhere. It just no longer points to information the program is entitled to treat as the old object.
On a busy web server, a PHP worker may process one request and then another. If a reference survives from the first request into the second, things can get weird very quickly.
The part I had to read twice: PHPSESSID
Here's my favourite part of the research, from a purely technical point of view.
PHP has a feature that tracks file-upload progress. It's meant to help an application know how much of a file has arrived. That feature can interact with PHP's session handling, which is where the familiar PHPSESSID cookie comes in.
Normally, PHPSESSID is just a way of identifying a session. There's nothing particularly exciting about it.
Researchers found that an attacker could trigger an out-of-memory failure during the upload-progress handling path, at a point where PHP had created internal session state but hadn't finished cleaning it up. The worker could be left with an old reference to memory it no longer owned.
Then a later request, handled by the same worker, could encounter that stale reference and treat the bytes now sitting there as though they were a session identifier.
PHP could URL-encode those bytes and send them back in a PHPSESSID response cookie.
I love the absurdity of that. Something intended to help the website recognize a browser becomes a way for a stranger to see pieces of the server's working memory.
Wiz demonstrated this without first achieving code execution, and even when the application never called session_start() itself. The relevant handling can occur before the application's own logic runs.
That last detail is easy to miss, and I think it's important. You can write careful application code, validate inputs, use good authentication, and still inherit a memory-safety problem from the runtime underneath you.
To be clear, it doesn't mean every request spits out passwords. The content of memory depends on what that worker has been doing, and useful exploitation requires the right conditions. But the possibility of revealing tokens, credentials, or other people's data is enough to make this serious on its own.
If you're monitoring for suspicious shell commands, you might not see much. If you're only looking at what comes into the application, you might miss the important part of what went out.
Okay, but how does it become a shell?
Memory disclosure is one outcome. The researchers also showed how related memory-handling problems could be chained into remote code execution, or RCE.
That's when an attacker gets a system to execute code of their choosing. It doesn't automatically give them every privilege on the machine. What they can do still depends on the permissions of the PHP worker and the environment around it. But code execution on an internet-facing server without authentication is a terrible place to start.
There were a few attack paths in the research that I thought were worth mentioning, even if you don't spend your days digging through PHP internals.
Upload progress and unserialization
PHP has internal machinery for reconstructing session data. An out-of-memory error during upload-progress processing could leave some of that machinery pointing at invalid memory. On a later request, the attacker could influence how PHP used that stale state.
Wiz combined this with memory disclosure to make an exploit more reliable. Seeing information about memory can remove some of the guesswork involved in exploiting memory corruption. The researchers demonstrated unauthenticated RCE against WordPress, Drupal, and Joomla environments.
The interesting part isn't that those three content-management systems have the same application bug. They don't. The common piece is the PHP runtime underneath them.
A diagnostic feature that becomes part of the problem
Another path involved fatal-error backtraces, the records developers use to understand what the program was doing when it failed.
A fatal error could leave an old backtrace reference behind. When the next request came through, PHP could try to use that reference even though the memory had been released. The resulting use-after-free could be developed into memory corruption and code execution.
There's something a little ironic about a diagnostic feature becoming part of an exploit chain. The very mechanism intended to help us understand failures can end up mishandling one.
Even the performance cache got involved
PHP's OPcache makes websites faster by keeping compiled PHP structures available for reuse. It's a useful feature, and one most site owners probably never think about.
Researchers found a way for interrupted processing to leave inconsistent internal pointer information. Another worker could then interpret reused memory as the wrong kind of object. That's called type confusion.
It sounds obscure, and it is. But the outcome was another demonstrated route to code execution.
I won't pretend any of these are easy exploits to build. They aren't. The point is that an error in memory handling can show up through several quite ordinary features: uploads, diagnostics, and caching.
And it can all be happening underneath an application that thinks it's simply serving a webpage.
What about the claim that this affects 70% of the internet?
I've seen that headline a lot this week, and it needs a little context.
PHP is enormous. W3Techs estimates that it powers roughly seven in ten websites where the server-side programming language is known. WordPress alone gives you some idea of how widely PHP is used.
But saying PHP powers that much of the web isn't the same as saying 70% of websites are exploitable, or compromised, or even configured in the same way.
Version, server architecture, and reachable code paths all matter. The PHP Foundation specifically called out Apache deployments using mod_php, where an unauthenticated attack was demonstrated before the application's own code even ran. PHP-FPM also had demonstrated exposure through application-level paths, but those conditions are different.
So I'd resist the temptation to repeat the biggest possible percentage without explaining it. There's enough legitimate concern here without doing that.
Still, the size of PHP's footprint matters a lot. If the problem is in the runtime, updating a WordPress plugin won't solve it. You might need to update an OS package, rebuild a container image, coordinate with a hosting provider, or get assurance from a vendor that runs PHP somewhere inside a service you rely on.
The application isn't always the thing that needs fixing.
A bug that was old long before it became a headline
This part of the story deserves more attention than it's getting.
According to the PHP Foundation, signs of the underlying out-of-memory issue surfaced in 2024, during work following an external security audit. People considered whether it might be exploitable, but at the time there wasn't a concrete attack path demonstrating the full impact.
The fixes weren't simple either. Different approaches risked breaking compatibility, creating denial-of-service problems, or forcing changes across third-party extensions. The small group of maintainers with the right expertise was balancing all of that while doing the rest of the work needed to keep PHP running.
I have some sympathy for them. It's easy to read the disclosure and say, "Well, why didn't you just fix it?" That question gets a lot more complicated when a wrong change could break an enormous amount of software people rely on.
But the PHP Foundation didn't try to excuse the delay. They described it as a structural failure in their decision process and resourcing. I thought that was refreshingly candid.
It also raises an uncomfortable question about how we fund and maintain the open-source infrastructure underneath modern businesses. We expect extraordinary things from a surprisingly small number of people who know these runtimes well enough to change them safely.
And then, in 2026, additional research from Calif, OpenAI, and Wiz demonstrated practical exploitation paths. Suddenly the theoretical concern wasn't theoretical anymore.
The AI part is bigger than a flashy headline
Of course AI is part of this story. It's 2026, so it was almost inevitable that it would show up in the headline somewhere.
But there's a real point behind it.
Memory corruption exploitation is hard. A chain that works on one version of PHP can fail on another. Minor changes in allocation behaviour, configuration, or internal structures can ruin your assumptions. Much of the work is painstaking analysis, testing, finding out why something broke, and trying again.
Frontier AI models helped the researchers with that work. Wiz described using AI to assist with discovery, exploit development, debugging, and adapting attacks across environments.
I don't interpret that as "anyone with a chatbot can hack PHP now." That's not what the research demonstrates. Human expertise, controlled testing, and deep knowledge still matter.
What I take from it is that the cost of working through difficult technical problems is changing. Things that required an extraordinary amount of specialist time may become practical with much less of it.
We've used exploit complexity as one input into vulnerability prioritization for a long time, and I still think that's sensible. But complexity isn't frozen in place. The code might be ten years old while the effort required to exploit it drops dramatically.
That should make us a little more careful about dismissing a vulnerability as "too hard to exploit."
There's a good-news story here as well. This research happened on the defensive side. Researchers reported what they found, worked with maintainers, and helped prepare fixes and protections. That's exactly where I want to see these capabilities used.
The same tools make it possible to uncover dangerous problems before someone turns them into a real-world compromise. I wouldn't want that part lost in the discussion.
Something I liked about Cloudflare's response
Cloudflare's defensive work was interesting for a different reason.
We often think of a web application firewall as something that examines incoming traffic. Look for a suspicious payload, a malicious pattern, or a request that clearly doesn't belong, then block it.
Fair enough. But with memory disclosure, the critical event may be what the server sends back.
Cloudflare said that looking at requests alone wasn't always enough to distinguish malicious activity from legitimate traffic confidently. They developed a way to evaluate signals from the request and the origin's response together, then block a matching response before it reached the requester.
I like that as a defensive idea. It sounds simple when you say it aloud, but it changes what you need to observe. Sometimes the strongest evidence of an attack isn't in what somebody asked the application to do. It's in how the application responded.
That doesn't replace patching. A WAF can buy time and reduce exposure, but it can't fix a stale pointer inside PHP. And attackers will keep trying variations against whatever protections are published.
Still, it's a good reminder that the controls we depend on need to evolve as the attack techniques do.
If I were responsible for a bunch of PHP services, what would I ask?
Probably not just, "Did we deploy the patch?" It's an important question, but it doesn't quite get me to an answer I can trust.
PHP released fixed versions 8.5.12, 8.4.27, 8.3.36, and 8.2.35 on October 21. For older releases, I'd want to know whether a supported vendor has backported the fixes or whether we need to migrate. I'd also want confirmation that the affected services and workers restarted and are actually running corrected code.
Then I'd start asking about exposure. Which internet-facing services run PHP? Which containers and managed platforms? Where do we depend on a vendor to do the update for us? If a system isn't directly exposed, are there other paths that still make it worth prioritizing?
On detection, I'd want someone looking beyond the obvious signs of a server takeover. Unusual multipart uploads, memory-limit failures, repeated HTTP 500 responses, unexpectedly large or malformed PHPSESSID cookies, and unexplained worker restarts are all leads worth looking into.
They're leads, not proof. Plenty of ordinary failures can produce some of those symptoms. But I'd rather have a defensible investigation than assume "no suspicious process" means "no issue."
And if we had credible evidence that memory was disclosed, I'd want to think about the contents. Were session tokens or credentials potentially exposed? Does anything need to be invalidated or rotated? Could a third party have been affected? That's a different conversation from simply confirming that a scanner stopped flagging the CVE.
This is why I don't love a vulnerability queue sorted by CVSS alone. I want to understand what can actually happen, where it can happen to us, what evidence we have, and how we know the exposure is closed.
One more wrinkle from October 23
As if two critical PHP vulnerabilities weren't enough for one week, PHP published a separate advisory on October 23 for CVE-2026-115560.
It involves a much narrower issue in session upload progress. The PHP team says exploitation requires an unusual combination of session serialization settings and application code, so I wouldn't lump it in with the broadest PHP2Shell scenarios.
It also isn't fixed by the October 21 releases. PHP recommended temporarily disabling the feature with session.upload_progress.enabled=0 until the next regular bugfix release. If you already applied that mitigation on October 21, PHP says to keep it in place.
To me, this is less a reason to panic and more a reminder that vulnerability research keeps moving after the first patch announcement. Guidance changes. Variants get discovered. Sometimes there's another very specific condition to check before you're really finished.
Why I wanted to write about this
I started reading about PHP2Shell because I wanted to understand the memory disclosure, and ended up spending just as much time thinking about the people and decisions behind it.
There's a beautifully weird technical bug in here. There's a maintainership problem. There's a really useful defensive story about AI. And there's a lesson about how we judge vulnerability risk that I think will only become more important.
A server runs out of memory at the wrong moment. Cleanup misses something. A stale reference survives. Later, a session cookie can end up containing information it has absolutely no business containing.
I don't think I'll look at a PHPSESSID cookie quite the same way for a while.
And if there's one lesson I'm taking away, it's that the difficulty of exploiting a vulnerability can change, even when the vulnerable code doesn't. That's a fairly important thing to keep in mind when deciding what deserves our attention.
References & further reading
For the original research, maintainer perspective, and mitigation details:
- Wiz Research: PHP2Shell technical analysis ↗The exploit demonstrations, memory disclosure through PHPSESSID, and the different RCE paths.
- The PHP Foundation: Today’s PHP Security Release ↗What the maintainers knew, why the fix was difficult, and how the research came together.
- PHP: Official October 2026 advisories ↗Patched versions, mitigation guidance, and the October 23 session-upload-progress advisory.
- Cloudflare: Protections against PHP2Shell ↗Why effective WAF detection needed to consider the request and the response.
- UK NCSC: Critical security issue affecting PHP ↗Additional guidance on exposure and remediation.
- Canadian Centre for Cyber Security: PHP advisory ↗Canadian guidance for operators assessing the vulnerabilities.