Kate: Welcome to the weekend deep dive. It's Saturday, October twenty-fourth, and this week one story ate the whole security news cycle. A pair of critical bugs in the core of PHP, nicknamed PHP2Shell. Websites went offline, millions of attack attempts rolled in, and yet nobody can point to a confirmed break-in. Dade, why is this worth a quarter of an hour?
Dade: Morning, Kate. Because it's three stories wearing one coat. First, it's a very old, very widespread piece of software with a flaw in the engine itself, not in some plugin. Second, it's a disclosure that fell apart days before the patch, which tells us something about how fragile coordinated disclosure has become. And third, it's a textbook case of the gap between a scary headline and what attackers can actually do today. PHP runs on roughly seventy percent of websites where the server-side language is known. WordPress, Drupal, Joomla, Magento, and a whole universe of home-grown apps. So when someone says unauthenticated remote code execution in PHP core, every consultant's phone starts buzzing. But the interesting part is what happened next, and honestly, how messy it got. Let's walk through it properly.
Kate: Okay, so start at the beginning. Because I gather this didn't start on Tuesday, when everybody noticed it.
Dade: No, not at all. The discovery timeline comes from Wiz Research, as quoted by Simon Willison. On August nineteenth, Wiz found the first vulnerability, and they say they used their own AI-driven platform together with two frontier models. The next day, August twentieth, they confirmed unauthenticated remote code execution against Drupal. August twenty-first, against WordPress. Then on August twenty-fourth they reported it to the PHP security team. PHP acknowledged the reports on September twenty-first and started building a coordinated fix. So you've got the finders and the maintainers working quietly for about two months, and the release was planned for Thursday, October twenty-second, at two in the afternoon, UTC. That's a normal, healthy, responsible-disclosure timeline. Nothing unusual about it. Wiz also worked with OpenAI and with another security firm, Calif, to measure how big the problem was before the details went public. Now keep that calm picture in your head, because on Tuesday it all goes sideways.
Kate: Right. So what actually went wrong on Tuesday?
Dade: The leak. Around three in the afternoon UTC on Tuesday, October twentieth, the two CVE identifiers started circulating on forums and social media. They came with the wrong release time and a wrong severity score of ten point zero. The real score, as rated by the PHP team, is nine point two. No technical details leaked at that stage, which is the one piece of luck in this story. PHP reacted by pulling its pre-announcement forward to half past seven that evening, and by moving the release a full day earlier, to Wednesday at two in the afternoon. But then, around eight o'clock UTC, Calif, one of the firms that had reported the bugs, accidentally published a video. It showed their proof of concept working against several targets, and it revealed a few extra details. They deleted it, but copies were already spreading, and according to the PHP Foundation, that video sped up the development of exploits by other people. Who actually caused the leak is disputed. A headline in The Register says PHP blames the supply chain security company Chainguard. I haven't been able to verify that claim myself, so treat it as one party's position, not as settled fact.
Kate: Let's get to the engine room, then. Two separate bugs, right? Not one bug with two numbers?
Dade: Two separate bugs, living in different places, and that's worth saying because people mix them up. Start with the first one, the one ending in one-oh-nine-six-one-eight. It's an out-of-memory problem. Picture PHP handling a web request. Halfway through, it runs out of memory. In vulnerable versions, PHP responds to that by doing a long jump, a longjmp, which basically yanks the program out of whatever it was doing and back to a safe point. The trouble is that the request's internal data is only half set up at that moment. Then the cleanup code runs, and it cleans up things that were never fully initialized. Think of a movie crew striking a set while the actors are still being hired. Cleanup code works on garbage, and an attacker who can shape that garbage can steer the program into running their code. PHP says the confirmed attack against Apache with mod_php happens before any application code even runs. That's why it doesn't matter how clean your WordPress is.
Kate: And how do you make a server run out of memory on purpose? That sounds hard.
Dade: Less hard than you'd think. PHP's own advisory lists several ways. Huge or oddly structured multipart requests, tons of form fields, deeply nested input, lots of headers inside each part. And here's a nuance the advisory makes: you can set the memory limit to unlimited, and that removes the predictable trigger, but real allocation failures can still reach the same code path. So it reduces exposure, it doesn't fix anything. PHP is blunt about this: there's no complete mitigation, updating is the only safe choice. Now the second bug, ending one-oh-nine-six-one-nine, is subtler and in a way more elegant. A PHP worker handles request after request after request. State from one request can survive after the memory behind it was freed. The next request on that same worker can then pick up that stale state before the normal reset happens. It's like a hotel room where the previous guest's key card still opens the door because nobody reprogrammed the lock. PHP confirmed paths through the session upload progress feature, and on PHP eight point five also through the backtrace that's printed on fatal errors. But PHP is explicit that those are not the only paths. There are per-request settings that can trigger diagnostics before normal initialization, and fatal errors and timeouts inside application code can create the stale state too. That's why the advice to switch off upload progress only blocks the confirmed paths, not all variants. As for which setups are exposed: Apache with mod_php is the highest risk. PHP-FPM, php-cgi, FrankenPHP and LiteSpeed are affected too. And on reach, Wiz says every PHP version from the last decade is hit by at least one of the two bugs, and Sysdig traces the vulnerable code back to PHP five point four, from twenty twelve. So this is code that's been sitting there for well over a decade.
Kate: Which brings up the question I keep seeing. If it's been there for a decade, why now? Why did nobody find it?
Dade: That's probably the most important structural point of the whole story. Wiz's argument is that the flaws were old, but proving they were exploitable took an extraordinarily complex chain of steps, right at the edge of what human researchers can realistically do. And frontier AI models, in their words, substantially lowered that barrier. They turned a long-standing flaw into a working exploit. OpenAI, which was involved in the research and the outreach, said it considers this one of the most impactful security issues in recent memory. I'd add one caution. Those details about how much the AI really did come from the companies involved and from secondary write-ups. I couldn't check them independently. But even with a discount, the direction is clear. Bugs that were theoretically there but practically out of reach become reachable when you can throw a lot of tokens and patience at them. Exactly. VulnCheck's exploit developer, Spencer McIntyre, said something that stuck with me: adversaries are clearly spending time, and tokens, on this bug. He also made the point that the technical difficulty of an exploit should never be confused with protection against it. And then there's the disclosure side of the trend. A secret that was held for almost two months by a handful of firms and the PHP team was effectively blown within about one day. That's not the first time, and it won't be the last. When a bug is this valuable, and when more people can reproduce it quickly with AI help, embargoes get shorter and leakier. If you're running NIS2 or CRA programs for clients, that's the real lesson here. The window between hearing a rumor and being attacked is shrinking. Amazon even said its honeypots saw an attempt on October seventeenth, four days before the public announcement. Whether that was a real exploit or just early scanning isn't clear yet.
Kate: All right, let's make it practical. A client calls on Monday morning and says, we run PHP, what do I tell them?
Dade: First and foremost, the runtime. Not the CMS, the runtime. This is the trap. People hear PHP bug and update WordPress, and WordPress doesn't contain PHP. The fixed versions are eight point five point twelve, eight point four point twenty-seven, eight point three point thirty-six and eight point two point thirty-five. For the end-of-life branches, seven point four, eight point zero and eight point one, PHP published source backports only, no official releases, so you need a distribution package with the backport, a rebuild, or better, an upgrade. For the really old five-point-something and other seven versions, there's no backport announced at all, so it's upgrade or isolate. Then hunt for the hidden PHP. Containers inherit PHP from base images, so you have to rebuild and redeploy, not just patch the host. Hosting panels often run several PHP versions side by side. Vendor appliances bundle PHP where nobody looks. And watch out for one more trap: check what the production pool actually runs. A workstation can show a patched binary while the PHP-FPM pool serving production runs a different one.
Kate: And how big is the unpatched pile? Do we have numbers?
Dade: We do, roughly. Picus cites a rapid scan from October twentieth that counted about eight hundred eighty-four thousand internet-facing hosts reporting PHP eight point one or older. That's around fifty-nine percent of the hosts that reported any version at all. And Censys said on Friday that over thirty-four million PHP services were still assessed as vulnerable, out of more than fifty-six million web properties running PHP. Those are banner-based estimates, so don't treat them as exact, but they show the scale. Meanwhile, Cloudflare rolled out firewall rules about nine hours before disclosure, which helps, but it already sees attackers mutating payloads to get around them. So a web application firewall is a seatbelt, not a fix. The UK government said thirty-two of its digital services were unavailable and four partially, largely from precautionary shutdowns, and its national cyber centre sent around fifty thousand warnings.
Kate: What about detection? If you can't be sure you're patched in time, what should the blue team watch?
Dade: Look below the application, because the attack can happen before application code runs. Picus lists a few useful signals. Bursts of worker crashes in the PHP-FPM logs, or segmentation faults in the Apache error log. Out-of-memory messages that say unknown on line zero, which are worth investigating even if they're not unique to this attack. And strange request shapes: giant or deeply nested multipart bodies, thousands of fields, chunked requests without a content length, or the session upload progress field sent to endpoints that never use it. Then the classic move: watch what PHP spawns. A web worker launching a shell, a Python or Perl interpreter, curl or wget, or recon commands like whoami and id is almost never legitimate. Baseline first, though, because some apps legitimately call image converters or PDF tools. And if you do find something, remember that code runs with the privileges of the web application, so think about the secrets and database connections reachable from that process.
Kate: Okay, so now the part where I ask you to calm me down. Millions of attacks. Is it as bad as the headline?
Dade: Here's where it gets interesting, because the evidence is much messier than the headline. Cloudflare saw tens of thousands of attempts within forty-five minutes of the announcement, hundreds of thousands within two hours, millions by early Thursday. But the Record spoke to dozens of experts, and none of them has seen a successful attack. Sophos actually published a report of successful exploitation and then retracted it, saying it only saw a small number of failed attempts. Google's John Hultquist said there's no validated wide-scale exploitation, but that exploitation may have started in a limited way and the threat is viable and very serious. Mandiant said many of the public proofs of concept look vibe-coded and can't execute code at all, though they've validated some that work against default mod_php, not PHP-FPM. And Marcus Hutchins made a sharp distinction: some vendors mean sophisticated, targeted exploitation, others just count failed mass attempts with broken exploits. He says the second matches what he's seen. The Hacker News also reports a Mirai-style botnet called Potassium being pushed through these attempts, without success so far. So, the accurate summary: lots of noise, no confirmed compromise, but not for lack of trying. Only for a moment, and that's the point. The main barrier for attackers is ASLR, the protection that randomizes memory addresses. VulnCheck says it built, overnight, a technique that chains a memory leak to the code execution and defeats ASLR on x86-64 with PHP's recommended production setup. They only share it with their own customers. And SOCRadar found, on an exposed attacker server, what the operator called a one-click exploit for PHP eight point four point twenty-six under Apache mod_php, which leaks addresses through a session cookie to beat ASLR. Alongside it were scripts that screen sites for the preconditions. Hunt.io said the same actor probed one hundred twenty-three servers, about fifty-seven ran PHP, ten rejected the request, and none was compromised. So the tooling is getting better in the open. Someone also built a scanner that fingerprints vulnerable servers, which means target lists are probably being compiled right now. Cobalt's CISO called this quiet stretch borrowed time. That's a fair phrase. And there's still a lot we don't know. We don't know if there are quiet, targeted compromises nobody's noticed, and we don't know how fast a reliable exploit reaches the botnets.
Kate: And then on Friday a third bug showed up. Should we worry about that one?
Dade: Probably not as much, and the PHP Foundation was quite candid about it. It's tracked as CVE twenty twenty-six, one-one-five-five-six-oh, and it won't get an emergency fix. It needs a very unlikely combination: an application has to set the session serialize handler to one of the binary or serialize options in its config, then switch it to the plain php handler at runtime with ini_set, before starting the session, with upload progress enabled. The Foundation says they don't expect to see that in practical use, and the temporary mitigation is to set session upload progress enabled to zero until the next regular release. And if you already applied that setting for the second PHP2Shell bug, you've got it covered. So what do I watch the coming weeks? Four things. One: patch progress for everything you don't directly control, like base images, hosters and appliances. Two: the moment a reliable ASLR-bypassing exploit goes public or turns up in botnets, because then the window shrinks from weeks to days. Three: the first confirmed incident, ideally reported by a victim and not a vendor. And four: what the disclosure post-mortems say, because eight weeks of secrecy lost to a leak in the last two days is a lesson about the process itself.
Kate: Dade, thank you, that was a proper deep dive. For everyone listening: patch the runtime, not just the CMS, look for the hidden PHP, and treat this quiet moment as borrowed time. Have a good weekend, and we'll be back with your daily briefing on Monday.
Two critical vulnerabilities in the PHP core got an emergency patch after the embargo broke. Millions of attack attempts, but no confirmed successful attack yet: what is real, what is overblown and what should you do now?
Read the article →