by Craig

Hardening WordPress

If you ever deploy a site using WordPress then you REALLY need to ensure its had some security hardening. “Why?” I hear you ask, “No-one is going to target me!”. If you think these things then you are probably right; no-one is really interested in hacking you personally unless you have high profile. This raises the question of who a likely attacker would be then and therefore the method of attack. In my opinion, humble as it is, the likely attacker is going to be one of opportunist and the method will be automated scripting. This is done by targeting multiple websites and IP ranges and would not directed at you personally.

So with that premise in mind what can be done to harden a WordPress installation to make it more difficult for an automated hack?

Keep WordPress up to date

WordPress does automatically patch itself but you should also ensure that the plugins that are being run are also up to date as these wont be automatically updated. Checking this on a regular basis (put it in your diary!) will stop attacks with known vulnerabilities that you have yet to patch on your website.

Do you really need that plugin?

The more plugins you have the broader the attack surface is for an attacker. This is mostly because of the extra code you are adding to your website for those “must have features” could also contain bugs which an attacker can exploit. If a plugin author does not fix bugs in their software, or worse stops maintaining it, then it could contain undiscovered vulnerabilities. The less of these you have the smaller the attack surface of exploitable bugs for an attacker.

Cloudflare

I have only recently started using this but it is worth bringing up as it can be used as a free service and really help.
Very briefly Cloudflare works by passing all the traffic destined for your website through its network first before hitting your webserver. It does this by pretending to be your webserver to the outside world (you have to configure DNS for this to work).
So why is this good? Well the more people use this service the more Cloudflare “sees” what is going on across many many websites and therefore who might be acting maliciously. If an attacker is automating scripts to hit hundreds of websites at once then Cloudflare will see this and block their IP from hitting your server.
Cloudflare does the blocking on the basis of you telling them about the bits of your website that needs special attention using something called “Page rules”. I use these, within the confines of the free version, to do the following:

Protecting the WP-Login.php page; this setting lets Cloudflare know that this particular page needs to be protected!!

URL match: craig.yourintranet.co.uk/wp-login.php
Settings
Security: High

Protecting the WP-Admin area; this setting tells Cloudflare that the entire area under wp-admin needs to be protected and not cached or any clever stuff done with it :)

URL Match: craig.yourintranet.co.uk/wp-admin*
Settings
Security: High
Cache Level: Bypass
Disable Apps
Disable Performance

This next one is not about security but you get 3 free page rules with the free version so the last one is about performance. Caching your uploads folder means that your webserver wont always be asked for those big image files that you have uploaded and that Cloudflare’s servers will serve them on your behalf. This is really clever as it means a local (to the user) Cloudflare server will be providing those files rather than your server which might be on a different continent to your user!

URL Match: craig.yourintranet.co.uk/wp-content/uploads*
Browser Cache TTL: a day
Cache Level: Cache Everything
Edge Cache TTL: a month

WordPress itself!

Yes there is still more to do with our WordPress site to make it difficult for an opportunistic attacker. Initially we want to break up the structure of WordPress such that an attacker isn’t going to instantly know what the underlying code looks like. We do that in two ways:

  1. Change the table names
  2. Change the structure of the WordPress site (the URL).

In detail:

  1. Changing the table names is something you typically do during the installation of the site. When the installer asks you “Table Prefix” then put in something a bit rubbish like “wpijundsaf_” as the prefix. This will make SQL injection (writing database commands into a URL) much more difficult to execute as the table name will be unpredictable and therefore the SQL command will fail. This change won’t stop your site from working but might stop an attacker writing malicious code into your database.
  2. Changing the structure of the WordPress site is a similar method to the table prefixes. When an attacker iterates hundreds of vulnerable plugins by just looking for /wp-content/plugins/ on a webserver then perhaps we should change that!

Doing so is not that difficult and requires the re-naming of the wp-content directory to something else like wp-content-myblog and then the changing of the wp-config.php file. To change the wp-config.php you need to know the name of the directory you have changed and where it sits on your operating system and then add the following:

define ('WP\_CONTENT\_DIR', '/the/operating/system/path/to/my/website/html/wp-content-myblog');
define ('WP\_CONTENT\_URL','/wp-content-myblog');

Now bear in mind the following; ‘the/operating/system/path/to/my/website/html/wp-content-myblog’ will be different for you depending on where your files are on the server which runs your website. You need to work out where that directory is on your server then name the folder something other than wp-content and put the entire path into the config as above. You will also need to go back up to that page rule for Cloudflare we talked about earlier and change the URL match so that the path to your uploads folder is correct.

.htaccess

Onward now to .htaccess where we look at the file in the root directory of your website which deals with, among other things, security. The .htaccess file is a simple text file in a directory which the Apache webserver reads to determine if there are any actions it should take. It only reads that file it is in the same directory as the file/page being requested it or if it passed it in a lower directory on the way to get that file/page.
Within .htaccess you can setup some rules about what things are accessible, to whom and under what conditions. It’s finer grained than some of the other things we have talked about but does protect some specific thing even further.

