All posts
security 6 min read

What Bots Hit First: Lessons From Our Honeypot's Opening Day

PB
Patrick Britton

We recently deployed a bot honeypot across the MPLS infrastructure. The concept is simple: trap endpoints that no legitimate user would ever visit — WordPress login pages, .env files, database admin panels — and log everything that touches them. We serve fake responses, collect intelligence on who’s scanning and what they’re after, and occasionally hand out a gzip bomb to the greediest crawlers.

The honeypot has been live for about 24 hours. In that window, it’s logged 1,825 attack attempts from 69 unique attackers across 21 countries — with 11 honeypots deployed across 12 production domains. The system is new, but the lessons are already clear — and they’re the kind of thing I wish someone had spelled out for me when I was standing up my first VPS.

The internet doesn’t wait for you to be ready

There is no grace period. The moment your server has a public IP and an open port, it is being probed. Not by sophisticated attackers. Not by anyone who knows your domain name. By automated scanners running 24/7 that cycle through IP ranges and try a checklist of known vulnerabilities on every host they find.

Our honeypot was fielding requests within minutes. Not because anyone cared about mp.ls — because something, somewhere, added our IP to a list and started walking through the playbook.

This is the baseline reality of hosting anything on the internet in 2026. You don’t need to be a target. You just need to exist.

What they’re scanning for

Here’s where the 1,825 requests actually went, ranked by volume:

PHP info probes — 821 hits. By far the most common. Bots requesting paths like /info.php, /about.php, /moon.php, /simple.php, /fm.php — all common filenames for PHP info pages and file managers that developers leave exposed. These aren’t targeted attacks. They’re mass scans looking for any server that responds to .php at all. If you respond with a PHP info page, you’ve just handed the bot your PHP version, loaded extensions, server paths, and environment variables.

WordPress setup scans — 342 hits. Requests to /wp-admin/setup-config.php and /wordpress/wp-admin/setup-config.php. This is the WordPress database configuration page that’s exposed during fresh installs. A bot that finds it can configure your WordPress instance with their own database credentials. They’re not looking for established sites — they’re looking for fresh installs that haven’t been locked down yet. The window between “I just installed WordPress” and “I finished the setup wizard” is a real attack surface.

.env file scans — 176 hits. Requests to /.env, /.env.bak, /.env.save, /.env.production, /.env.production.local. This is the one that should scare you. A .env file typically contains database passwords, API keys, third-party credentials — everything. Laravel, Node.js, and most modern frameworks use .env files, and a single misconfigured nginx or Apache server will serve them as plain text. The bots know this. They try every common variant.

WordPress login — 136 hits. Requests to /wp-login.php with credential stuffing attempts. Two passwords have been guessed so far, both using the username admin. They’re not guessing creatively. They’re trying the defaults.

Git repository scans — 36 hits. Requests to /.git/config and /.git/HEAD. If your .git directory is web-accessible, an attacker can reconstruct your entire source code, including commit history. That history may contain credentials, internal URLs, or API keys that were “removed” in a later commit but are trivially recoverable from git objects.

XML-RPC probes — 10 hits. WordPress’s XML-RPC interface (/xmlrpc.php) is a well-known attack vector for brute-force amplification and DDoS. It’s enabled by default on most WordPress installations.

Where the traffic comes from

The top source countries in our first 24 hours: France, Sweden, Germany, Russia, and the United States. But the country labels are mostly irrelevant — what matters is the hosting provider. The vast majority of this traffic originates from cloud providers and VPS hosts: Cloudflare, Microsoft Azure (ASN 8075 appeared on four separate IPs), and a French host called Bucklog SARL that alone accounted for 372 hits from a single IP.

These are not people sitting at keyboards. They’re rented servers running automated tooling around the clock. One IP from a Swedish Cloudflare proxy hit us 656 times. A single French IP hit 372 times. This is industrial-scale scanning.

What you should do before your first deploy

None of this is new or exotic. That’s exactly the point. The attacks hitting your server on day one are the same attacks that have been working for years because people keep making the same mistakes. Here’s the minimum:

Never serve .env files. Your web server should explicitly deny access to dotfiles. In nginx:

location ~ /\. {
    deny all;
}

This single rule blocks .env, .git, .htpasswd, and every other dotfile from being served. It should be in every server block you write.

Don’t expose .git directories. If you deploy with git (which is fine), make sure the .git directory is not inside your web root, or is explicitly denied. Better yet, deploy build artifacts, not source checkouts.

Remove default install pages immediately. If you use WordPress, Joomla, or any CMS with a web-based installer, the install wizard is an open door until you finish it and delete the files. Don’t leave a fresh install sitting on a public server while you go to lunch.

Disable XML-RPC if you don’t need it. If you’re running WordPress and not using XML-RPC for Jetpack or the mobile app, block it:

location = /xmlrpc.php {
    deny all;
}

Don’t run PHP if you don’t need PHP. This one sounds obvious, but 821 requests hit .php endpoints on infrastructure that doesn’t run PHP at all. If your stack is Node, Go, Python, or static files — make sure your web server isn’t configured to pass .php requests to anything. Let them 404. Or, in our case, let them walk into a honeypot.

Use non-default credentials. The bots try admin / admin. They try root / root. They try test / test. If you’re using default credentials on anything — your database, your CMS, your admin panel — you will be compromised. It’s not a question of if.

Set response headers. At minimum: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, and a Referrer-Policy. These don’t stop bots, but they close real browser-level attack vectors that get exploited after a bot finds a way in.

The meta-lesson

The most important takeaway from running this honeypot isn’t any single mitigation. It’s the realization that your server is being actively probed before you’ve written your first line of application code. Security isn’t something you add after your app works. It’s something that needs to be in place before your server has a public IP.

The bots don’t know what you’re building. They don’t care. They have a checklist, and they’ll run it against every IP on the internet, every day, forever. Your job is to make sure your server doesn’t answer to any of it.

We’ll be writing more about what we learn from the honeypot as the dataset grows. If you want to see the live dashboard, it’s at mp.ls/botcharts.