65,478 SSH login attempts hit one of our servers last month, from 1,789 distinct IP addresses. Not one succeeded. What’s interesting isn’t the volume — it’s that 651 of those attempts used our own brand name as the username, which breaks the comfortable assumption that this kind of scanning is completely blind.

We had thirty days of logs sitting on our own infrastructure, so instead of describing what an attacker might do, we counted what actually arrived. Here’s the whole dataset.

What We Measured

The subject is a single virtual private server with a public IPv4 address, running two WordPress publications behind nginx. There’s nothing notable about it: no enterprise traffic, no valuable brand, no reason for anyone to single it out. That’s what makes it useful — it’s the baseline every small site operator is sitting in.

Data comes from two sources over the same 30-day window ending July 29, 2026: the systemd journal for the SSH daemon, and nginx access logs for both sites. Every count below is raw log lines, deduplicated only where stated.

The SSH Numbers

SSH activity, 30 days Value
Total invalid-user login attempts 65,478
Distinct source IP addresses 1,789
Failed password attempts 0
Successful password logins 0
IPs responsible for half the volume 108
IPs that tried exactly once 293
Quietest hour / busiest hour (UTC) 1,654 / 3,798

Two of those rows carry the whole story.

Zero failed passwords next to 65,478 attempts isn’t a contradiction. The server doesn’t accept password authentication at all — keys only. Attackers never reach the stage where a password gets checked, so they’re rejected before they can guess anything.

That distinction matters when you read your own logs. A high “invalid user” count with zero “failed password” lines means nobody rattled the door. They only walked past it.

The traffic never stops. Averaged across the month, every hour of the day saw between 1,654 and 3,798 attempts. No overnight lull, no weekend dip, no business hours. That flat line is the clearest evidence that nothing human is involved.

What the Usernames Give Away

Attackers advertise their business model through the account names they try. Ours broke down like this:

Username attempted Attempts
admin 6,320
ubuntu 5,508
user 3,188
debian 2,000
solana 1,944
test 1,509
solv 1,313
deploy 1,149
sol 1,051
postgres 770
git 759
ftpuser 698
pi 666
dev 656
cvedaily 651

The top of the list is boring on purpose: default accounts that ship with Linux distributions and cloud images, tried on the chance somebody left one enabled with a weak password. This is T1110.001 Password Guessing in its purest form — no finesse, just volume.

The middle of the list is where the money is. solana, solv and sol together account for 4,308 attempts — more than user, more than debian. Those are conventional service account names on Solana validator nodes.

The people behind that slice don’t want a web server to deface. They want wallet keys, because a hit is instant and irreversible. It’s the most concentrated intent in the dataset, aimed at a category of machine we don’t even run.

postgres points at databases worth dumping or ransoming. git and deploy are sneakier than they look: the prize on a build or deployment account usually isn’t that machine, it’s the credentials it holds for other machines.

Then there’s the last row. cvedaily — our own brand — was tried 651 times. That name isn’t in any generic wordlist. Some slice of this traffic resolved the hostname, pulled the brand out, and fed it back as a candidate username.

It’s a useful correction. Most scanning really is blind, but a measurable portion does one cheap enrichment step first. If your company is called Northwind, northwind is already in somebody’s list.

Where It Comes From

We sampled the most persistent sources. The top four traced to two mainstream cloud hosting providers and two smaller hosting operators — DigitalOcean addresses appeared twice in the top four. None of them traced to a residential connection.

That’s the economics of the whole operation. Scanning infrastructure gets rented cheaply, often with stolen payment details, used until abuse reports pile up, then discarded.

The distribution backs it up: 108 addresses generated half of all traffic, while 293 addresses showed up exactly once and never came back. That long tail is machines that got listed, scanned, and taken offline mid-campaign.

A Different Shopping List on the Web Side

Requests to the two websites showed completely different priorities:

Path requested Requests
/wp-login.php 373
/xmlrpc.php 352
/wp-cron.php 71
/.env 16
/wp-admin/install.php 16
/phpinfo.php 15
/.git/config 13
/wp-config.php 11

The volume here is three orders of magnitude below the SSH noise, and the intent is sharper. /.env and /.git/config are attempts to read config files that developers ship by accident. One exposed .env can hand over API keys, database credentials and third-party tokens in a single request. That’s why it stays on every scanner’s list even though it rarely works.

One detail worth stealing for your own monitoring: those login and XML-RPC attempts were spread thin enough across the month that they never tripped a per-IP rate limit. Distributed low-and-slow probing is the norm now. The loud brute-force burst that rate limiting was built to catch is the exception.

They’re Looking for Each Other’s Backdoors

About fifteen distinct filenames showed up in the logs, each requested between eight and twelve times, all in the site root:

