f in x
WordPress Brute Force: How to Protect wp-login.php (Practical Guide)
> cd .. / HUB_EDITORIALE
Sistemi Operativi & Sicurezza

WordPress Brute Force: How to Protect wp-login.php (Practical Guide)

[2026-06-15] Author: Ing. Calogero Bono

If you run a WordPress site, you already know that sooner or later someone will try to break in. It's not paranoia, it's statistics. Every day we see hundreds of failed login attempts on our clients' servers. Most are bots hammering wp-login.php with usernames like "admin" and weak passwords. The result? Logs flood, the server slows down, and if they find a crack, they hijack your site.

We, at Meteora Web, have handled dozens of brute force attacks on WordPress. We've seen them come from zombie networks scattered around the world, at rates of 1000 attempts per minute. We've also had to clean compromised sites — and it's much more expensive to cure than to prevent. This guide shows you exactly how to block brute force attacks on wp-login.php with concrete measures, from .htaccess to smart plugins, including server-level configurations. No theory: only what works.

This guide is a specific deep-dive within our WordPress Security Pillar Guide. For a complete overview, start there.

Why wp-login.php is the prime target

WordPress places the login page at a fixed URL: /wp-login.php. Convenient for us, convenient for attackers. A bot knows exactly where to knock. The first attempt is always "admin" with password "password" or "123456". Sounds trivial, but it still works on an alarming number of sites.

Sponsored Protocol

A brute force attack systematically tries username and password combinations until it finds the right one. It can be:

  • Online: the bot sends HTTP requests to wp-login.php, one after another.
  • Offline: the attacker has already downloaded the hashed password database and tries to crack them locally (but this requires a prior vulnerability).

We focus on online defense — the kind you can implement right now.

The cost of an unprotected login

Each request to wp-login.php consumes CPU and memory. At 500 requests per minute, a small server can time out. But the real damage occurs when the attack succeeds: the attacker installs backdoors, steals customer data, turns your site into a malware distributor. Cleaning up costs hours of work and reputation. We've seen e-commerce sites shut down for three days because the attacker deleted product tables.

First line of defense: .htaccess and IP blocking

The .htaccess file is the fastest guard. With a few lines you can restrict access to wp-login.php only to specific IP addresses. Perfect if you're the only admin and have a static IP.

Sponsored Protocol

Caution: if you have multiple collaborators or a dynamic IP, this becomes a barrier. In that case, use it only as a fallback combined with other techniques.

Allow only your IP

<Files wp-login.php>
    Order deny,allow
    Deny from all
    Allow from 192.168.1.100
Allow from 203.0.113.0/24
</Files>

Replace the IPs with yours. You can specify multiple IPs or a whole subnet. This is the simplest method — but if your IP changes, you lock yourself out. We used this for years on a project with a fixed admin IP.

Block malicious IPs via .htaccess

If you've already identified IPs that hammer the login, you can block them individually:

<Files wp-login.php>
    Order Deny,Allow
    Deny from 192.0.2.50
    Deny from 198.51.100.0/24
    Allow from all
</Files>

This strategy is manual and does not scale. For automation, you need the plugins we cover next.

Second line: security plugins with rate limiting

WordPress security plugins offer advanced rate limiting: after a certain number of failed attempts, the IP is temporarily blocked. The most famous is Wordfence, but we prefer lighter, more targeted solutions.

Sponsored Protocol

Limit Login Attempts Reloaded

A free, lightweight plugin that does one thing well: blocks IPs after N failed attempts, with a configurable lockout period. No performance impact.

  • Install and activate.
  • Go to Settings → Limit Login Attempts.
  • Set Max retries = 3, Lockout time = 30 minutes.
  • Enable "Notify on lockout" to receive emails.

Beware: sophisticated bots use rotating proxies, so each attempt comes from a different IP. Local rate limiting is not enough — you need global pattern-based blocking.

Wordfence Security

Wordfence has a built-in firewall that recognizes brute force attack patterns and blocks IPs globally via its blacklist. It also has a CAPTCHA on wp-login.php. Configure it like this:

  • Wordfence → Firewall → Rate Limiting: enable "Immediately block IPs that exceed the login attempt threshold".
  • Choose 3 attempts in 1 minute.
  • Enable CAPTCHA protection for login.

Our opinion: Wordfence is powerful but heavy. On shared servers it can consume resources. We prefer modular solutions.

