Vulnerabilities
PHP CVE-2026-115560 and the Potassium bots that missed
PHP flagged an unpatched session RCE, CVE-2026-115560, two days after PHP2Shell. Who is exposed, the one-line fix, and what failed Mirai attempts show.
On October 23, two days after the emergency PHP2Shell releases, the PHP project published an informational advisory for a third remote code execution (RCE) flaw, CVE-2026-115560. It has no patch and no published score. PHP will fix it in the next regular release instead of shipping another emergency build, because the bug needs a configuration and code pattern it calls "unlikely in practice". The workaround is one php.ini line, session.upload_progress.enabled=0, which PHP had already listed as a PHP2Shell stopgap on October 21.
In the same days, the first real payload behind the PHP2Shell attacks was identified. Sophos says attackers tried to use CVE-2026-109618 and CVE-2026-109619 to install Potassium, a botnet derived from Mirai, the malware family that turns hacked Linux machines into DDoS (distributed denial of service) nodes. Sophos found no successful compromise, and as of October 23 no confirmed compromise had been published. That leaves time to patch, though less of it as better exploits appear. Our PHP2Shell post covers the fixed versions and stopgaps; this one covers what changed since.
How CVE-2026-115560 works
PHP saves session data in a text format chosen by session.serialize_handler. The default, php, writes each variable as a name, a pipe character and a serialized value. The alternatives, php_serialize and php_binary, use different layouts. Data written in one format and read back in another is parsed wrongly.
Session upload progress is the feature that links the two. When it is on, PHP writes progress details for a multipart upload into the session while it is still reading the request, before any of your code runs. That write uses the handler set in configuration. PHP says the flaw appears only when an application configures php_binary or php_serialize, then switches to php at runtime with ini_set() before calling session_start(), while upload progress stays enabled. In that case the progress data, which includes values the uploader controls, is written in one format and decoded in another.
PHP has not published the details and will release a full advisory with the fix. Our reading, which PHP has not confirmed, is that this follows a known pattern: a pipe character inside attacker-supplied upload data makes the php decoder treat what follows as a serialized object, and unserializing attacker-chosen objects is a long-standing route to code execution. CERT-EU's advisory also says no technical detail is available yet.
What attackers did with PHP2Shell
Amazon Threat Intelligence logged the first PHP2Shell exploitation attempt on October 17, four days before the patches, according to Sophos's advisory and later reporting. Cloudflare saw attempts reach tens of thousands within 45 minutes of the October 21 announcement, which PHP had brought forward after the CVE IDs leaked on October 20, and millions by October 22. As of October 23, Censys counted more than 34.4 million PHP services on versions it rates as potentially vulnerable.
Sophos analysed the payload in one attempt. The sample is an updated and much expanded build of a Mirai-derived botnet first identified in early 2026. It contacts a hardcoded command and control (C2) server, accepts the download only if the server answers HTTP 200 and the file starts with the ELF header of a Linux executable, and falls back to the public DNS resolvers 8.8.8.8 and 1.1.1.1 when local DNS fails. It can download more malware and launch DDoS floods. Sophos blocked the attempt before the malware was delivered, and it corrected an earlier update of its own that had reported a successful exploitation.
Arctic Wolf linked two Potassium binaries to servers hosting PHP2Shell payloads, but says its data does not show PHP2Shell requests fetching or running them. Both samples contain code to find their C2 through Ethereum Name Service (ENS) names, switched off for now. Hunt.io attributed the traffic to a Mirai-style botnet active since at least May 2026.
The attackers' own tooling shows why they are missing. SOCRadar found a server with browsable working files: an exploit chain for PHP 8.4.26 on Apache mod_php that its operator called "one-click", plus scripts to check targets for the configuration it needs. SOCRadar says it only works on lab-like servers, and it saw no shell access as of October 22. The operator fingerprinted about 20 sites and probed 11 in depth, and none qualified. Hunt.io looked at the same server and counted 10 attack rounds against 123 servers, about 57 of them running PHP, with none exploited.
That gap is closing. VulnCheck has built a CVE-2026-109618 exploit that gets past ASLR (address space layout randomisation, which hides where code sits in memory) on x86-64 with PHP error display off. It is limited to VulnCheck's paying customers, and VulnCheck knows of no other exploit that works across PHP versions in production setups.
What to do
- Install 8.5.12, 8.4.27, 8.3.36 or 8.2.35 and restart PHP-FPM or Apache if you have not. Those builds do not fix CVE-2026-115560, and failed attempts so far are no reason to wait.
- Set
session.upload_progress.enabled = 0in php.ini, the FPM pool or the Apache config, then restart every worker. PHP says not to rely onini_set()or.user.inifor this, since the progress write happens while the request is parsed. If you did this for PHP2Shell, keep it in place. - If you need upload progress bars, find out whether you are exposed. Check the effective
session.serialize_handlerin aphpinfo()page on an internal host, notphp -i, which reports the command-line build. Then search your code and vendor libraries for runtime changes, for examplegrep -rn "session.serialize_handler" --include=*.php .. PHP says applications that never change the handler at runtime can keep the feature on. - Watch for the next PHP point releases, which will carry the fix and the full advisory, and patch then.
For PHP2Shell compromise checks, look for PHP worker processes starting shells or download tools such as curl or wget, multipart requests followed by memory limit errors or bursts of HTTP 500, and outbound connections from web servers to unknown hosts. A Potassium infection shows up as an unfamiliar ELF binary started by the web server user and new outbound traffic, including DNS queries sent straight to 8.8.8.8 or 1.1.1.1 from a host that normally uses an internal resolver. An egress firewall that blocks web servers from reaching the internet stops the download step even if an exploit lands. If you find a hit, rebuild the server and rotate the secrets in its config files.
One setting, two advisories
PHP published the upload progress workaround for PHP2Shell on October 21, two days before CVE-2026-115560 existed. Teams that turned off a feature they did not use were already protected from the second flaw. If a PHP feature you do not use keeps appearing in advisories, turn it off server-wide, not only until the patch lands.
If you are not sure which of your applications switch session handlers or still have upload progress on, our web application penetration testing covers that kind of code review, and safeguarding and hardening work sets PHP and egress rules so the next flaw has less to work with. Open the chat and Yaali, our AI agent, will pass your question to an engineer.
Sources: PHP news archive, October 23 advisory, CERT-EU advisory 2026-018, BleepingComputer, The Hacker News, The Hacker News on Potassium, Sophos advisory, SecurityWeek, Security Affairs, ActiPace.