PHP2Shell's Third Flaw: What CVE-2026-115560 Means for Servers

Illustration of a data centre server rack with a cracked front panel leaking a glowing data stream past a file upload progress bar toward a padlock with its toggle switched off, representing the PHP2Shell session upload progress flaw

PHP2Shell's third flaw, CVE-2026-115560, lets attackers run code on a PHP server only when an application switches its session serializer at runtime while upload progress tracking stays on. PHP says that setup is rare, so it will ship the fix in its next regular release instead of an emergency patch. One php.ini line closes it today.

What Happened

On 21 October 2026 the PHP project shipped PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 to fix two critical remote code execution bugs that researchers nicknamed PHP2Shell. According to the official PHP security advisory, CVE-2026-109618 is an out-of-memory corruption bug and CVE-2026-109619 is a use-after-free caused by "stale global state" that survives from one request to the next. Both can be triggered by an unauthenticated remote attacker, and both carry a CVSS 4.0 score of 9.2. A leaked listing had wrongly shown 10.0.

Two days later, on Friday 23 October, the PHP Security Team posted a much quieter note: an "informational advisory" about session upload progress. It describes a third remote code execution vector, now tracked as CVE-2026-115560, that the 21 October releases do not fix. PHP Foundation executive director Elizabeth Barron told The Register the bug needs "a very unlikely combination of configuration and specific PHP application code," and the project said it will publish a full advisory and a fix with the next regular bugfix release. No date has been given.

The timing matters because PHP2Shell was already being exploited. Amazon's threat intelligence team reported an exploitation attempt against its MadPot honeypot network on 17 October, four days before disclosure, and more attacks between 02:00 and 08:00 UTC on 21 October, hours before the embargo lifted at 14:00 UTC. Cloudflare reported early attacks the same day, and Mandiant CTO Charles Carmakal wrote on LinkedIn that exploitation "may have already begun in a limited fashion."

Why It Matters

PHP still runs a very large share of the web, from WordPress blogs to custom shop back ends and government portals. When the interpreter itself has a remote code execution bug, every application on top of it inherits the risk, whether or not its own code is well written. The first two PHP2Shell bugs were serious enough that CISA's 21 October alert told organisations to take PHP systems offline if they could not patch, especially unsupported PHP 8.1 or older.

The third flaw matters for a different reason. It tests whether a security team can tell the difference between "critical" and "critical for almost nobody." The PHP project chose not to rush another release in the middle of an incident that had already produced a leaked CVE listing, a prematurely published proof-of-concept video and an embargo break by a container image vendor. Pushing yet another emergency build would have asked every Linux distribution and hosting company to repackage PHP again within a week, for a bug most of them cannot hit.

For site owners the practical stakes are small but real. If you already applied PHP's recommended mitigation for CVE-2026-109619 on 21 October, you are already protected against the new vector. If you only upgraded and stopped there, you are probably safe, but one line of configuration removes the doubt entirely.

There is also a broader lesson about how fast this cycle moved. The PHP Foundation's own write-up says Calif's audit started on 30 July 2026 and reported the unconditional code execution chain on 11 August. Calif and Wiz both said they used AI models in their research, and The Register's columnist summed up the episode as days to find and hours to exploit. Defenders who measure patch windows in weeks are now competing with attackers who can turn an advisory into a working exploit before lunch.

How It Works

To understand CVE-2026-115560 you need two pieces of PHP plumbing: session serialization and upload progress tracking.

Session serializers

When a PHP application stores data in $_SESSION, the interpreter has to turn that data into a string so it can be written to disk, Redis or a database between requests. The session.serialize_handler setting decides which format it uses. The default is called php; two alternatives are php_binary and php_serialize. Each one reads and writes session data differently, so data written in one format can be misread if the server later parses it with another.

Upload progress tracking

The session.upload_progress.enabled feature, on by default in PHP, lets a page show a progress bar while a large file uploads. When a multipart POST includes a field named after session.upload_progress.name (by default PHP_SESSION_UPLOAD_PROGRESS), PHP writes progress information into the user's session while the request body is still being parsed. That means attacker-controlled request data lands in session storage before any application code has run, which is exactly why this feature keeps appearing in PHP2Shell exploit chains.

Where the third bug sits

According to PHP's informational advisory, the new flaw appears only when three conditions are true at once:

  • The server configuration sets session.serialize_handler to php_binary or php_serialize.
  • The application then switches the handler back to php at runtime with ini_set(), before calling session_start().
  • Session upload progress is still enabled.

PHP has not explained the mechanism yet, but the conditions point to the same weak spot as the earlier bugs: progress data written in one serializer format while the request is parsed, then read back under another. PHP has not yet published the technical details, the affected version range or a severity score, and says those will come with the full advisory. Applications that never change the serializer at runtime are not exposed and can keep upload progress on.

How it relates to the first two bugs

