Rate limit, move the door, add a second factor

WordPress Brute Force Attacks: How to Make Them Pointless

Identify a brute force attack on a WordPress login by what it leaves behind: repeated failed sign-ins from rotating addresses, load spikes with no matching traffic, and lockout mail nobody triggered. Automated guessing runs against every install continuously, so the target is not the attempt. Rate limiting, a moved sign-in route and a second factor end the exposure rather than slowing it down.

A WordPress brute force attack is automated password guessing against wp-login.php or XML-RPC. It is continuous and universal rather than targeted. Rate limiting, two-factor authentication and moving the login endpoint remove the exposure; blocking addresses individually does not.

Is your site showing signs of compromise?

Checks what an attacker or a search engine would see from outside, including the giveaways of a cloaked hack.

Reads only what any visitor can see — no login, no access needed. We keep the address, your email and what the check found for 1 year, then delete it. How we handle it.

automated login guessing blocked by rate limit and second factor
The path this interrupts: failed logins fill the log then the addresses are blocked then the attempts continue then the exposure never changed.

Symptoms and what they indicate

SymptomWhat it indicatesUrgency
Hundreds of failed logins from rotating addressesDistributed guessing in progressRoutine, but confirm the defences
Lockout notifications nobody triggeredAttempts against a real usernameRoutine
Load spikes with no matching visitor trafficXML-RPC amplificationAct this week
Failed attempts against one specific usernameThe username is known and targetedAct this week
A successful login from an unfamiliar locationThe guessing succeededTreat as a compromise now
New administrator accountsPost-compromise persistenceTreat as a compromise now

Continuous, universal, and not about you

Every reachable WordPress install receives automated login attempts, continuously, starting within hours of the domain first resolving. The traffic is indiscriminate: software walking address ranges, trying common usernames against common passwords.

That matters for the response. Attempts are not evidence of being singled out, and counting them achieves nothing. What matters is whether any of them can succeed, which is a question about your passwords rather than about their volume.

Why blocking addresses is the wrong instinct

The first reaction to a log full of failed logins is to block the addresses, and it is effort with no return.

The addresses rotate. A distributed attempt uses thousands of them, each making a handful of tries, and a blocklist is obsolete before it is finished. Meanwhile the underlying exposure is unchanged.

Rate limiting works because it does not care where attempts come from. Two-factor works because it removes the value of guessing correctly at all. Both are configuration rather than vigilance, which is the only kind of defence that survives a busy month.

The version that actually succeeds

Random guessing rarely works against a generated password. Credential stuffing does.

An attacker takes username and password pairs from an unrelated breach and tries them against thousands of WordPress sites. No guessing is involved – the password is correct somewhere, and the only question is whether it was reused here.

That is why unique passwords and two-factor sit at the top of the hardening list and why everything else on it is secondary. A reused administrator password defeats every other measure on this page.

Credential attacks are one entry route among several, and the others rarely announce themselves as loudly. What each one looks like, and what closes it, is catalogued on WordPress security threats.

Removing it, in order

  1. Confirm whether anything succeeded. Failed attempts are noise; a successful login is an incident. Check the user list for accounts nobody created and the last-login times on every administrator before doing anything else.
  2. Rate limit the login endpoint. Lock out after a small number of failures, per address and per username. This alone removes the economics of guessing.
  3. Turn on two-factor for every account that can install code. The password stops being sufficient, which ends the entire credential-guessing class regardless of how many attempts arrive.
  4. Disable XML-RPC unless something needs it. It allows many credential attempts inside one request, which bypasses ordinary login rate limits and is where the load spikes come from.
  5. Move or protect the login path. Server-level protection stops the traffic before PHP starts, which removes the load as well as the risk.
  6. Close user enumeration. Author archives and the REST users endpoint publish valid usernames, which is half of every attempt. Both are closed with configuration rather than a plugin.
  7. Rotate credentials where anything succeeded. Passwords, salts and session tokens together, so an existing session does not survive the reset.

Harden it against a repeat

  • Reused credentials from an unrelated breach are the most common way guessing succeeds
  • Removes the entire credential-guessing class outright
  • Without it an attacker gets unlimited attempts at no cost
  • It permits many credential attempts inside a single request
  • Usernames are half of every attempt and WordPress publishes them by default
  • Automated traffic stops reaching PHP at all
  • Every extra administrator is another target and another reused password
  • A campaign against one account is visible weeks before it succeeds

Tick the tasks you already run. Where you stand, what the gaps cost and which ones matter appear here.

Site already compromised?

Cleanup starts the same day. We trace the entry point rather than only removing what the scanner found, because a site that reinfects still has the backdoor.

Start recovery

$199 one-time, credited against your first month · Included free on Business

Questions people ask before calling

Is my site being targeted?

Almost certainly not personally. Automated guessing runs against every reachable WordPress install continuously, and the traffic is indiscriminate. Attempts against one specific username are the exception worth investigating.

Do I need to block the attacking addresses?

No, and it does not work. The addresses rotate constantly, so blocking them individually is endless. Rate limiting and two-factor remove the exposure regardless of where attempts come from.

Does moving wp-login.php help?

Yes, though not through obscurity alone. The real gain is that automated traffic stops reaching PHP, which removes the server load along with most of the noise in the logs.

How do I know whether an attempt succeeded?

Check the administrator list for accounts nobody created, and the last-login time on every existing account. A successful login from an unfamiliar location is an incident rather than an attack.

Will a security plugin stop this?

It handles the rate limiting well. It cannot give you unique passwords or two-factor, which are the two changes that matter most, and it runs inside PHP so the traffic still reaches the application.

When it needs handing over

wordpress malware removal service

Clean malware out of WordPress and close the route in, so the same infection does not return in a fortnight. Files, database, scheduled tasks and administrator…