top of page

CISA Told Every Agency to Patch PHP by Today. Eleven of the 28 Federal Sites We Checked Advertise PHP in Their Own Response Headers. DHS, Which Owns CISA, Serves Drupal 11.

Writer: Patrick Duggan
Patrick Duggan
1 hour ago
9 min read

Federal agencies had until today, October 29, to remediate the two PHP flaws known as PHP2Shell under Binding Operational Directive 26-04. Both are unauthenticated remote code execution. Both were added to the Known Exploited Vulnerabilities catalog on October 26, five days after the emergency PHP releases.


Reading that, the obvious question is not "is PHP bad." It is how much PHP is actually out there, and the honest answer is that nobody has to guess, because a great many web servers announce it in their own response headers to anyone who asks politely.


So we asked politely. One ordinary homepage request each — the same request your browser makes — to 28 federal hostnames, reading only the headers each server volunteered. No path probing, no scanning, nothing an attacker would do and nothing we would do to somebody else's infrastructure.


Eleven of 28 advertise a PHP platform in their own headers.





The census


Seven are Drupal, which is PHP: dhs.gov (x-generator: Drupal 11), irs.gov (x-generator: Drupal 10), justice.gov, energy.gov, noaa.gov, gsa.gov and house.gov.


Three are WordPress, which is PHP, identified by the wp-json API link every WordPress install publishes: nasa.gov, state.gov and share.america.gov.


One says it outright. sba.gov returns x-powered-by: PHP/8.3.36 — a precise runtime version, in a public header, to anybody who connects.


Underneath those eleven, the stack is the one you would expect from the acronym: Apache on dhs.gov, irs.gov, state.gov, sba.gov, energy.gov, noaa.gov and house.gov. BigIP in front of irs.gov and energy.gov, Akamai in front of dhs.gov, Cloudflare in front of justice.gov.


The other seventeen showed no PHP tell, and here is the part that matters more than the number: no tell is not a finding. america.gov returns nothing but server: cloudflare, and its own content property, share.america.gov, is unmistakably WordPress. A reverse proxy that strips headers produces the same silence as a server that has no PHP on it. We spend a lot of our time on false zeros in our own instruments, and this is one: eleven is a floor, not a count.


What the quiet seventeen do reveal is the other architecture, and it is the more interesting half. treasury.gov answers from AmazonS3. va.gov carries x-amz-request-id. state.gov and house.gov sit behind awselb/2.0. The federal web estate has split cleanly in two: the properties that were rebuilt as static sites on object storage shed PHP entirely, and the properties that are still content-managed kept Apache, kept Drupal or WordPress, and therefore kept PHP. The migration to AWS is visible in the headers as a PHP exit.


None of this says a single one of those sites is vulnerable. Patched Drupal is fine. Patched WordPress is fine. PHP 8.3.36 may well be a patched build — we did not test, and we are not going to imply otherwise from a banner. This is a platform census, not a vulnerability assessment, and the distinction is the whole reason it is worth publishing: the directive's deadline lands on a population nobody has fully inventoried, including the department that issued it.



Ten PHP bugs have made the must-patch list. Exactly one names an operating system


Having established that PHP is everywhere, the second question is whether the platform underneath changes what happens to you. We joined every PHP-lineage entry in CISA's catalog — version 2026.10.28, 1,762 entries, pulled from the public JSON feed today — and read what each says about the system beneath.


Ten entries, 2009 to last Monday. Three flagged as used in known ransomware campaigns: PHPMailer CVE-2016-10033, PHP-FPM CVE-2019-11043, and PHP CVE-2024-4577. The rest: phpMyAdmin CVE-2009-1151, PHP CVE-2012-1823, PHPUnit CVE-2017-9841, ThinkPHP CVE-2018-20062 and CVE-2019-9082, and the two new ones, CVE-2026-109618 and CVE-2026-109619.


Exactly one of the ten names an operating system in its own description, and it is CVE-2024-4577. CISA's words: "PHP, specifically Windows-based PHP used in CGI mode, contains an OS command injection vulnerability." Not PHP — Windows-based PHP, in CGI mode. The flaw is a character-encoding seam. Windows best-fit encoding quietly maps certain characters into the hyphen that PHP's CGI handler reads as the start of a command-line argument. The identical PHP build on Linux does not have it, because the seam belongs to the operating system.


