How to Secure Your WordPress Blog by Christopher Heng Although, in the past, I have read of WordPress blogs being compromised and made to deliver malware, in these last few months, I have actually personally encountered a number of hacked blogs myself. Nobody can guarantee that your WordPress installation is 100% secure. However, there are ways to improve the security so that it is slightly less vulnerable than it otherwise might be. This article discusses some measures an ordinary blogger can take to protect his/her WordPress blog. Why a Blog Is Vulnerable to Hacking and Other Exploits All websites on the Internet are vulnerable to hacking and other exploits. There are no exceptions. The reason is simple: unlike your own personal computer, which only connects to the Internet sporadically (such as when you turn it on to surf), websites are hosted on computers that are permanently connected (or so one would hope) to the Internet, exposed to anyone who wants to access it, be they customers or hackers. Sites that run blog scripts, content management system (CMS) software or online forums, have an additional area of vulnerability to contend with. The software (blog, CMS or forum script) is actually online, along with your content. If there are any security holes in the software, they can be exploited by a person who connects to the site. And the probability that there are holes is very high, since such programs are very large and complex. As complexity increases, so does the likelihood that there are bugs that can be exploited. In addition, WordPress (at least up to version 4.9.1, which is the current version at the time I write this paragraph) is coded in such a way that also makes it more attractive to attackers. WordPress does not randomize the names of the directories it uses, so the URLs (ie, web addresses) to all its potentially vulnerable bits are fixed. As such, if hackers know of an exploitable bug in a particular script, they don't have to do any work at all to find it on your site. For example, the WordPress admin scripts are in http://www.example.com/wp-admin/ on every site that uses WordPress (where www.example.com stands for your domain name). (Randomization, while it doesn't prevent attacks, is helpful in raising the difficulty for the attacker, and as such, mature software written with an awareness of security issues tend to do such things. For example, Windows implements something called ASLR to randomize the addresses that programs are loaded on your computer, and Firefox randomizes the name of its profile directory when it is installed. And so on.) WordPress' low security awareness even shows in its login script. Not only does it have a fixed address which everyone knows (http://www.example.com/wp-login.php), it even helpfully tells attackers specifically which part of the login they didn't enter correctly, that is, whether it is the username or the password. (Security-aware systems just tell you that the login failed and to check that the username and the password are correct. This keeps the hacker guessing whether the username or password is wrong, and forces him/her to continue to try all combinations of usernames and passwords. If you give that information away, they will know that a particular username is valid, so they can just focus on trying different passwords with that username.) In fact, even without the help of the login script, in the default installation, attackers can also figure out the name of the admin user by accessing Example Domain. The WordPress software will obligingly convert that web address to http://www.example.com/author/your-admin-user-name/, the address of that person'sauthor archives. So even if you use an admin name other than "admin", since WordPress always (at the time I write this) assigns the first user (and thus the admin user) an ID of 1, hackers can focus their brute force attacks with that admin user name. And so on. In a sense, WordPress is in the position Windows was many years ago, with a strong focus on features and user-friendliness (which is why it's so popular) and a weaker (though improving all the time) emphasis on security. At present, the program still depends on knowledgeable users to secure their blog. Symptoms of a Hacked WordPress Blog If your blog has never been hacked before, you may wonder what the consequences are. In the past, hacked blogs have exhibited one or more of the following symptoms: The blog may be defaced. The hackers install hidden links on the blog that point to sites they own. Since Google ranks sites according to the number of links pointing to them (among other things), the intention is to make their site appear more important to Google. The hackers may insert some sort of malware that will install on the computers of the blog's unsuspecting visitors. Or they may install software that attack other sites. As a result of the above things happening, Google may remove the blog from their search engine results. Traffic to the blog will therefore plummet. Hence, it's not just a matter of defacement if your site is compromised. There are serious side effects that will cost the blogger considerable effort just to clean up and recover. Some Measures to Improve the Security of Your WordPress Blog Here are some things that I have done with my WordPress blogs to (hopefully) improve its security. They do not guarantee that your blog will never be hacked. As I said above, no one can give you that kind of assurance. But at least they will make things more difficult for attackers. Note that the code given below is only meant for a normal, personal WordPress blog, and not a Multisite installation (where you install WordPress to be used by a network of WordPress sites). If you have installed WordPress yourself, and don't know whether it's a Multisite installation or not, it probably isn't. Your blog also has to be hosted on an Apache web server for some of the following tricks (the ones involving .htaccess) to work. In practice, this probably means that your blog is on a machine (on your web host) that runs Linux, FreeBSD or some other Unix-type system, and not Windows. If it is hosted on a Windows machine, it probably uses a different web server, and you will have to find the equivalent method to enable those facilities yourself. In addition, most of the things listed below will only work if you have installed WordPress on a normal web hosting account. If you are using a specialized blog host, you probably won't be able to use the .htaccess methods to protect your blog. Keep Your WordPress Software, Themes and Plugins Updated to the Latest Version Ultimately, the best security precaution is to only use software that have no security holes. Since perfect software is not possible (we're all fallible after all, even the WordPress developers), the next best thing is to quickly update WordPress and all its themes and plugins every time a new version is released. New versions often fix holes found in earlier ones. The good news is that WordPress automatically updates itself if there is a new minor version. However, it will not automatically update to the next major one. For example, if you have WordPress 4.9.1, it will automatically update to 4.9.2 when it is released, as well as 4.9.3, and so on. However, it will not update to 4.10 or 4.11 or 5.0 or the like. Major versions may contain things that break your existing plugins and themes, or perhaps even the way you do things, and so the software requires you to initiate the update manually. That said, updating is nowadays much easier than it was in the past. You can even install an update to the next major version from within your WordPress dashboard, and it will (mostly) do everything for you. Note that if you have installed plugins and themes, you will also have to keep them up-to-date. WordPress does not automatically update these. You will have to do it yourself. A vulnerability in a plugin or theme has the same reach as a vulnerability in WordPress. Back Up Your WordPress Blog Regularly Although backing up your blog is technically not a security measure, in the end, it is one of the most important things you can do if you value your blog's content. I have written at length on this, in The Crucial Task Often Forgotten by New Webmasters (Until It's Too Late). Please read it. Use Strong Passwords I know everyone says this, but they do so with good reason. If your blog is attacked using brute force attacks, and it surely will, a weak password will easily be broken. Remember that computers are extremely fast, faster than any human, so hacking software can try out zillions of possible passwords within a very short time. Use a very long password with a variety of characters as input (not just small and capital letters of the alphabet, but numbers and other symbols like punctuation marks, brackets, etc). I'm sure you know the drill. And the password setting facility in WordPress will also help you by saying whether your password is strong or weak, though it tends to accept passwords that are still too short for my liking. Password Protect /wp-admin/ and /wp-login.php Since the /wp-admin/ directory contains a lot of scripts that can damage your blog if successfully exploited, it may be a good idea to add another layer of protection by password protecting it. Note that this doesn't help the other files located in the /wp-content/ and /wp-includes/ directory or even the main WordPress blog directory, but at least if there is a hole in a file in /wp-admin/, there is another layer of security that the attacker has to overcome to exploit it. In the same vein, it's also possible to additional password protection to the /wp-login.php file. That is, before the attacker can even use the WordPress login prompt as a means to guess your password by brute force (ie, repeatedly trying different username/password combinations till they succeed), he/she has to deal with another password screen. And this password screen is one that is less informative to attackers. The procedure for password protecting a directory can be found in my article How to Password Protect a Directory on Your Website. I recommend that you use a different username and password from your WordPress login. With a different username, even if an attacker knows your WordPress login name (which, as mentioned above, is easily found out), they will still have to work out both components of your login (ie, both the name and password) for the server side password prompt. Place the .htaccess file in the/wp-admin/ directory, although your .htpasswd file should preferably be placed elsewhere. If you use your web host's control panel to password protect the directory, the placement of files will be done for you. Then, after doing the above, if you also want to password protect /wp-login.php, you should add the following lines to the .htaccess file in your main blog directory (yes, the main blog directory, where the wp-login.php script resides). <Files "wp-login.php"> AuthName "Members Area" AuthType Basic AuthUserFile /path/to/your/directory/.htpasswd require valid-user </Files> Note you cannot just create a new .htaccess with these lines. WordPress creates a .htaccess file after installation (or alters it if one already exists), so you should download the one it created (or altered), and add the above lines to it. Important: remember to change the AuthUserFile line so that it says the same thing as the one you created earlier for the /wp-admin/ directory. If your .htaccess file already has a section enclosed by "# BEGIN WordPress" and "# END WordPress" add the above lines before that section. Do not place them inside that section, since lines enclosed between the BEGIN and END lines are auto-managed by the WordPress software. It may choke on your additions, delete them, or even mangle them so that your blog is no longer accessible. In addition, make sure you use a plain text editor like Notepad (on Windows) or TextEdit (on Mac). Do NOT use Microsoft Word, Office, Wordpad, Write, LibreOffice, OpenOffice or any other word processor. When done, upload the file to the same directory you got it from (ie, the main directory of your blog folder). As a consequence of the above, every time you log into your blog, you will have to log in twice, once with the user name and password you set here, and once with the WordPress username and password. While this is no guarantee that your blog won't be hacked, at least there's another hurdle that the attackers have to overcome. If your blog is accessible via both HTTP and HTTPS, always log in with the HTTPS form of your web address. Otherwise, your username and password will be transmitted in the clear through your WiFi or broadband provider and across all the machines along the route from your computer to your website's computer. If you don't have HTTPS, consider moving your site to SSL. In fact, make it a priority. If you use a theme or plugin that uses the /wp-admin/admin-ajax.php file, you will need to add the following to the .htaccess file in the /wp-admin/ directory. <Files "admin-ajax.php"> Order allow,deny Allow from all Satisfy any </Files> This allows /wp-admin/admin-ajax.php to be accessed without any password prompt appearing. Otherwise even your normal visitors will be confronted by the web server's password prompt. XML RPC Even if you put the /wp-login.php script behind a server password screen, attackers can still log in using another facility provided by WordPress called XML RPC, delivered via the /xmlrpc.php script in your blog directory. This facility even provides a special interface that lets attackers be more efficient, allowing them to try hundreds of passwords in one go with every attempt. If you don't use any plugins that depend on /xmlrpc.php (such as the JetPack plugin), and you don't use the WordPress mobile app (which also uses XML RPC), you can actually disable it in your .htaccess file. This will also effectively disable trackbacks and pingbacks, which is, in my opinion, no loss, since it's the source of lots of spam. <Files "xmlrpc.php"> order allow,deny deny from all </Files> As before, add it to the .htaccess file in your blog's main directory, making sure to put it outside the WordPress BEGIN and END block of lines. (I usually put such lines before the WordPress section.) After adding them, test your blog again. If something fails, it may mean that you're using a plugin that depends on that file. In such a case, remove those lines and your plugin should work again. Refuse direct access to the "include" files There are a whole bunch of files in various WordPress directories that are not meant to be directly accessed by your visitors. These files are parts of the main WordPress program that are loaded when they are needed. They are sometimes referred to as "include" files. Since they are never supposed to be directly run by your visitors, you can safely block direct access to these files. I use the following code, which I think I got from somewhere in the WordPress documentation, to do the job. <Files "wp-config.php"> order allow,deny deny from all </Files> RewriteEngine On RewriteRule ^wp-admin/includes/ - [F,L] RewriteRule !^wp-includes/ - [S=3] RewriteRule ^wp-includes/[^/]+\.php$ - [F,L] RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L] RewriteRule ^wp-includes/theme-compat/ - [F,L] Insert them into the .htaccess file in your main blog directory. As always, make sure they go outside part of the file managed by the WordPress software, that is, outside the block enclosed by the BEGIN and END lines. That said, the "include" files are supposed to be written in such a way so that even if your visitors try to access them directly, they will not be able to do anything useful with it. However, the .htaccess rules are still a good idea in case there is a bug somewhere (either now or in future versions) that can be exploited. /wp-content/uploads/ The /wp-content/uploads/ directory and its descendants (ie, sub-directories) contain your image and video uploads. Since scripts (programs) are not placed in that folder at all, you can block any attempt to run scripts from that location, in case some hacker manages to get WordPress to upload a script there and tries to get it executed to compromise your system. I use the following lines in the .htaccess file placed in that directory. <FilesMatch "\.ph(p?|t|tml)$"> order allow,deny deny from all </Files> <FilesMatch "\.(cgi|rb|pl|py)$"> order allow,deny deny from all </Files> The first batch of instructions block scripts with file extensions typically used for PHP scripts (ie, ".php", ".php3", ".php4", ".php5", ".pht" and ".phtml") and the second block those typically used for Perl, Ruby and Python scripts (names ending with ".cgi", ".pl", ".rb" and ".py"), in case your web server is set up to allow those to be run outside the cgi-bindirectory. Third Party Plugins Apart from the server-level measures that I mentioned above, some people also install plugins that are designed to tighten your security or to block access when they detect intrusions. There are plugins designed to block or limit the REST API, which is another programming interface that WordPress makes available to anyone accessing your blog. Plugins are also available to limit the number of failed login attempts. If someone from a particular IP address fails to successfully log in after a certain number of tries, they are locked out for a set period of time. This is especially useful if you cannot put the /wp-login.php script behind server password protection. There are numerous plugins that place a CAPTCHA on your login form. These are attempts to make sure that only human beings (and not automated hacking programs) can use the form successfully. And then there are plugins that limit what someone can do with the /xmlrpc.php facility. This is useful if you cannot block the /xmlrpc.php script because you're using the mobile app or some plugin that depends on it. Finally, there are also a few "firewall" security plugins that monitor and block attempts to hack your blog if they can detect it. Many of these are "premium" plugins, meaning that you have to pay for it. These plugins are available from WordPress' plugin repository. You will have to evaluate them yourself. Conclusion Hacked WordPress installations are becoming increasingly common on the Internet. Don't let your blog become the next victim. Copyright © 2008-2018 by Christopher Heng. All rights reserved.