CVE-2026-109619 works because a fatal error can leave internal state pointing at memory that was freed at the end of an earlier request; the next request on the same worker can then reuse that stale pointer. PHP's mitigation list for that bug already told administrators to set session.upload_progress.enabled=0, because the confirmed exploitation paths went through session handling. CVE-2026-109618 is a separate problem: if a request hits memory_limit at the wrong moment, cleanup code treats half-built data as valid. On Apache with mod_php, PHP says that path can be triggered before any application code runs, which is why mod_php is rated the highest-risk setup.

What to do now

The checklist is short. First, confirm you are on 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or on a distribution package with the backported fix; PHP published minimal source backports for 7.4, 8.0 and 8.1, while 5.4 through 7.3 get nothing. Second, add this line to php.ini, an FPM pool file or the Apache configuration, then restart every worker:

session.upload_progress.enabled=0

PHP warns not to rely on ini_set() or an FPM .user.ini file for this, because those apply too late in the request. Third, follow Amazon's advice and start any log review from 17 October rather than the disclosure date, searching for POST requests that contain the PHP_SESSION_UPLOAD_PROGRESS field.

What's Still Unknown

Several important details have not been published yet:

  • Affected versions. PHP has not said which branches contain the CVE-2026-115560 code path or whether end-of-life versions are affected.
  • Severity score. There is no CVSS rating for the third flaw, which makes it hard for scanners and compliance tools to rank it.
  • Release date. The fix arrives with "the next regular bugfix release," but no date has been announced.
  • Real-world exposure. PHP says the configuration is unlikely in practice, but nobody has published a survey of how many applications switch serializers at runtime. Older frameworks and session-compatibility shims are the obvious places to check.
  • Who has been compromised. As of 23 October no successful compromise had been publicly attributed to PHP2Shell, though Amazon now describes it as broadly exploited, and attackers were probing before disclosure. How they learned of the bugs early is still unexplained.

The PHP Foundation's post-mortem blog post admits that the out-of-memory fix stalled for months under a consensus-based decision process, which it calls a structural failure, and says the security team is moving to majority decisions and earlier involvement from Foundation leadership. Whether those changes speed up the next fix is the open question.

Frequently Asked Questions

What is PHP2Shell?

PHP2Shell is the nickname for two critical PHP interpreter bugs, CVE-2026-109618 and CVE-2026-109619, disclosed and patched on 21 October 2026. Both let an unauthenticated attacker run code on a server through crafted web requests. They affect PHP-FPM, Apache mod_php, php-cgi, FrankenPHP and LiteSpeed, and PHP rates mod_php as the riskiest setup.

Is CVE-2026-115560 part of PHP2Shell?

It is a separate, third bug in the same area, disclosed two days later in an informational advisory on 23 October. It is not fixed by the 21 October releases. PHP says it needs an unusual mix of configuration and application code, so the fix will arrive in the next regular bugfix release rather than an emergency update.

Am I affected by the third PHP flaw?

Only if three things are all true: your configuration sets the session serializer to php_binary or php_serialize, your application switches it to php with ini_set() before session_start(), and session upload progress is enabled. If your code never changes the serializer at runtime, PHP says you are not exposed to this particular vector.

How do I protect my server right now?

Upgrade to PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35 for the first two bugs, then set session.upload_progress.enabled=0 in php.ini, an FPM pool or the web server configuration, and restart every PHP worker. Do not rely on ini_set() or .user.ini files, because they apply too late in the request to help.

Will turning off upload progress break my website?

Only pages that show a native PHP progress bar during file uploads will lose that bar. The uploads themselves still work. Most modern sites track upload progress in the browser with JavaScript instead, so they will not notice any change. Test file upload forms after the change to be sure.

Why did PHP not release an emergency patch this time?

PHP judged the setup unlikely in real deployments and said a configuration change fully mitigates it. Another emergency build would have forced distributions and hosts to repackage PHP again within a week, during an incident already disrupted by leaks and an embargo break. A full advisory will accompany the regular release.

What if I run PHP 8.1 or older?

PHP no longer ships updates for 8.1 and older. The project published minimal source backports for 7.4, 8.0 and 8.1, and some Linux distributions and long-term support vendors offer patched packages. Versions 5.4 through 7.3 get no fix. CISA advised taking unpatchable PHP systems offline, so upgrading is the safest path.

Is PHP2Shell being exploited?

Yes. Amazon saw an attempt against its honeypots on 17 October, four days before disclosure, and more on 21 October; it now calls the bugs broadly exploited. Cloudflare reported early attacks the same day. As of 23 October no specific breach had been publicly attributed to PHP2Shell, so check logs back to 17 October.

Related Reading

If you manage a hosting stack, our report on the actively exploited cPanel bug that hit more than 70 million websites shows how control panel flaws compound interpreter risk. For a framework on deciding what to patch first when advisories pile up, see how Microsoft's risk cohorts triage a 1,400-flaw Patch Tuesday. Abandoned code is its own danger, as our look at Popcorn Time's abandoned updater and the botnet near-miss explains, and it is the same problem facing anyone still on PHP 7. If you are weighing a move off PHP entirely, our complete guide to programming languages compares the alternatives, and our explainer on VPS hosting and administrative access covers who controls your php.ini in the first place.