The information within this post was compiled and created in preparation for my WordCamp Toronto 2012 presentation titled, “Steps to Securing WordPress”. The title doesn’t quite match the content because while researching the topic I realized (actually, re-realized) that it’s better to understand the big picture than to blindly follow some steps which could lead to a false sense of security. So, what is the big picture?
The Big Picture
WordPress is not inherently insecure. There’s a dedicated WordPress security team focused on addressing security issues (Anyone know who’s part of that team?). They’re taking it seriously these days. Thing is, WordPress is only one small part of the big picture. Let’s continue and look at the other parts.
There’s a lot of technology between you and your WordPress code and every part has it’s role in the overall security of that connection. You being one of the biggest factors of unpredictability. It always starts with you. So, don’t give your password to anyone unless you like them a lot. Don’t use passwords that are easy to guess. Don’t log into your WordPress admin screens from public internet computers. Make sure your workstation doesn’t get hacked, scammed, phished, infected.
Next along our almost-speed-of-light line between you and WordPress; the network. All those bits travel across different media and through a bunch of devices before reaching their destination. You don’t have control over most of those intermediary points of routing so the best you can do is encrypt all your sensitive and private information.
Then there’s all the protocols involved in delivering those bits from one point to the next and turning them into something we can understand like a web page about, well, for the sake of focus, a web page about WordPress security. Again, not a lot you can do about how secure those protocols are and historically speaking, they’ve had their issues and I’m sure more will be discovered.
The point I’m trying to make is there are factors that you have no control over so your goal is to do the best you can with the information available. You may follow every step in this guide yet still get hacked. Your best defense, after applying some of the recommendations below, is vigilance.
…back to the Big Picture…
Now we’re getting pretty close to the core players involved with making WordPress do its thing. It has a familiar ring that rhymes with shlamp. Yes, the famous LAMP stack comprising of our dearly beloved GNU/Linux operating system, the Apache web server, the MySQL database and the PHP scripting language. A couple of these players can be mixed and matched with some others but the general idea is that we’ve reached the machine(s) that runs an operating system, a web server, MySQL and PHP. The relative fortitude of these components all depends on what kind of web hosting you’re using, but that’s another presentation altogether.
Ok now, enough with the theory, on to the steps. We’ve finally reached WordPress and now we’re in control.
When to upgrade
The oft heard mantra is “update update update” and I generally agree with that stance. There are times when I won’t jump immediately to click that update button. When a major version is released I’ll sit back and consider a few things first. If there’s been a maintenance release for the previous version then I will install that one because that would almost surely mean there was a security issue discovered and fixed. Otherwise I’ll wait till the early adopter types (ie people who pre-ordered the iphone5, those with twitter accounts that match their name, etc) have upgraded and found any bugs the new major release might have (ahem). Once the first maintenance version is released, that’s when I’ll upgrade. Best practice with upgrading is to be informed. Read the WordPress.org blog to get an overview of the changes.
Here’s what the different versions look like:
- Major release: 3.4
- Maintenance and/or security release: 3.4.1
Monitor http://codex.wordpress.org/WordPress_Versions to know for sure when a new version is released. Use a service like http://www.changedetection.com because sometimes a maintenance release of a previous major version will be published without any notifications elsewhere. Of course, if you are regularly visiting your WordPress admin screens then you will see notifications appearing near the top reminding you that things need to be updated. There’s also a plugin to send you notifications via email when plugins, themes and core need to be updated called WP Updates Notifier.
Before upgrading always take a backup of your database and files. If automatic updates work without any additional configuration then your hosting provider has configured your WordPress files and directories to be owned by the same user the web server (or php.cgi, php-fpm, etc) is running as. This is very convenient for upgrading plugins, themes and WordPress itself but it also isn’t the most secure setup. There are a few ways to have your files owned by a user other than the one used to run the web server process. You will be required to choose one of the following upgrade methods if you decide to modify your WordPress files and directories:
Automatic via SSH
- You will need SSH access to your hosting environment.
- You will need to add a module to your PHP process.
- You will need to make changes to your wp-config.php.
Basic steps are:
- Create SSH key pair with no password using ssh-keygen
- add public key to authorized_keys file
- Add to wp-config.php
- Install libssh2-php or something similar to enable SSH support in PHP
- Recursively change ownership of everything under the wordpress directory
- The user account can have a restricted shell like rbash or even /bin/false
More detailed instructions: http://wpforce.com/wordpress-tutorial-ssh-install-upgrade/
Directory and File Permissions and Ownership
It all depends on your hosting environment. The general rule is to set all directory permissions to 755 and all file permissions to 644. If you are on a VPS you can use the Automatic SSH update method so the files and directories don’t need to be owned by the user the web server runs as. Otherwise you can change the permissions recursively to enable and disable write access.
You can read more about permissions here.
Disable Plugin and Theme Editor
If you follow the recommendation to use SSH updating and change the ownership of files and directories to not be the same as the user the web server runs as then you are taking care of this issue at the same time. When the web server has write access to your files then this feature is automatically available and rather risky. If one of your authors’ accounts were to get compromised the attacker has full access to modifying theme and plugin files. The other option, if changing ownership isn’t available to you is to add the following to your wp-config.php:
define( 'DISALLOW_FILE_EDIT', true );
Read more about this option and the possibility of it interfering with plugin functionality here.
Make sure the Authentication Unique Keys and Salts section of wp-config.php has been setup using https://api.wordpress.org/secret-key/1.1/salt/
WordPress admin Account
By default WordPress will create the first administrator account with a username of admin. Since this is common knowledge these days this account is an easy target for brute force login attacks since the username is already known, that’s one less token that needs to be guessed reducing the overall complexity required to break into the account. Best practice is to avoid creating the account in the first place or replace it with an administrator account having a username not called admin.
When creating a new WordPress site choose something other than admin for the initial administrator account. If you have a WordPress website containing an administrator account with the username admin then you can follow these steps to replace it:
- Log in as admin
- Create a new account using ‘Add New’ link
- Choose a strong password
- Set the role to Administrator
- Create the account by clicking the ‘Add New User’ button
- Log out of the admin account
- Log in as the administrator account created above
- Delete the admin account
- Make sure to attribute all posts and links to the new administrator account using the option on the delete user page
Hiding the administrators’ account names
Edit the user_nicename field in the users table so that it doesn’t match the username. That way malicious bots can’t scrape your login username credential from your blog posts and author archive. You can change it to something like Firstname_Lastname. Don’t use spaces if you use more than one word for the user_nicename field. The easiest way is to use phpmyadmin but if that’s not available then you could use the Edit Author Slug plugin. This plugin would be a candidate to install, use, then immediately remove. No need to have any plugins installed (even deactivated) if they’re not actively required.
Only install plugins that you need. Delete all plugins you are not using. Choose reputable plugins and only ones that are part of the official WordPress repository at http://wordpress.org/extend/plugins/. Here’s a quick checklist:
- check that the “Last Updated” date is reasonable
- check the rating and vote count
- check the author and plugin count
- check the support forum for recent and quick replies
- check the number of downloads
- check the compatibility (Requires)
If you choose not to use the default theme that comes with WordPress (twentyeleven, twentytwelve) then be sure to do a bit of research on the theme developer before installing. There are many high quality themes being built both for free and purchase but there are many many more that are poorly coded (again both free and for purchase) which at best will make your site slow and at worst open your site up to compromise. Here are a few I recommend:
Ensure that your php.ini has error_log defined. Again in php.ini, disable displaying errors to the browser using display_error. Alternatively you can set these in your wp-config.php
Having a working error log to consult can save a lot of time while debugging a problem. Even the dreaded white screen of death will usually produce some printed error that will point you in the right direction to fixing the issue. Without the error log, you’re in the dark.
Web Server Logs
Web server logs are invaluable sources of information when trying to determine if you are currently under attack or if you think you might have been attacked in the past. If you have shell access to your hosting environment you can watch your logs in real time. Any attempt to determine the methods with which an intrusion was accomplished requires careful inspection of the web server access and error logs. Finding SQL commands such as SELECT, INSERT, DELETE in a GET request is a clear sign of attempted SQL injections. It’s not a clear sign that the attack was successful though.
External Monitoring Sources
Signup for Google Webmaster Tools – you will be notified if your site has been delisted because hackers have inserted spam links or other malware all over your site.
Additions to .htaccess
Many more ideas and protective measure can be taken. There is an exhaustive list of them here. Some of the more interesting and useful ones are providing some protection against cross site scripting and SQL injection attacks.
Database Table Prefix
Choose a unique table prefix instead of the default ‘wp_’ since that’s what the malicious bots and hackers will be using in their attempt to compromise the security of your database. Use a random character generating tool to create a prefix of at least 8 characters. You can set this during the initial installation.
Use SSL to Access wp-admin
This isn’t always an option provided by hosting companies but if you have SSL enabled then simply adding the following line to your wp-config.php will redirect all logins and wp-admin pages to HTTPS.
Force Mutual Authentication over SSL
Mutual authentication in the context of web security is when both the client and server are asked to authenticate themselves. This adds a layer of protection to your environment that’s very difficult to circumvent if implemented correctly. The way it works is that when you connect to your WordPress administration screens the server will, immediately after the SSL negotiation, ask you (your browser) for your SSL certificate. If you have one and it’s signed by the proper certificate authority (CA) then you gain access to the screen. If you (your browser) provide no certificate or your certificate isn’t signed by the appropriate CA then your are denied access. Using a tool such as openssl is all you need to create all the certificates required to make this work. You’ll also need to modify your web server configuration. Here are some instructions to build this protection into your environment:
Hide Your WordPress Version (optional)
Hide your WordPress version from the world. Here’s one method:
You can use this simple utility to check your site:
Recommended Security Plugins
More Security Related Best Practices
Take backups often. At least daily. Hourly snapshots even better.
Only install plugins and themes you need. Delete the ones you’re not using.
Keep your computer malware-free. Use antispam and antivirus tools and services.
Use an application layer firewall if available or choose managed hosting that includes this service.
Locking Down WordPress
WordPress Security the Sucuri Way
Administration Over SSL
My Site Was Hacked – Steps to take if your site has been hacked.
Stop Badware – Get help from a community of people helping to stop malware.
General information about file and directory permissions.
WordPress Exploit Scanner – Scan your WordPress install for signs of hackage.
Login Security Solution – Thwart unauthorized login attempts.
BackWPup – Backup plugin supporting offsite storage on Dropbox, Amazon, Google, etc.