1 Steps to Securing WordPress – WordCamp Montreal 2013

Hugh McGuire and Victor Granic

Prelude to the Prelude

I gave this talk at WordCamp Toronto 2012. This is an updated version of the article I wrote to accompany the talk since there are lots of technical details and resources associated with this topic. Fear not, I’m only plagiarizing myself.


The information within this post was compiled and created in preparation for my WordCamp Montreal 2013 presentation titled, “Steps to Securing WordPress”. While researching the topic I realized that it’s important to understand the big picture and to avoid blindly following some steps which could lead to a false sense of security. So, what is the big picture?

The Big Picture

You vs Evil(1)

WordPress is not inherently insecure. There’s a dedicated WordPress security team focused on addressing security issues. They take it seriously. 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 and tools available to you. 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.5
  • Maintenance and/or security release: 3.5.2

Follow @WordPress to get alerts on new version releases. Use a service such as TweetyMail to get tweets delivered to your inbox.

Some alternative to Twitter: 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


  1. You will need SSH access to your hosting environment.
  2. You will need to add a module to your PHP process.
  3. 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.phpdefine('FTP_PUBKEY', '/home/user/.ssh/id_rsa.pub');define(‘FTP_PRIKEY’, ‘/home/user/.ssh/id_rsa’);

    define(‘FTP_USER’, ‘user’);

    define('FTP_HOST', 'localhost:22');

  • 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/


Take daily backups. Store them offsite. Take more backups and put them somewhere else. Automate this process.

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.


Using long, random passwords is the single most important step in making your WordPress site secure. There’s been an ongoing attack against WordPress installation by a 100,000 node botnet. Read more about it here. If you use random passwords that are at least 16 characters long, your site probably won’t get hacked by this botnet.

Generate strong passwords for your WordPress accounts using http://lastpass.com/ or 1Password. Online random password generating utilities like random.org are helpful.

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/

Alternatively use two-factor authentication to access your admin screens. Authy and Google Authenticator are but two that I know work with WordPress. Use them if you don’t mind the extra step.

Read why long passwords with words from the dictionary are not secure over here at ars technica.

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:

  1. Log in as admin
  2. Create a new account using ‘Add New’ link
  3. Choose a strong password
  4. Set the role to Administrator
  5. Create the account by clicking the ‘Add New User’ button
  6. Log out of the admin account
  7. Log in as the administrator account created above
  8. Delete the admin account
  9. 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:

Theme Hybrid





PHP Logs

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.

Services such as VaultPress, Sucuri and Stop the Hacker are known to be good.

Additions to .htaccess

# Make sure these directives are either above the “BEGIN WordPress”
# line or below the “END WordPress” line. Also, make sure you test
# your site if you use any of the suggestions below. These rules
# are very specific to running WordPress so if you also serve some other
# static or PHP files under the directory where these rules will live
# you may find they won’t work. TEST TEST TEST.
# disable directory browsing
Options All -Indexes
# prevent direct access to wp-config.php
<files wp-config.php>
order allow,deny
deny from all
# block access to all php files under /wp-content and further
RedirectMatch 403 ^.*/wp-content/.*\.php$
# Block the include-only files.
RewriteBase /
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]
# prevent comment posting if referrer is blank
# replace yoursite.com with your actual domain name
RewriteCond %{REQUEST_URI} .wp-comments-post\.php*
RewriteCond %{HTTP_REFERER} !.*yoursite.com.* [OR]
RewriteCond %{HTTP_USER_AGENT} ^$
RewriteRule (.*) ^http://%{REMOTE_ADDR}/$ [R=301,L]
# deny access to all dot (hidden) files (eg .htaccess)
<Files ~ “^\..*”>
order allow,deny
deny from all
satisfy all
view raw
This Gist brought to you by GitHub.

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.

define('FORCE_SSL_ADMIN', true);

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:

Mutual authentication for accessing wp-admin and phpmyadmin.

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.



Hardening WordPress

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.


Random Password Generator

WordPress Detection Utility


WordCamp Montreal 2013 Book Copyright © 2013 by Hugh McGuire and Victor Granic. All Rights Reserved.


Leave a Reply

Your email address will not be published.