their planned disclosure. Known as PHP2Shell, CVE-2026-109618 and CVE-2026-109619
order of 70% (Wiz, Endor Labs); PHP runs about 70% of the websites whose server-
old version? The answer is only as good as your monitoring. This post shows how to
test that monitoring before the next advisory, with a fleet of simulated PHP servers
1. Know What Your Monitoring Actually Reads
channels:
- HTTP response headers: By default, PHP announces its version in an
X-Powered-By header, and Apache can add it to its Server header. A scanner
reads them with one request -- and so can an attacker. To see what one of your
own servers announces:
curl -sS -o /dev/null -D - https://your-server/index.php | grep -i -E '^(server|x-powered-by):'
- SNMP inventory: Network management platforms read installed and running
software from the HOST-RESOURCES-MIB tables. This channel works where headers
are hidden, on any server that runs an SNMP agent.
Each channel has blind spots. Learn them before an advisory, not during one.
2. Build a Web Server Lab That Reports Any Version
Each simulated server answers HTTP through the MIMIC Web Simulator and SNMPthrough the MIMIC SNMP Simulator, and reports whatever PHP version you give
it. A thousand servers is a modest lab -- our August post built ten thousand
devices -- and you choose the mix: servers patched on day one, servers on a
vulnerable 8.x release, and a tail of PHP 7 and PHP 5.
One simulated server, before its patch:
$ curl -I http://web-01/
HTTP/1.1 200 OK
Server: Apache/2.4.62 (Win64) PHP/8.3.20
X-Powered-By: PHP/8.3.20
$ snmpwalk -v2c -c public web-01 HOST-RESOURCES-MIB::hrSWInstalledName
...
HOST-RESOURCES-MIB::hrSWInstalledName.17 = STRING: "PHP 8.3.20"
HOST-RESOURCES-MIB::hrSWInstalledName.18 = STRING: "Apache HTTP Server 2.4.62"
Point your scanner and NMS at the lab, and you know the right answer before they
report it: exactly which servers are vulnerable, because you made them that way.
As with the scenarios in our September post, it is a dry run your tools are free to fail.
3. Prove Your Tools Count the Servers They Can't Read
A monitor that alerts on a bad version says nothing about a server that reports noversion. If none of your 100 servers can be read, the dashboard stays green -- and
the true answer to "which servers still run old PHP?" is "we don't know."
This is common. Arctic Wolf's 2026 attack surface report finds 17% of IT assets
Your discovery tools find the servers on your network; a MIMIC lab with a known
count shows how well. Build exactly N servers, make some hard to read, and check:
- Ground truth: does the tool report all N, with the hard ones listed as
unknown?
- Discovery gaps: servers that answer only HTTP or ping, use another SNMP
community or version, or answer nothing on the expected port -- which ones
does it find?
- Classification: does an unreadable server show as unknown, drop out of the
report, or count as patched?
- Scale: does a sweep of thousands of addresses finish, or do timeouts quietly
drop hosts?
- Regression: after an upgrade or configuration change, does the lab give the
same count?
- Process: when the tool flags the PHP 5 billing server nobody can switch off,
does a ticket reach an owner, with the exception on record?
In the lab each is a configuration choice -- a drill you could never run in
production without switching off monitoring on real servers.
4. Test the Hard Cases
The fleet is yours to misconfigure, so give your tools the servers that trip them up:the header channel goes quiet. That is the usual case: the Web Almanac
finds an X-Powered-By header on about a quarter of sites, and a version in
just over a quarter of those. Does your NMS still find the PHP package over
SNMP?
- Version in one header only: With PHP running as PHP-FPM, Apache's Server
header names no PHP version; only X-Powered-By carries it. Does your scanner
read both?
- Vendor backports: "Vendors sometimes backport fixes without changing the
upstream version number" (Datadog). A server can report an old number and
be fixed. Does your tool let you record the exception?
- Channels that disagree: Update the package but not the running service, and
SNMP and HTTP report different versions. Which one does your tool trust?
- Branches with no official fix: More than a third of PHP sites run PHP 7 or
older (W3Techs), and the PHP project no longer releases updates for 8.1
and older. Those servers need an alert of their own, for as long as they run.
5. Patch the Lab and Watch the Alerts Clear
Finding the vulnerable servers is half the job; the other half is knowing when youare done. In the lab, a patch is one command. Here is the same server a few
seconds later, on the fixed release, with no restart:
Server: Apache/2.4.62 (Win64) PHP/8.3.36
X-Powered-By: PHP/8.3.36
HOST-RESOURCES-MIB::hrSWInstalledName.17 = STRING: "PHP 8.3.36"
Patch a hundred servers at once, or in waves the way your team would, and watch
your tools: do the alerts clear, does the inventory update, does the management
report reach zero -- and stay there?
6. Under the Hood: How the Lab Works
Each simulated web server is a MIMIC agent with two protocols turned on: SNMP and WEB.- Start from a real server. We began with a recorded Windows server that already
answers the HOST-RESOURCES-MIB software tables.
one rule for GET and one for HEAD, and each hands the headers to a short Tcl
procedure that writes the Server and X-Powered-By lines from a per-server PHP
version variable.
installed-software table, and httpd.exe and php-cgi.exe to the
running-software table.
entry together, and both channels report the new version on the next request.
The same rule file serves every server; only the version differs. Hiding a banner
is a one-line change to the procedure, and making the channels disagree means
updating one and leaving the other.
The Next Advisory
PHP2Shell will not be the last critical PHP flaw. When the next one lands, thequestion will again be "which servers still run the old version?" -- and your scanner,
To set up a lab like this for your own tools, tell us what you run. Check this short






