WordPress gets a bad rap from people who complain that it’s not secure. In more than 40 years of working with computers I have never met an application or operating system that could not be hacked. I used to be an “old school” hacker, myself. Some decades ago I accidentally shut down a government computer center for a few hours. It happens. Now I only hack my own or customer systems when passwords are irretrievably lost, hackers have seized control over sites, fixing corrupted databases or file systems, etc.
The search engine optimization community bears some responsibility for magnifying the hacking problem. Indiscriminate use of SEO crawling tools for link research and “competitor analysis” feeds the botnet industry, for example. And some affiliate marketers are perfectly comfortable hacking sites for links, landing pages, or other nefarious purposes.
There is no one type of hacker but most of them use a small set of tools and look for a narrow range of vulnerabilities. The hacking threats you face could be coming from a government, Russian criminals, lone wolf marketers — it doesn’t matter. If you have a WordPress site they want in. They can use your blog and your hosting account for all manner of mischief and when your site is no longer useful they move on. Many of them never even know you exist because they are just running software they bought.
That includes many Web marketers “doing link research”. Your WordPress site is precious to you but not to anyone else. If you use any of these tools on other people’s sites you are as callous a bastard as the bastards trying to break into your own site. Unfortunately we are an industry without standards, and without standards everyone rationalizes things into being “okay”.
With that preamble, here is what you need to know about how to secure WordPress sites against hackers.
Web Security and Site Performance Go Hand in Hand
The first thing everyone needs to understand is that while a site is under attack its server is allocating resources to the attacker. Regardless of how smart your protocols are, if your server is paying attention to the hacker it is paying less attention to the people you want to visit your site. You only get so much RAM, CPU power, bandwidth, and TCP connections. Once your resources are all spoken for new visitors have to wait until sufficient resources become available to handle their requests.
While the majority of Web marketers who lecture the world about site performance may be overestimating the impact of site speed on search engine optimization, I’d say about 99% of us have figured out that slow sites create bad user experiences, and we all now know that bad user experiences don’t produce as many sales as we want. So you have a real financial incentive to defend your sites against hackers as efficiently as possible.
Efficient defense = allocating fewer resources to the hackers
The hacker’s world view is much larger than yours. The “hacker” is not a single person or botnet. The “hacker” is a swarm of bad guys and machines constantly probing the Internet for vulnerabilities to exploit. It doesn’t matter if you were just hacked five minutes ago. If your first hacker doesn’t secure the site against intrusion another hacker can come along and overwrite his changes. You go on vacation and your site is hacked five times an hour. It happens.
The “hacker” looks for many ways to get in. The “hacker” has a list of Web application login file names to check for. They look for other scripts and places where they can attempt various attacks. It’s not all about brute force dictionary (BFD) attacks. They’ll also try SQL injections and some of them just look for unchanged default passwords.
It Takes Only Minutes to Scan The Internet
I have seen two recent estimates of how long it takes to scan every IP address on the Internet for an open port. One estimate put the time under 10 minutes. The other estimate put the time under 3 minutes. These estimates were based on separate experiments. The only caveat to both estimates is that you would need a huge amount of computing power and bandwidth to pull this off. But it’s reasonable to assume that the average botnet (consisting of only a few thousand compromised home computers and Web servers) can easily scan the entire Internet in a day.
They don’t have to look at IP addresses. They can cook up random domain names, work off of libraries, follow links, and get their inspiration for who to hack in a multitude of ways.
The “hacker” is constantly running scans across the Web. They are looking for different things with each scan. Each scan makes notes and takes names. Your WordPress site is queued up several times a day, at least, for future probes just because some scanner found a file name with known vulnerabilities.
It’s Not Just WordPress; It’s Everything On Your Server
The “hacker” will come back later to attempt whatever it is they want to try. Some of them try many different types of attacks, which can include:
- FTP BFD attacks
- SMTP BFD attacks
- SSH or Telnet BFD attacks
- Website admin panel BFD attacks
- Comment form SQL attacks
- Comment form link drops
- Registration attacks
Those are just a few examples. There are many more. The registration attacks are favored by link spammers. They’ll create as many accounts as they can and then leave them alone for a while, maybe days, maybe weeks. I have read of sleeper accounts being activated months after they were created. The “hacker” is very patient. You have to wait your turn to be fully exploited.
If you have a blog, a forum, and an email server running on your account they are all being probed and attacked. A “probe” just determines what you have that can be attacked. The actual attack is often a brutal, ugly massive high-speed attempt to break through your security. I’ve seen as many as ten thousand attempts in one day by one IP address to break into a server. And I’ve seen attacks go on for days. Sometimes multiple attacks take place. They may or may not be coordinated by the same hacker or botnet.
It doesn’t matter. What matters is that your server is allocating resources to the “hacker”, and that’s not what you want.
How Do You Stop Hacking Attacks?
Hopefully you’re running on a modern server. The people most likely to NOT be running on modern servers are those of us who lease or co-locate dedicated servers. It’s expensive to keep them updated with the latest software, and a lot of servers are old enough that the hackers have a variety of tools to use against them. So how do you secure these sites against the hackers?
If you are using a major Web hosting company’s virtual server, shared hosting, cloud hosting, or managed plan where they take responsibility for security then you are probably in reasonably good hands as far as server-level attacks are concerned. We have worked with multiple hosting providers for years and I have yet to see any of them defend customer sites against application-level attacks.
There is really no way a hosting company can defend at the application level. After all, the user typically modifies the application with modules and plugins and personalized configurations. We don’t yet have security systems smart enough to keep all that stuff safe from hackers. So it’s on you to stop the “hacker” when he comes after your application vulnerabilities, even if they don’t exist.
Just because you have the latest available version of all your applications doesn’t mean your site is safe. It can still be hacked. Your software developers just haven’t figured out where the next hacks will come from.
What you have to do, to stop application level hacking attacks, is outsmart the hackers. That begins by learning what they are looking for. In general we ignore probes that look for software we are not running. They’ll get error 404s and while those errors do briefly tie up server resources the scanning software moves on quickly. I have rarely, rarely ever been in a position to stop a scanner while it was hitting a Website. If your security software doesn’t do the job, you won’t either.
So how do you outsmart the hackers? Renaming the scripts they are looking for is the first choice of anyone who understands the problem. As long as the hackers don’t know what to attack all they can do is probe your site for “known” scripts. If you don’t have any, that is as far as they get.
You cannot always rename the scripts. Maybe there are modules and plugins for all the major forum and blog applications that allow admins to rename login pages and other vulnerable scripts, but most people don’t even know they exist. Or they don’t know how to find them. Finding good plugins on WordPress.Org, for example, is a very hit-and-miss thing. Even when you use Bing or Google to search the site, if you don’t know what tags or descriptive phrases the developers used you probably won’t find what you are looking for. Worse, WordPress.Org recently redesigned its plugin pages, removing a lot of helpful text.
To be honest, I probably find about half the plugins I test by reading developer and security blogs. Most of them are inefficient or too complicated. Sometimes I come across a good recommendation. I would guess that we found about half the plugins we currently use by reading blogs that discuss various problems.
You should disable comments wherever and whenever feasible. I have seen comments closed off everywhere, usually after a short time frame, even in Web forums. The thinking is that few people are interested in resurrecting five-year-old discussions. Ironically, that is often the only content that the search engines surface. There are certain question-and-answer sites for developers that regularly remove follow up questions because the discussions are old. The admins don’t stop to think about WHY people are finding these old discussions. They just rudely tell people to stop resurrecting old threads.
If people cannot comment on your old posts and discussions, the hackers cannot play with them, either.
The Last Thing You Want to Do is Blacklist IP Addresses
I do blacklist IP addresses, but not happily. And this is an especially bad idea for an application like WordPress. Not only are you allocating resources to the hacker by allowing him to attempt to leave a comment, create an account, or login to an existing account, you’re allocating even more resources to the task of identifying troublesome IP addresses.
Many WordPress site owners install “firewall” plugins on their blogs. This is a really bad idea. If you have left all the doors and windows open then checking badges and taking names is a huge waste of time and resources. They have an endless supply of IP addresses to play with. You do NOT have an endless supply of server resources unless you want to pay for automatic scaling of your bandwidth.
Before you install that WordPress firewall plugin, look for other ways to defend the blog, such as installing the rename wp-login.php plugin. We have used this plugin for years and it is 100% compatible with today’s WordPress. It doesn’t require any support and if you search for it on WordPress.Org they’ll warn you that it’s more than 2 years old and might not be safe to use.
As far as WordPress comments go, you have built-in options that come with core WordPress. Browse your Settings => Discussions dashboard and look at the options. You can set limits on who can leave comments, how long comments are open, when comments are held for moderation, and more. You can also set these values on individual posts and pages. I don’t recommend having your blog sen you email every time someone leaves a comment. Spammers can leave hundreds of comments before they move on.
If you really want to leave all your content open to comments, you will have to install some sort of IP address firewall.
As for your admin login, if you are not renaming the script at least use a firewall that allows you to limit logins to a specific set of IP addresses. In other words, if you know where YOU will be logging in from, your firewall only needs to block every other IP address and accept yours. That’s not perfect, and you have to keep updating the whitelist if you use mobile and/or wi-fi IP address pools, but it’s better than having your blog track and block IP addresses. PHP is not suited to detecting and blocking BDF attacks in an efficient way.
Nor Do You Want to Block Directories
If you are running on Apache Web Server you can set “options -indexes” in your “.htaccess” file to prevent people from browsing directories that don’t have index pages. This prevents scanning software from browsing directories but if the hacker already knows what files your current distribution of WordPress includes, they can just try to reach the files directly.
Note to NGINX and IIS users: Yes, I know you don’t use “.htaccess” files. I know you will update your server configuration in the equivalent ways when possible or necessary.
Other Wrong Defenses I Have Seen
An inordinate number of people worry about protecting the “wp-config.php” file. I’m not sure why, as attempts to fetch this file always fail (unless PHP is not active for some reason). Your browser displays a blank page and “wget” retrieves 0 bytes.
You can move “wp-config.php” to another directory, including one above your normal hosting “root” folder. You do that by replacing it with a new “wp-config.php” file that includes this code:
/** Absolute path to the WordPress directory. */
if ( !defined(‘ABSPATH’) )
define(‘ABSPATH’, dirname(__FILE__) . ‘/’);
/** Location of your WordPress configuration. */
require_once(ABSPATH . ‘../[NEW DIRECTORY]/wp-config.php’);
But on some (older?) servers you may have to set the “base_dir = ” option in your PHP configuration to include the parent of both directories, which kind of defeats the purpose.
If you discover that your PHP was inactive and the “wp-config.php” script was fully fetchable during that time, it’s better to change the SQL database login and password, and replace the salt keys (you can make up new ones on the spot). This only takes a minute. Of course, it would be better to just completely reinstall everything from a safe backup because once your site is left wide open you won’t know what is infected (if anything).
I have never seen PHP disabled on a working WordPress site. I suppose “it happens”, but … the most likely scenario, some people say, is when the hosting dashboard software is updated and accidentally resets everything to “default”. How this would manage to disable PHP, wipe out your “.htaccess” file, and leave everything else intact is beyond me. I won’t say it can’t happen. I won’t promise it won’t happen. You can move the file if you wish, but there are other vulnerabilities you should pay closer attention to, in my opinion.
Disabling PHP file editing for users is fine, if they don’t have admin privileges. But there are other plugins that allow people to get into your server. If your non-Admin users have access to those plugins there is no point to disabling PHP file editing. If you want to do this, add the following code to your “wp-config.php” file:
Using two factor authentication is a joke in any context. Do you know how TFA works? It asks you for a device it can send a confirmation code to. If you don’t lock in a specific device then the hacker can lock his in for you. Worse, if you do lock in a device and you lose or replace it, you’re screwed. The argument “it’s better than nothing” is just false logic. Two factor authentication is relatively easy to circumvent in many cases, but when you lock it down you are married to the authenticating device. Be sure that is what you really want.
Resetting Two Factor Authentication is easy to do when you need to, but a lot of people don’t think about that when they change cell phone numbers. That’s a very common problem in other contexts. A lot of people change email addresses for a variety of reasons and then they lose access to old Web accounts, which is a huge personal security risk if you leave sensitive data in those accounts.
Host Your Site on Dedicated Servers. When I first read this suggestion I about fell out of my chair. Most people don’t know enough to manage security on a dedicated server. If your Website(s) don’t use enough CPU, bandwidth, or diskspace to demand a dedicated server this is a really stupid idea. You don’t need to take on the burden of managing server security if you are struggling to manage application security.
Enable HTTPS on your site. Yes, SEO Theory is now running on HTTPS but it’s NOT because we foolishly believe it will make the Web safer. HTTPS has been circumvented in so many ways I honestly don’t understand why Google and the browser vendors insist that everyone get on board with it. We’re only switching to HTTPS because the browser vendors are pushing everyone toward using HTTPS. Eventually all HTTP sites will be labeled as unsafe, and if some of the browser engineers had their ways they would do that last year. The vast majority of hackers who want to break into your site are NOT trying to sniff your login criteria, but the ones who do that will most likely trick you into giving them your credentials OVER HTTPS CONNECTIONS.
You should encrypt your sites only to avoid the stigma of having your sites labeled as “unsafe” by all the browsers. And pray that Microsoft doesn’t prevail in the HTTPS wars because they want everyone to use Extended Valuation certificates, which will break a lot of Websites.
What Else Can You Do to Defend WordPress?
You can disable the “xmlrpc.php” script. The “xmlrpc.php” script is used for cross-site communications, like trackbacks and pingbacks. The Jetpack plugin uses this script to connect your site to a couple of sites, but you only need to authenticate and then you can block access to the script. There are plugins that do this for you or you can edit your “.htaccess” file. Here is how you block attempts to access file in “.htaccess”:
Deny from all
You’ll find many examples of how you can use “allow [IP ADDRESS]” or “allow [HOST]” in that code. I have found that this inevitably fails on a lot of hosting services. Don’t ask me to explain why. You can end up with a lot of conflicting logic in server configurations and either something you don’t know about will prevail or you get an error 500 condition. Don’t assume you can allow exceptions to a “deny” but test for it.
It’s a good idea to defend the “.htaccess” file itself and from there defend “wp-login.php” and “xmlrpc.php”.
Rename the admin account. This is an old but popular idea. If you’re renaming the login script this is kind of redundant but it’s a prudent measure nonetheless. If you are just installing WordPress you have the option to specify a different admin username. Otherwise you’ll either have to edit the SQL table or use a plugin.
Caveat: Don’t ever POST anything from the admin account. If you rename “admin” to “fred” then all your posts will be grouped under “/author/fred/” instead of “/author/admin”, which defeats the purpose. Trust me, the “hacker” knows to look for author pages. You can disable author pages altogether by redirecting them to your home page. Don’t just use “noindex” on these archives. That defends nothing. It’s more like a “come hack me” sign.
If you rename the admin account then create an account with editor privileges that you use for posting. Try not to login as “admin” unless you absolutely must.
Use really long passwords. Longer passwords are much harder for even botnets to guess. DO NOT USE THE PASSWORD GENERATOR. You want passwords that are easy to remember. Security experts are moving away from the pointless “#8a72Dahgd0!” style passwords and recommending that people use memorable phrases like “itrustthispasswordmore” (but don’t use that one).
How long should your password be? The threshold moves every couple of years as computers get smarter. The thing is, once these guys hack into a database they get tons of passwords to play with. So …
Use really long salt keys. If your database is hacked this makes it harder for the bad guys to decrypt them. You can easily get long salt keys from https://api.wordpress.org/secret-key/1.1/salt/ and it’s a good idea, when reviewing an older WordPress site, to check the salt keys. If they are short they are probably very old.
Change the “wp_” database table prefix. I’m not sure of how great an idea this is. The thinking is that the “hacker” will get into your SQL table by some means other than reading your “wp-config.php” file (and thus use blind SQL code to modify “wp_” tables). This could happen in a variety of ways, but if they somehow grab your login credentials (say, by installing malware on your personal computer and logging all your keystrokes) then they will be able to read the “wp-config.php” file. This is a weak defense but not necessarily a bad one.
Hide your WordPress version level. WordPress Core code embeds comments on every page as part of the basic template. The comments will include your version number. Many plugins (including popular SEO plugins) also embed comments with their own version numbers. Some people feel that leaving these version numbers embedded in your source code helps hackers. Whether hackers really look for the version numbers isn’t important. If you’re going to do this be very thorough.
Some WordPress security plugins will hide the version numbers but you could also use real time find and replace plugins to hide the comments or munge them.
Browse your user accounts. Make sure you know who your admins are and that their email addresses are set correctly. You may only catch the bad guys after they have created a back door.
Browse your Web directories. There are thousands of files in a WordPress installation and you cannot possibly recognize them all. But you can sort them by modification dates and see if they line up with “clean” WordPress and plugins code.
Don’t just delete suspect files; redirect them. When a hacker installs a file on your server it is probably best to wipe the server clean and reinstall everything, but that is not going to happen 99% of the time. I once had a problem on 2 hosting accounts with the same Web host. They were hacked and after I removed the hackers’ files they mysteriously came back. Even wiping the entire accounts clean and reinstalling everything from scratch failed to fix the problem. The hosting company kept complaining that I was ignoring their warnings about the hacks and threatening to remove the accounts. They didn’t believe me when I suggested the hacker was coming in from somewhere else on the server.
I finally just added redirects for the hacker’s files to “.htaccess” and after that everyone but the hacker was happy. I only found a permanent cure by moving those sites to a new Web hosting company.
Block Rogue Crawlers, including SEO Tools
You don’t owe it to anyone to allow them to crawl your site. You have three levels of defense against many crawlers:
- Use your “robots.txt” file
- Block user-agents in your “.htaccess” and firewall
- Block aggressive IP addresses
Some SEO tools honor “robots” directives, but this may be conditional upon what user-agent they are set to use. It doesn’t matter. Don’t trust any of them to crawl your site. They tie up TCP connections and use CPU time and bandwidth. Since the people using these tools don’t compensate you for the use of your resources (and rest assured, they are trying to monetize your data in some way) you don’t have to let them walk all over your server.
If you control the server you can block them at the firewall. The native “iptables” firewall on Linux supports powerful string processing. Unfortunately, some modern server dashboards (like CPANEL) install user interfaces for “iptables” that don’t take full advantage of the software. You may have to find ways to hack the security modules to filter HTTP requests on the basis of URLs and user-agents. I don’t like using regular expression logic, which is both unreliable and hard for people to learn how to use correctly, but you’ll probably find more examples of solutions using REGEX than other string processing methods.
Drop Packets When You Can
You cannot drop incoming packets once your server is processing “.htaccess” or executing PHP script. By this point the packets have already been accepted. Your “iptables” firewall has the ability to DROP or REJECT packets based on the tests it performs. You’ll find that a lot of people set their IP rules to REJECT bad packets, but this creates unnecessary traffic (using bandwidth and keeping the connection live just a little bit longer) and it tells the botnets that someone is receiving their traffic. They will come back and take all the REJECT notices you can deliver.
When you DROP packets the machine on the other end has to wait for a timeout. Not only does this slow down the attack, it can discourage botnets from making further attempts in the same session. More importantly, it saves your bandwidth and server resources. You’re better able to keep your legitimate visitors happy.
If you cannot DROP packets then implementing a WAIT state or DELAY, essentially a server-side timeout, is almost as good. If the botnet has to wait 30 seconds in-between attempts to login or check your server that at least keeps your server free most of the time.
Using DENY via “.htaccess” or some other method only creates more problems for you. Your server is sending 403 status code to the botnet, and that tells the botnet it is looking at a live Website and possibly a vulnerable URL.
How Botnets Get Around Your IP-based Defenses
A typical botnet probe sends two requests per IP address. The “hacker” has learned to keep probes to a minimum because many people set their IP-based defenses to block after 4 or more attempts. Most people assume 2 suspicious fetches are tolerable or don’t mean anything. These are just scouting expeditions. The botnet will probe your server from multiple IP addresses throughout the day, concentrating on “wp-login.php”, “xmlrpc.php”, and sometimes various comment and attachment pages. They’ll eventually queue your site for an attack. When the attack comes your site will be hammered with thousands of requests for the potentially vulnerable script.
You may not see the same IP address for as much as two weeks. Some IP addresses will appear several times a day in your server logs. It could be one botnet or several. It doesn’t matter. They are all looking for information, including how well your server is defended and how responsive your site application is.
Botnets constantly cycle through the machines that connect to your site. They report back to a command and control server. They are running on autopilot, following a pre-recorded set of instructions. You achieve nothing when you block their IP addresses. You can win a temporary reprieve at most.
SEO crawlers often work the same way. The worst tools connect to various proxies and use them to fetch your content, tying up server resources, using bandwidth, and adding junk data to your server log files. When you block the proxies the SEO tool users laugh at you, ask their proxy hosts for new IP addresses, and come right back at you.
First of all, sorry for the length of this article. I thought I would be able to do it in under 2,000 words. But these suggestions just barely touch on the topic of Website security. Over the years we have covered Website security in the SEO Theory Premium Newsletter in many articles.
You cannot protect everything from hackers. Sooner or later they’ll find a way in. You’re lucky to be part of a large crowd. It’s that “school of fish” factor that protects you more than anything else. Other sites are getting hacked every minute. The hackers have a huge pool of vulnerable sites to play with. You should indeed take measures to secure your site, but don’t assume it’s impregnable.
Follow SEO Theory
Do you want more than just reposts of the week's SEO discussions and news?
Get the LARGEST weekly SEO newsletter now ...