Sponsored Protocol

Third line: fail2ban at the server level

If you have SSH access to the server, fail2ban is the most robust solution. It monitors access logs and blocks IPs at the firewall level (iptables/nftables). No request even reaches PHP.

Configure fail2ban for WordPress

Fail2ban does not have a native WordPress rule. You need to create one manually. Here's our battle-tested setup on hundreds of servers:

  1. Identify where WordPress logs failed attempts. It could be in the PHP error log or a custom file. We use a plugin like WP Security Audit Log that writes to syslog.
  2. Create a fail2ban rule.
# /etc/fail2ban/jail.local
[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/php*-error.log
# or /var/log/auth.log if using syslog
maxretry = 3
bantime = 3600
findtime = 300

Then create the filter in /etc/fail2ban/filter.d/wordpress.conf:

[Definition]
failregex = ^<HOST> .* "POST /wp-login.php HTTP/.*" 200
ignoreregex =

This blocks any IP that does a POST to wp-login.php (even successful attempts — be careful). For a more precise regex that matches only failures, you must pair it with WordPress's log. Many plugins record messages like "LOGIN_FAILED" — use those.

Sponsored Protocol

Fail2ban blocks at the firewall level, so even if the attack comes from 500 different IPs, after 3 attempts each, they are banned for an hour. We have servers that receive 2000 attempts per day but fail2ban stops them on the first try.

Fourth line: hide wp-login.php

A controversial technique: change the login URL. With plugins like WPS Hide Login you can move the login page to a custom path, e.g., /my-secret-entry. wp-login.php becomes inaccessible and returns 404.

This is not an absolute defense: an attacker can still guess the new path or use XML-RPC vulnerabilities. But it raises the bar and stops dumb bots.

We use it only on highly exposed projects, and we pair it with IP whitelisting. Caution: if you change the login URL, any system that directly calls wp-login.php (e.g., third-party plugins) may break.

How to do it manually (without a plugin)

You can modify the WordPress template file, but it's discouraged because every update overwrites it. The clean way is to use a plugin or a mu-plugin. Here's a simple example:

Caution: this changes routing logic and can cause incompatibilities. We prefer using well-tested plugins like WPS Hide Login.

Fifth line: Two-Factor Authentication (2FA)

Even if the password is guessed, the second factor blocks access. WordPress has excellent 2FA plugins. We recommend Two Factor (by Oskar Hane) or Wordfence which includes it.

Make 2FA mandatory for all users with admin role. Use authenticator apps (Google Authenticator, Authy) or hardware keys (FIDO2). Brute force becomes useless because each attempt requires a temporary code as well.

We have clients who implemented 2FA and have had zero intrusions via login since then.

Other complementary measures

  • Disable XML-RPC: many brute force attacks exploit xmlrpc.php to try passwords without touching wp-login.php. Block it by adding to .htaccess: <Files xmlrpc.php> order deny,allow; deny from all</Files>
  • Change the admin username: if you still use "admin", change it. Create a new user with admin role and delete the old one.
  • Strong, unique passwords: trivial but still ignored. Use generated passwords of 16+ characters.
  • Security headers: add X-Frame-Options: DENY to prevent clickjacking that could simulate the login.

Dive deeper into these topics in our guide on Cryptography and data security.

In summary — what to do right now

  1. Check your logs. SSH into the server and look for requests to wp-login.php. If you see thousands, an attack is in progress.
  2. Implement rate limiting immediately. Use a plugin like Limit Login Attempts Reloaded or Wordfence. Block after 3 attempts.
  3. If you have server access, configure fail2ban. It's the most robust defense. We've never seen fail2ban bypassed by a traditional brute force.
  4. Enable 2FA for all admins. No excuses: it's free and easy.
  5. Periodically review passwords and disable XML-RPC if not in use.

Security is not a single action — it's a process. We, at Meteora Web, see it every day. If you need help hardening your WordPress, contact us. We're used to working even on already compromised projects — but we prefer to protect them first.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere Informatico, co-fondatore di Meteora Web. Esperto in architetture software, sicurezza informatica e sviluppo sistemi scalabili.
[ Read Full Dossier ]

> METEORA_WEB // DIGITAL AGENCY

We build the digital presence your business deserves.

Websites, social media, online advertising, e-commerce and high-performance hosting, engineered with method by computer engineers in Sciacca, for all of Italy.