That is the only place in sixteen years of this catalog where the platform is part of the bug. Which is the more useful finding, because it means the platform almost never decides whether you have the vulnerability. It decides what happens after.



Windows: the only platform-gated RCE, and the deadline was 848 days ago


If you run PHP in CGI mode on Windows you own the one platform-gated remote code execution in the catalog, and it is ransomware-flagged. Listed June 12, 2024. Due July 3, 2024. That deadline is 848 days behind us.


Nobody chose php-cgi on Windows in 2026. They inherited it: an appliance management console, a vendor intranet tool, a billing system a contractor stood up in 2016, an OEM device whose web interface happens to be PHP.


Windows also raises the ceiling. A Windows web stack is far more likely to run as a service account inside an Active Directory domain. On Linux, code execution as the web user is code execution as the web user. On Windows, code execution as a domain-joined service account is routinely the first half of a domain problem.



Linux: the bug is PHP's, and the kernel hands over root


Linux has no PHP flaw of its own in the catalog. Linux supplies the second half of the chain.


That is exactly what ran last week. An operator used the PHP2Shell flaws to land a web shell on internet-facing firewalls, then chained CVE-2026-46300 — the XFRM ESP-in-TCP Linux kernel bug called Fragnesia, public with a working exploit and a patch on the same day, May 13 — to turn that web shell into root. From root: a reverse SSH tunnel, an internal firewall management server holding credentials for every firewall that organization managed, a decrypted LDAP service account, domain enumeration, attempted Active Directory backdoors.


PHP got them the door. The kernel got them the building. Only the door had a federal due date: Fragnesia reached KEV on October 28, 168 days after disclosure.


Linux also carries the older ransomware-flagged server bug, CVE-2019-11043, the php-fpm underflow that certain nginx fastcgi_split_path_info configurations turn into remote code execution. Listed March 2022, and still out there in the deployment nobody re-reads: a working nginx config copied from a blog post in 2018.



macOS: the PHP you have is one you chose


There is no macOS-specific PHP entry in the catalog, for a simple reason. Apple deprecated the bundled PHP in macOS Catalina and removed it outright in Monterey. Since 2021, a Mac with PHP on it is a Mac where somebody installed PHP.


That is safer in one way — no vendor-default runtime sitting on millions of laptops waiting for Apple. It is the most interesting surface in another, because an installed-by-choice runtime is a runtime outside anybody's patch management. Homebrew's PHP updates when the developer runs an upgrade. MAMP's updates when they notice the badge. Laravel Herd and Valet put a PHP-FPM listener on a developer's machine by design, on whatever coffee-shop network that laptop is on.


Then there is the case we think matters most, because it is new and growing: PHP shipped inside a desktop application binary. NativePHP packages a full PHP runtime into a Mac or Windows desktop app. The vendor ships PHP as part of their product. When PHP publishes an emergency release, as it did on October 21, the fix reaches the user only when the app vendor rebuilds and the user updates the app — not when PHP ships, not when the OS updates. There is no php -v for a scanner to find, no package-manager entry, no CVE match, and frequently no administrator who knows a PHP runtime is on that endpoint at all.


NativePHP has two advisories worth knowing: GHSA-83jv-8h7x-287p, arbitrary object instantiation via its local API endpoint, and GHSA-76px-r497-93p9, a traversal in its asset handler. Both are small. The distribution model is the large part.



The worst PHP stack you could possibly be running today


Assembled from parts that are all real, all current, and all on somebody's network right now.


Start with php-cgi on Windows Server with a locale that best-fit maps, because that is the only platform-gated RCE in the catalog and it is ransomware-flagged. Put it behind an internet-facing management interface, which is where last week's campaign found its 25 victims. Leave session.upload_progress enabled — PHP's own default — because that is the primitive the PHP2Shell work travels on, a multipart POST body field carrying a serialized object. Run it under a domain service account, so execution is a domain problem. Advertise your exact PHP version in a response header, and leave /vendor/composer/installed.json readable, so nobody has to guess which exploit to bring.


Give it a Linux sibling: nginx with php-fpm on a 2018 config, on a host whose kernel never took the Fragnesia patch, so the web shell becomes root.