Within the root folder of your website edit (or add) your .htaccess file and append:

# protect the htaccess file
<files .htaccess>
order allow,deny
deny from all
</files>

# protect wpconfig.php
<files wp-config.php>
order allow,deny
deny from all
</files>

# Deny access to XMLRPC
<Files xmlrpc.php>
order allow,deny
deny from all
</Files>

These first few just deny external access to the .htaccess and wpconfig.php files which should only ever be read by the webserver.

The third one involves the XMLRPC service which usually allows you to post content remotely to your blog. This service is useful if you are planning to write content remotely and then upload it through a third party application or a mobile device. If your planning to just use the website itself to write articles and content then you do not need this service. Why deny access to it? Because by it’s very nature it allows the posting of content into your website remotely and could be a security hole. If you’re not going to use it then why take the risk?

# disable directory browsing
Options All -Indexes
# Turn off the ServerSignature
ServerSignature Off

# limit file uploads to 10mb
LimitRequestBody 10240000

These settings stop people browsing the files on your webserver and getting the server to tell information about itself to the end user. This is information an attacker could use so why provide it? The limit file uploads is not a security feature as such but is going to need changing if you plan on uploading any files of a certain size. You should be aware of this value and what you have set it to.

# Protect from spam bots
RewriteEngine On
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} .wp-comments-post\\.php*
RewriteCond %{HTTP_REFERER} !.craig.yourintranet.co.uk.* \[OR\]
RewriteCond %{HTTP\_USER\_AGENT} ^$
RewriteRule (.*) ^http://%{REMOTE_ADDR}/$ \[R=301,L\]

Finally within the .htaccess file we add in this to help with the ever present problem of spam. The section here uses the mod_rewrite module within Apache which will need to be enabled beforehand (it might well be within your hosting provider). The conditions flow through asking if someone is trying to post a comment and then if they posted it from the website and if that fails it pushes them to an error page. Useful little script to, again, keep automated comment bots from plastering your site with comments/spam.

File Permissions

The files on your webserver need to be protected from arbitrary access outside of the webserver itself usually from with the operating system. Adding permissions to whom can read/write/execute a file stops other website on the same server from reading your files and protects the integrity of the file system.
Wordpress themselves recommend the following:

Directories - 755
Files - 644
wpconfig.php - 400

HTTPS

Using HTTPS/SSL on your website ensures that the traffic between you, your customer or anyone else and your website is encrypted. Each time you login to your website, to post a new article or whatever, the username and password of your login is sent over as plain text.
If you install an SSL certificate on your website and your start using HTTPS then that login traffic will be encrypted. Similarly any comments or articles you or your users post are also encrypted in transit. It’s very unlikely someone is going to be “sniffing” the traffic passing to your website to intercept your login credentials but it could happen and so why not protect yourself?
With Google ranking HTTPS sites higher than HTTP sites and the roll-out of LetsEncrypt there are starting to be less and less reasons to do so.
I am not going to go into how you might go about putting a SSL certificate on your website as it needs the involvement of the hosting provider. In my case TSOHost(link on the right) allow you to tick the “LetsEncrypt” checkbox on your website and that applies an SSL certificate almost immediately; again there are caveats about more configuration and the limitations of LetsEncrypt.
Personally I pay for my certificate and ask my hosting provider to deal with all of it; which they do so I am happy!

Security Plugins

There are plenty of these around and some of them I think are reasonable enough. Certainly ones that scan your files for virus’ seem to be worthwhile as they could find malicious, injected, code in amongst your theme or plugins. The security plugins will often give you the option to clean that file or take some action against it which should give you peace of mind if you do find something untoward. Personally I don’t use these owning to the mantra above “Do you really need that plugin” and hope that the rest of these security steps are strong enough.

Backups

If all the above doesn’t work and something tells you that you have been compromised then it’s time to restore the site from backup.
Taking regular backups of the site means downloading the site via FTP and taking a backup (dump file) of the database. Much of this can be automated and your hosting provider might provide this service as part of the hosting package. You might think it isn’t worth it but if you ever have to use it you will be very glad you did and wish you had backed up more often!!!

We done now?

Yup.
Much of the above came after I was hacked and started to look into security much more around WordPress to stop it happening again. I am hoping I have managed to hit a balance between outright paranoia and security that will stop me being the victim of a “drive-by” hacking attack and will only be vulnerable to the most ardent of hackers. But even if that happens I will have a backup of my site and ultimately this is only a tech blog right???
You may wish to pose even stronger security features on your website such as locking out access to wp-admin by another security method through plugins or edits to the WordPress site. Further security hardening is up to the site owner as there are always other solutions which others will advocate.
Here is a picture of a fence which will stop anything that is not determined.