/w3lls.php
/zero.php
/OVO7xf.php
/this_is_a_new_hello_world.php
/sixxis.php
/mosty.php
/fpwch.php
/1xmomo.php
/wp-content/plugins/hellopress/wp_filemanager.php

None of these are WordPress files. None match a vulnerability in any real plugin. They’re the filenames of known web shells — the backdoors attackers upload after they’ve already compromised a site, to keep their access.

Scanning for them isn’t an attempt to break in. It’s an attempt to find sites somebody else already broke into, and walk through the door the first intruder left open. Compromised hosts are a commodity, and inheriting one costs nothing next to earning it. The near-uniform request count across every filename shows a single campaign working a checklist.

This hands you an unusually cheap diagnostic. Those paths should return 404 on a healthy site. If any of them returns 200, you’re not asking whether you might be compromised anymore. Grep your access logs for successful responses to unexplained root-level PHP files — it’s one of the few security checks that costs nothing and gives an unambiguous answer.

Historical Context

None of this is new, and the most instructive precedent is Mirai in 2016. It spread by trying a list of roughly 60 default username and password pairs against internet-exposed devices — the same technique in our logs, aimed at cameras and routers instead of servers. By October 2016 the botnet it built was large enough to knock Dyn offline and take much of the US internet’s DNS with it.

What’s changed in a decade isn’t the method. It’s the targeting. Mirai hunted anything with a default password; the campaigns in our data go straight for solana, postgres and deploy because crypto keys and credential stores pay better than bandwidth. Same T1110 Brute Force technique, better market research.

Why None of It Worked

Nothing here was stopped by anything clever. Three ordinary decisions account for the entire outcome.

Key-only SSH authentication. This is what turns 65,478 attempts into 65,478 non-events. A password can be guessed given enough tries; a key can’t. It maps to IA-5 Authenticator Management in NIST SP 800-53, and it’s the one line in your SSH config that does the most work. Turning off password authentication doesn’t quiet your logs — it removes the mechanism the noise depends on.

Nothing sensitive served over HTTP. Every request for /.env, /.git/config and /wp-config.php returned 404. These scans stay profitable somewhere, which tells you how often they aren’t.

No stale attack surface. XML-RPC blocked, PHP execution disabled in the uploads directory, current core and plugin versions on both sites. The web shell scan found nothing because there was no earlier compromise to inherit.

We added automated banning afterward. It cuts log noise and closes the window on a future misconfiguration, but it changes the shape of the graph, not the outcome.

Data at a Glance

Metric Value
SSH login attempts, 30 days 65,478
Distinct attacking IPs 1,789
Attempts using crypto-node account names 4,308
Attempts using our own brand name 651
Web requests probing for exposed files 1,260
Successful intrusions 0

Our Take

The number everyone quotes from a dataset like this is the big one, and it’s the least useful. 65,478 is just weather. We think the row that should change behavior is 651 — the attempts using our own brand as a username. It’s a small number, and it quietly kills the assumption most people use to sleep at night, that nobody knows or cares what their server is called. Somebody’s scanner did one DNS lookup and knew. If your onboarding docs tell new hires to create an account named after the company, that convention is already public.

The CVEDaily Take

Password authentication on a public SSH port stopped being a defensible default years ago, and this dataset is what that decision looks like in numbers: 65,478 attempts, zero of which got far enough to guess anything. The web shell scanning is the part that should keep you honest — attackers are actively shopping for sites that were breached and never noticed. When did you last grep your access logs for 200 responses on PHP files you didn’t put there?

FAQ

  1. Does 65,000 login attempts mean my server is being targeted?
    Almost certainly not. Tens of thousands per month, spread across hundreds or thousands of IPs using generic usernames, is the baseline for any public IPv4 address. Real targeting looks different: few sources, usernames specific to your org, and probing tied to software you actually run.

  2. Should I move SSH off port 22 to reduce this?
    It’ll cut your log volume, because most scanners only check 22. It won’t add real security — a full port scan finds the new port in seconds. Key-only authentication is the control that matters. A non-standard port is noise reduction, not defense.

  3. How do I tell if a web shell is already on my site?
    Search your access logs for 200 responses to PHP files in your web root that aren’t part of your CMS. A legitimate WordPress install serves a small, known set of root-level PHP files. Anything else returning 200 needs investigation today.

Methodology and Limits

This is one host, one 30-day window, one IPv4 address in one provider’s range. Volumes vary a lot by provider, address block, and how long an address has been in use — an IP recycled from a previous tenant inherits that tenant’s attention. Username distributions shift as campaigns rotate, so the Solana-heavy slice reflects what paid during July 2026 and won’t be permanent.

Counts are raw log lines from the SSH daemon journal and nginx access logs over the same window, with no sampling. Source addresses were checked against public registration records. We haven’t attributed any activity to named groups, and the filenames above are reported as observed strings, not as confirmed indicators of any specific malware family.