Hand the organization a NativePHP desktop app with a bundled runtime two emergency releases behind, which no asset inventory knows exists.


And for the finish, put phpMyAdmin on the same box. CVE-2009-1151 is seventeen years old and still on the federal must-patch list, which tells you how long this furniture lives.


Not a strawman. Every component has been measured in production by somebody this month. The assembly is ours and it is rhetorical; the parts are not.



What our own edge measured, including what it cannot see


We are a two-person shop and our sensors did not see that campaign. Here is what they did see, and the shape of what they could not.


Until October 25 we had no canary for any PHP or Composer path at all, so our edge could not have recorded PHP2Shell reconnaissance even if it arrived. The honest reading of that zero was blindness, not safety, and we said so at the time. We trapped the paths. What showed up immediately, having passed unnoticed before: /vendor/composer/installed.json — dependency shopping, the step before exploit selection — plus Symfony profiler phpinfo paths and /app_dev.php. Six edge blocks on the Composer manifest alone in the window we examined. That is the same behavior sba.gov's header hands over for free, without anybody needing to probe for it.


Two limits, because they change what our data can mean. The PHP2Shell primitive travels in a request body, and a path matcher only ever sees a path, so a body-only attempt does not appear in our instrument at all. And Cloudflare answers HTTP 400 to plain directory traversal before our code runs, so the ../ variants are invisible on our own zones and only deliberately evasive encodings reach us. We know which of our own markers are dead. We would rather print that than a bigger number.



What to actually do, in order


Patch PHP. The October 21 emergency releases close CVE-2026-109618 and CVE-2026-109619. The federal deadline is today.


Patch the kernel, not just the application. Fragnesia's mitigation has been free since May 13 and needs no reboot: unload the esp4, esp6 and rxrpc modules, blacklist them so they cannot reload, then drop the page cache, because the exploit lives in cached pages.


If you run PHP in CGI mode on Windows, stop. Move to FPM or a real application server. If you cannot, CVE-2024-4577's locale and handler mitigation has been available since June 2024.


Turn off the version banner. expose_php = Off is one line and it removes a free reconnaissance gift. Stop serving your Composer manifest to the internet while you are in there.


Find the PHP you did not deploy. Bundled desktop runtimes, developer laptops, vendor appliances, that one intranet tool. An inventory built from package managers does not contain the PHP inside an app binary — and an inventory built from response headers, like the one above, finds eleven when the real number is higher.


Our blocklist of currently active attacker infrastructure is free and needs no sales call: the IP, domain and hash lists are at analytics.dugganusa.com/api/v1/stix-feed, registration takes about thirty seconds, and you set the confidence floor, not us.



Limits


The census is 28 hostnames, one homepage request each, headers only, read today, October 29, 2026. It is a convenience sample we picked by hand, not a representative survey of the federal estate, and the eleven is a floor because header-stripping proxies produce the same silence as an absence of PHP. We did not test, probe, scan or authenticate against any of these sites, and we are not naming any of them as vulnerable — Drupal, WordPress and PHP 8.3.36 are all perfectly fine when patched, and we have no information about whether they are.


The KEV figures are CISA's, catalog version 2026.10.28, 1,762 entries. Re-pull them; that is why we cited the version. The ransomware flags are CISA's assessment, not a measurement of ours, and we did not independently test CVE-2024-4577 or CVE-2019-11043.


The October firewall campaign is Dream's research as carried in secondary reporting. We have not independently verified it and we hold no indicators from it — no IPs, domains or hashes from it have been published that we could ingest, so there is nothing of that campaign in our feed and we are not implying there is.


The macOS and NativePHP section is an argument about a distribution model, not a vulnerability finding. We know of no in-the-wild campaign against bundled NativePHP runtimes. We think the shape is bad before it is exploited, and we would rather say so early than afterward.


Five percent of this is wrong somewhere. It always is.


Was this useful? Rate this post — the widget is at the bottom of the page, and we read every response. If you ran the same header check against your own estate and found something we missed, that is the reply we want most.




Every indicator in this post is in the feed. Free.

1.58M+ IOCs, STIX 2.1 / TAXII, 88% novel vs ThreatFox, exploited-CVE leads ahead of CISA. No credit card — a free API key in 30 seconds, and you can audit every claim above against the live endpoints.


Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
bottom of page