14:00 UTC on October 21. That was the slot the PHP security team picked for its emergency out-of-cycle release, one day after details of CVE-2026-109618 and CVE-2026-109619 leaked ahead of the coordinated disclosure. Both have a CVSS v4.0 score of 9.2, and the threat feeds have already nicknamed the pair "php2shell". watchTowr reproduced the first one in a lab. When the leak happened, nobody had confirmed widespread exploitation in the wild. Fixes shipped for 8.2, 8.3, 8.4 and 8.5. If your server answers to 7.4, 8.0 or 8.1, nobody upstream is coming to help you.
Most of the triage guides I've read this week, including the Medium piece that got me writing, take that EOL group seriously and give them a tidy hardening plan: switch off allow_url_fopen, set open_basedir, put a long list in disable_functions, block .php under the uploads folder in Nginx, and lock the origin behind the WAF's CIDR ranges. I'd want all of that on any box. My problem is the reassurance that comes with it, the idea that disable_functions stops a shell before it gets to the kernel. We're talking about a flaw in the runtime's own request handling. It is exploitable without authentication, and it triggers before your router, your auth middleware or your ACLs load. A php.ini directive is enforced by the same C code the attacker is busy corrupting.
This isn't a hypothetical worry. disable_functions has a long and fairly embarrassing record of bypasses, and that record comes from attackers who only had userland PHP to work with. Once someone gets memory corruption inside the interpreter, they're past the layer that checks whether a function name is allowed. The function list makes the lazy payloads fail, the ones copied off a pastebin that just call system(). It does very little against whoever reads the diff properly. The guide's own numbers say scanners turn upstream diffs into working probes within two to six hours of a commit. That's well before the change-approval meeting for your 7.4 cluster gets onto a calendar.
Here's the best argument against me, and I'll make it properly. Plenty of shops can't upgrade at zero notice. Some run a billing system from 2019 that uses each() in eleven places. Some have an ionCube-encoded vendor module that only loads on 7.4. Some are stuck with a hosting contract that hands out whatever version the control panel ships. For them, layered hardening plus watching outbound sockets from www-data is the honest best they can do tonight, and calling it pointless would be cruel. I agree with all of that. Tonight it's the right move. I just don't want it to turn into the plan for next quarter.
The thing that makes this incident useful is that it puts a number on a decision you've already made. Running 8.1 past its end of life was always a bet that nothing critical would turn up in core before you migrated. Usually the bet pays off and nobody remembers it was made. This month it didn't pay off for a lot of fleets, and the price showed up as a weekend of grepping web roots for base64_decode and gzinflate, reading crontabs, and checking whether /dev/shm is mounted noexec. Put those hours into the migration estimate, because they're the interest you pay for staying on an old version.
One unglamorous part of the guide deserves more attention than it'll get: the inventory. which -a php, a sweep of /opt/cpanel/ea-php* and /opt/plesk/php, and docker exec into every container because the host doesn't list them. I'd bet a coffee that half the teams who scrambled this week found a PHP binary they didn't know about. My guess is a queue worker on a different build from the FPM pool, or a sidecar image someone pinned to php:8.0 in 2022 and forgot. The Go folks enjoy saying a static binary has no runtime to patch. That's fine until they need to rebuild forty services because the toolchain had a CVE. Everyone's dependency graph is bigger than they think. A core advisory just makes ours visible all at once.
So, after the patch is out and the checklist is done: get every runtime you run onto a supported branch, and treat the php.ini hardening as an extra seatbelt, not as the reason you can skip upgrading. Being one minor version behind is debt you can manage. Being on an EOL branch means you're betting your security on nothing serious being found in core, and this week the bet lost.
What I really want to hear from people who run real fleets is how you get EOL runtimes into your budget before an incident forces it. Is there an argument, or a metric, or a monthly report that actually got management to fund a 7.4 migration where you work? Or did it take a scare like php2shell every time?




Comments
No comments yet — be the first.
Open the discussion
No account or password needed — just enter your e-mail and we’ll send you a one-time sign-in link. First time here? You’re set up automatically.
Your rating will be applied automatically after you sign in.
Check your inbox
We’ve sent a sign-in link to …. Open it on this device — this tab will sign you in automatically.
Nothing arrived? Check your spam folder — and mark the mail as "Not spam" so it lands in your inbox next time.