What hit our customers in one week: .env hunts, fake Googlebots, and malware sweeps
· Witen Labs · Field report
The week in numbers
From October 14 to October 21, 2026, Witen recorded 36,474 security-related requests, logins, and connections from 2,989 addresses against our customers’ sites and servers. Most are plainly hostile: failed logins and probes for files that shouldn’t be public. Some aren’t, and we say so where it matters. Almost none of it was aimed at those sites in particular. It’s the background noise every server on the internet gets, and knowing exactly what it asks for tells you exactly what to lock down.
The evidence that it isn’t targeted: 85% of the web requests asked for something that doesn’t exist and got a 404. A scanner that had studied a site would ask for what the site runs. These ask every server for the same list and keep whatever answers. The useful question isn’t who is scanning you, because the answer is everyone. It’s which of these requests would succeed on your site.
| What | Events | Addresses |
|---|---|---|
| Suspicious web requests: secrets files, malware paths, path traversal | 14,622 | 193 |
| SSH connections dropped before logging in | 4,975 | 1,732 |
| SSH logins for users that don’t exist | 3,781 | 1,060 |
| SSH password failures | 2,426 | 303 |
| PHP exploit attempts | 1,347 | 201 |
| Failed WordPress logins | 1,103 | 157 |
| WordPress XML-RPC requests | 977 | 207 |
| Everything else | 7,243 | 592 |
One address often shows up in several rows, so the address column doesn’t add up to the total. Every day of the week brought between 4,300 and 7,100 events from roughly 500 to 560 addresses. There was no quiet day.
Everyone wants your .env file
/.env drew 107 addresses on its own. In all, 124 addresses asked for 584 different spellings of it, 4,346 requests between them: .env.local, .env.production, .env.backup, .env.old, .env.save, .env.bak, /api/.env, /app/.env, and hundreds more. AWS credentials files (/.aws/credentials) drew 42 addresses.
GET /.env.backup 404 Mozilla/5.0 (iPhone; CPU iPhone OS 17_3_1 like Mac OS X) ...
GET /.env.old 404 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...
GET /.aws/credentials 404 Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...The reasoning is simple economics. Laravel, Node, Docker Compose, and most modern frameworks keep database passwords, API keys, and cloud credentials in .env. If the web server’s document root is the project folder, that file is a plain-text download. One successful fetch is worth more than any exploit: no code runs, nothing crashes, and the attacker leaves with working credentials. The requests dress up as ordinary browsers on phones and laptops so they blend into your access log.
# nginx: refuse every dotfile except /.well-known/ (certificate renewal needs it)
location ~ /\.(?!well-known/) { deny all; }
# Apache
RedirectMatch 404 /\.(?!well-known/)
# Then check from outside, following redirects. You want 403 or 404.
# Any other status means look closer: the test is whether your secrets come back.
curl -sL -o /dev/null -w '%{http_code} %{url_effective}\n' https://example.com/.env
curl -sL https://example.com/.env | head -c 200What to do: keep .env and credentials files outside the document root, have your web server refuse every path that starts with a dot except /.well-known/, and then request /.env on your own site to confirm it fails.
SSH: still mostly root
1,177 addresses tried a username and password. root was tried from 296 of them, then admin (122), a blank username (108), ubuntu (66), user (50), deploy (32), test (27), and git (19). The list reads like an inventory of defaults: the root account, the account cloud images create, and the accounts that deployment tools and Git servers set up.
Another pattern is quieter. 1,732 addresses connected and hung up before logging in, and 715 of them never tried a username at all. Some of that is ordinary: dropped connections, monitoring checks, and clients that gave up. But connecting, reading what answers, and leaving without a word is also how scanners catalog what a server runs and decide whether to come back.
# /etc/ssh/sshd_config.d/10-keys-only.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
# Check the result before you log out of your current session:
sshd -t && sshd -T | grep -E '^(passwordauthentication|kbdinteractiveauthentication|permitrootlogin) 'What to do: use SSH keys, turn off password and keyboard-interactive logins, and allow root to log in with a key only, or not at all. We made our own production server key-only this week.
Old PHP exploits never die
PHP exploit attempts came from 201 addresses. Plenty were for holes closed years ago, or for mistakes no patch can fix:
- PHPUnit’s
eval-stdin.php(CVE-2017-9841, fixed in PHPUnit 4.8.28 and 5.6.3 in November 2016): 211 requests from 17 addresses, under 37 different paths. The file runs whatever PHP arrives in the request body, so a copy left under a publicvendor/folder is remote code execution. wp-content/plugins/hellopress/wp_filemanager.php, from 22 addresses. No plugin called hellopress exists in the WordPress plugin directory, so nobody installs it on purpose. Scanners ask for it to find a file manager that another attacker already planted.phpinfo.php(18 addresses) andinfo.php(20), looking for a forgotten debug page that prints the PHP version, extensions, file paths, and sometimes environment variables.
POST /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php 405
GET /wp-content/plugins/hellopress/wp_filemanager.php 404These keep coming because they’re free to try and still work somewhere. This week’s PHP2Shell flaws are the opposite case: brand new, and in PHP itself rather than a stray file, so the fix is a PHP update. Our PHP2Shell guide covers which versions are fixed and what to ask your host.
What to do: install production dependencies only (composer install --no-dev), point the document root at the app’s public folder so vendor/ is never reachable, and delete debug pages once you’ve read them.
WordPress logins, XML-RPC, and unfinished installs
Failed WordPress logins came from 157 addresses, and one address made 382 of the 1,103 attempts. XML-RPC drew 977 requests from 207 addresses, but not all of it was hostile: 400 of those requests, 41%, identified themselves as Jetpack or WordPress.com, which use XML-RPC legitimately. Blocking it outright can break those services.
The quieter probe: 99 addresses asked for /wp-admin/install.php. They’re looking for a WordPress that was uploaded but never set up. Whoever finishes the installer picks the admin password and can run code on the server from there.
What to do: limit login attempts and turn on two-factor sign-in (Witen Blocker does both), only disable XML-RPC if nothing you use needs it, and finish a WordPress install the moment you upload it.
Fake Googlebots
820 requests claimed to be Googlebot. Five of them were. Those five came from Google’s published crawler addresses, resolved to googlebot.com and back, and fetched images and favicons, as a crawler should.
- 89% came from a single address with no connection to Google. In under 14 hours it asked for 151 different paths, and almost none of them were pages:
/.git/config,/.git/index,configuration.php,wp-config.php, and dozens of.envvariants. - About 10% came from Google Cloud: eight rented servers in Google’s cloud ranges, hunting for
.envfiles just like everyone else. A rule that trusts any address owned by Google would have let them in. - The rest, five requests, came from three other addresses probing WordPress’s REST API.
GET /.git/config 404 Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
GET /.git/index 404 Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)Why bother faking it? Because sites trust Googlebot. Rate limits, firewalls, and paywalls often wave it through so search rankings don’t suffer. A User-Agent is just text, so any rule that trusts “Googlebot” without checking the address hands that trust to whoever types it.
# 1. Reverse lookup: real Googlebot resolves to crawl-*.googlebot.com
host <address from your log>
# 2. Forward lookup: that name must resolve back to the same address
host crawl-<...>.googlebot.comWhat to do: verify crawlers before trusting them, either with a reverse and forward DNS lookup or against the crawler address list Google publishes (Google’s verification guide). Match the crawler list, not just Google’s network, and don’t let a User-Agent alone decide anything.
Malware sweeps dressed as routers
The strangest traffic came in three bursts. Three addresses made 714, 1,977, and 2,175 requests, every one for a different path, each burst over in 8 to 17 seconds. Each rotated through more than 200 User-Agents, and about half of those named home routers, NAS boxes, and network switches: Mi Router 3E, Tenda-AC5, UniFi Switch 8 PoE, and DD-WRT.
GET /kirk.powerpc 404 Mi Router 3E/V2.6.5 UPnP/1.0 Xiaomi/Mi Router 3E
GET /bot-armv7l 404 ASUS Router Y989-H8 6.3.1
GET /dj/dj.m68k 404 DD-WRT v3.0 (Linux)The paths are malware file names. 87% were Windows executables or PowerShell and shell scripts, and the rest included Linux binaries named for the processor they target: m68k, powerpc, armv7l. Our read: someone is checking which servers already host malware payloads, either to reuse them or to catalog them. Every request got a 404.
What to do: nothing on an ordinary site, but it makes a good self-check. If a path like these ever returns 200 on your server, something else is wrong, and it needs looking at today. Rate limits on 404 bursts keep the noise out of your logs.
The short checklist
- Refuse dotfiles (
/.env,/.git/,/.aws/) at the web server, except/.well-known/. - Use SSH keys, with no password logins and no root password login.
- Keep development dependencies,
vendor/, and debug pages off the public web. - Limit WordPress login attempts, turn on two-factor sign-in, and never leave an install unfinished.
- Verify crawlers by their published addresses, not by User-Agent.
- Keep PHP itself patched. Start with the PHP2Shell fixes.
How we see this
These numbers come from Warden, our Linux agent that reads server logs and bans repeat offenders at the firewall, and from Witen Blocker for WordPress. Both are free. If you see an address in your own logs, check it against what we’ve observed with the IP reputation lookup.