Blog · · HoneyLabs
A 32-node Azure fleet is checking the internet for 1,197 webshell filenames
Over fifteen complete days in September and October, 32 short-lived Azure machines asked our honeypots for 1,197 specific PHP filenames, the names webshells get saved as, sending each name once as a bare GET with no User-Agent. The list is sharded across the nodes, 43 percent of it matches what SANS ISC logged from the same tooling in April, and the full list is here to grep a web root against.

If any of 1,197 specific PHP files exists in your web root, a fleet of Azure machines wants to know, and it has been asking every host it can name for the past two weeks. This is about WordPress sites first and any PHP site second. The list is downloadable and one find command compares it with a web root.
HoneyLabs runs honeypots: servers on the public internet that host nothing and that nobody links to, so everything arriving at them is a scan, a probe or a crawler. The requests below are what one operation sent to those honeypots over fifteen complete days, 22 September to 6 October 2026. That bounds every number here: this is the fleet as our sensors saw it, which is a sample of its work and not the whole of it.
The operation does not exploit anything. It sends one GET per filename and reads the answer. The filenames are the ones that webshells, the small PHP scripts an intruder leaves behind to keep a door open, tend to be saved as. So the question it asks of every server is whether somebody else has already broken in. A 200 means yes, and means that door now has a second owner.
The fleet is 32 addresses, all in Microsoft's network (AS8075), spread across twenty different /16 prefixes. No address lived longer than five days and the median lived two; one made its 90 requests inside a single minute and was never seen again. Four addresses we checked against passive port data had no record anywhere, which is what a virtual machine looks like when it was created for the job and deleted after it. The nodes arrive in a stagger, so the census never pauses: as one instance stops, another is already working through its share of the list. Over the fifteen days they made 8,284 requests, every one a GET on port 80, and every one without a User-Agent header.
The empty User-Agent and the opening sequence match two earlier reports. Johannes Ullrich of the SANS Internet Storm Center wrote up the same behaviour on 7 April: four Microsoft-assigned addresses probing 287 URLs, wp-content/plugins/hellopress/wp_filemanager.php among the most requested. Koji Otake, who publishes bot observations from his own servers, documented it again in July and August: Azure ranges, no User-Agent, and an opening sequence that starts with that same hellopress path and then this_is_a_new_hello_world.php. Our fleet opens its runs with exactly those two files, in that order, on every node. Of the 240 PHP paths in Ullrich's April list, 103 are in the list we saw, which is 43 percent six months apart. Our telemetry holds none of these filenames before 22 September, so the April and July waves did not reach us and the overlap figure is the only comparison across time this post can make.
The list is sharded. A node asks for a median of 131 filenames, the smallest asked for 57 and the largest for 419, and only two filenames were requested by all 32 of them: the two that open every run. 299 names were seen from a single node and 372 from two. Watching any one address for a week would show you a tenth of the list and none of its structure. The 1,197 is the union of what the whole fleet asked our honeypots, and since each node seems to carry a slice, the real list is at least that long.
A second request form appears on 26 of the names: the same path with ?p= appended and nothing after the equals sign. 402 requests took that shape, and in thirteen cases the same node asked for the bare file first and the ?p= form later. Several of the names it is attached to, xiugai.php, makeasmtp.php, classwithtostring.php, are known from Chinese-language PHP tooling, and p is a common name for the parameter such scripts expect. The value is always empty, so this is a second way of recognising a particular family of script, not an attempt to drive it. The fleet also asks for three directory listings on every host it can, /wp-content/uploads/ and two wp-admin colour-scheme folders, which are places an upload bug would have dropped a file.
Most of the names are chosen to be overlooked. 526 of the 1,197 are plain words that would not look wrong in a web root: media.php, images.php, about.php, simple.php. Another 230 are WordPress paths or wp- prefixed names, 226 are one to three letters (a.php, sm.php, aa.php), 53 are bare numbers. Only 76 carry a name that says what they are, alfa, wso, shell, bypass, filemanager. The two that open every run are the exception: this_is_a_new_hello_world.php is a name you would only use if you had written the file yourself, and hellopress is not a plugin that exists. Both are near-unique, which makes them the simplest signature of this fleet in a web log.
The purpose is not in the requests. The fleet only ever asked; it never sent a second request to a file that answered, and our honeypots answer the same way to everything, so they were not useful to it. Two readings fit what is visible. One is a competitor taking inventory: find the doors other intruders left, keep a list, come back through them later from different machines. The other is housekeeping by whoever planted some of these files, checking which of their installs are still alive. The 43 percent overlap with a list collected six months earlier, and the two signature names that have not changed in that time, point at a long-running operation either way.
To check a server, download the list of filenames into its web root and run, with bash:
cd /var/www/html # your web root
find . -type f -name '*.php' | sed 's|^\./|/|' | grep -Fxf <(grep -v '^#' webshell-names.txt | cut -f1)
Any hit is a file you should be able to explain. If you cannot, somebody put it there before 22 September, and the fleet is the smaller of the two problems. Ullrich's advice in April was that scanning for filenames is a poor defence on its own, and that holds: the fix for a webshell is the upload or execution bug that let it in. The list is still worth one pass, because the people running this fleet evidently think it is worth 8,284 passes.
In your logs, three things identify the fleet with no false positives in our data: a request for /this_is_a_new_hello_world.php or /wp-content/plugins/hellopress/wp_filemanager.php, an empty User-Agent, and a source in AS8075. Over the fifteen days, nobody outside this fleet asked our honeypots for five or more names from its list; three small European networks contributed a single address apiece that touched one or two. You can test any address against our telemetry at /lookup, and the port 80 page shows the rest of what arrives on it.
Dataset: requests from 32 addresses in AS8075 to HoneyLabs honeypots, 22 September to 6 October 2026, 8,284 requests, 1,197 distinct PHP filenames once ?p= variants are folded onto their base names. Fleet defined as AS8075 addresses with an empty User-Agent that requested five or more of the operation's forty most-requested filenames. April figures from SANS ISC diary 32874; July and August observations from Koji Otake. Passive port data from Shodan InternetDB.