Skip to content

How to protect WordPress from brute force attacks

A brute force attack is a program trying one password after another on your login page or on xmlrpc.php. Strong unique passwords and two-factor login make the guessing fail. Login limits, a firewall and server rules cut down how much of it reaches the site.

By
WP Ministry
Published

In short

  • The guessing is automated and aimed at every site with a login. Failed attempts in a log are not a break-in.
  • A long password used nowhere else, plus two-factor login, is what makes the guessing fail.
  • Limiting attempts slows an attack. Stopping it at a firewall or at the host also spares the server the work.
  • WordPress has two places that take a password, wp-login.php and xmlrpc.php. Protect both.
  • Hiding the login page reduces noise. It is not a defense on its own.

A brute force attack is the plainest way into a site: a program tries one username and password after another until a pair works. The attempts are automated and often come from many addresses at once. They are aimed at any site with a login, not at yours in particular.

WordPress has two places that take a username and a password. One is the login page, wp-login.php. The other is xmlrpc.php, an older interface that apps use to reach the site, and WordPress's own guidance names it as a frequent target.

How to tell it is happening

  • The access log. Your host's control panel usually offers it. An attack shows as many POST requests to /wp-login.php or /xmlrpc.php, close together.
  • A security plugin's log. If you run one, it lists failed logins and the addresses it has locked out.
  • A site that slows down in bursts. Every attempt is a request the server has to answer, and enough of them can overwhelm a site even when every guess fails.

A failed attempt is not a break-in. A sign that one got through is an administrator account you did not create, or a change nobody on your side made. If you see that, go to how to remove malware from a hacked WordPress site. When a site is already infected, our WordPress security service starts with a one-time malware removal, and a care plan then keeps the site updated, scanned and backed up.

The measures below are in order of what they are worth. The first two make the guessing fail. The rest reduce how much of it reaches the site.

Use a strong, unique password on every account

Guessing works on passwords that are short, built from words or names, or used somewhere else. A long random one is out of its reach.

  • Let a password manager make and keep the password. Use it for this site only.
  • Do this for every account that can log in, not only your own. One weak account is enough.
  • Do not use admin as a username. Create a new administrator under another name and log in with it. Then delete the old account; WordPress asks what to do with its posts, and you can hand them to the new one.

Add two-factor login

With two-factor login, the password is followed by a second step: a code from an app on your phone, or a hardware key. A correct guess at the password then opens nothing.

WordPress does not include two-factor login. A plugin adds it. Turn it on for every administrator, and for anyone else who can publish or change the site. How to set up two-factor authentication in WordPress has the steps.

Limit login attempts

A security plugin can lock out an address after a number of failed logins. WordPress security plugins compared covers the plugins that do it. A challenge on the login form, such as a CAPTCHA, also slows bots.

Know what a limit does not do:

  • An attack spread over many addresses stays under a limit that counts per address. The limit slows it and does not end it.
  • The plugin runs inside WordPress, so each attempt still costs the server work before it is turned away.
  • It can lock you out after your own mistyped passwords. If that happens, how to fix the 403 Forbidden error has the steps for a security plugin that has blocked you.

Stop it before it reaches WordPress

A firewall at the host, or a service that sits in front of the site, can limit requests to /wp-login.php and /xmlrpc.php and challenge the ones that look automated. The traffic is turned away before your server does any work. WordPress's guidance prefers this to a plugin where you have the choice.

Ask your host two things: whether they limit requests to those two files, and whether they run a web application firewall. If the answer is no, WordPress firewall plugins compared covers the services and plugins that do it.

Restrict the two files at the server

If you can edit .htaccess on Apache, or the site's configuration on nginx, the web server can refuse requests itself. Keep a copy of the file before you change it, and try the rules on a staging copy of the site first if you have one.

Allow wp-login.php only from your own address

Use this only if everyone who logs in does so from an address that does not change, such as an office. Do not use it on a site where visitors have accounts, such as a store or a membership site. Logging in, logging out and password resets can pass through this file, and those visitors would be refused.

Replace 203.0.113.15 with your own IP address. Searching the web for "what is my IP" shows it.

.htaccess

<Files "wp-login.php">
    Require ip 203.0.113.15
</Files>
Apache reads this from .htaccess in the site's main folder. On nginx it goes inside the site's server block.

For more than one address, list them on the same line on Apache, separated by spaces. On nginx, add one allow line for each. If WordPress is installed in a subfolder, the nginx path includes it, as in /blog/wp-login.php.

Two things can go wrong.

  • On nginx, the block needs the PHP lines. nginx stops looking once it finds this exact match, so the block has to hand the file to PHP itself. Without those lines, the login page does not run for you either.
  • Behind a proxy, the address is the proxy's. If a firewall service or CDN sits in front of the site, the server sees its address and not yours, and the rule will not do what you mean. Set the restriction at that service.

Close xmlrpc.php if nothing uses it

Jetpack and the WordPress mobile apps use XML-RPC. If you use neither, and no other tool that publishes to the site from outside, refuse the file to everyone.

.htaccess

<Files "xmlrpc.php">
    Require all denied
</Files>
These go in the same places as the rule for wp-login.php.

To check, open https://example.com/xmlrpc.php in a browser, with your own domain. Before the rule, WordPress answers "XML-RPC server accepts POST requests only." After it, the server refuses the request.

If you do use XML-RPC, leave the file open and ask your host or firewall service to limit requests to it.

If a rule goes wrong

Remove the lines you added, through your host's file manager or over SFTP, and reload the page. If the rule refuses you and you are not sure which one it is, how to fix the 403 Forbidden error shows how to find it. If every page shows an error after you saved .htaccess, the server could not read a line in it: see how to fix the 500 internal server error.

What not to rely on

  • Moving the login page to another address. It cuts down the automated requests aimed at /wp-login.php. It does not make a password harder to guess, and xmlrpc.php stays where it is. WordPress's guidance treats it as a way to reduce noise, never as the only defense.
  • Blocking addresses by hand. The attempts come from many addresses and the list changes. Temporary blocks set automatically by a plugin, the host or a firewall keep up; a list you maintain does not.
  • Blocking whole countries for good. WordPress's guidance advises against it: it refuses real visitors and is hard to keep right.

WordPress security: what to do, in order of what matters most puts login protection in its place beside updates, backups and the rest.

Common questions

Can a brute force attack slow my site down?

Yes. The server answers every attempt, and WordPress checks each password it is sent. A heavy run of attempts can make pages slow for real visitors. That is the reason to stop the traffic at the host or a firewall when you can.

Can I switch off XML-RPC without touching the server?

Partly. WordPress has a filter, xmlrpc_enabled, and adding add_filter( 'xmlrpc_enabled', '__return_false' ); in a small plugin of your own switches off the XML-RPC methods that need a login. Those are the ones password guessing uses. Pingbacks are not affected, and each request still reaches WordPress before it is refused.

Should I put a second password on the wp-admin folder?

A server password in front of the login adds a layer, and WordPress's hardening guide describes it. The same guide warns that protecting the whole wp-admin folder can break features that depend on wp-admin/admin-ajax.php, which plugins and themes can call from public pages. If you want this layer, ask your host to put it on wp-login.php only.

Do passkeys help?

They can. Logging in with a passkey uses a check on your own device, such as a fingerprint or a security key, and sends no password. WordPress needs a plugin for it. While the account can still log in with a password as well, that password is still there to be guessed and has to stay strong. Register at least two devices for each administrator, so that losing one does not lock you out.

More on this subject

Not sure what is wrong?

Tell us what you see. We reply with the cause and a fixed quote, and the diagnosis is free.