15 rules to secure WordPress

After the alert of WordPress 2.8.3 vulnerability, I decide to work on the security of my blog. I looked for some information on the web, to list some securization rules. I give you, in this post, the most used rules.

First step: backup

In fact, an attack on a blog is not a true disaster. In case of incident, we have just to delete all files and data, change passwords, and restart from the last backup … if we have one.

The backup is an essential point to secure a blog. If you lose some data, because of an attack, or just an error, backups are the last (or the only) resort.

We have two categories of data to backup:

  • the database,
  • the files: images, attachments, but also theme, plugins, and the blog engine itself.

You can read the post I wrote on this subject during the october 2008.

Secure WordPress

At WordPress level

There are some rules fairly widespread, but more or less easy to use, depending on you want to apply them during a blog installation, or on a already running blog.

  1. Keep WordPress up to date: The vulnerabilities of the old versions are well known, and can be easily used. Keeping your blog engine up to date, avoid you to suffer any attacks on these known vulnerability,
  2. Keep your plugin up to date: This point is debatable, because we don’t know if the new version is more secure than the previous. But if you get a security alert on a plugin, don’t hesitate to update it,
  3. Use secret keys: The file wp-config.php contains four secret keys, that are empty by default. You can fill them very easily, with a WordPress service . You just have to copy/paste the keys given by the service, in the file wp-config.php. For example:
    define('AUTH_KEY',        '&E4_G @;`rOToF~%cLUlOrcUzp>MIXX-Opg~-#),p,Z=q!%Jx%Yn[lvUD:t`1H~s');
    define('SECURE_AUTH_KEY', 'Vh*|99*eBYtd7$2(QFMm3{[c@KXfVpV.Nz_V)9{YMnyRi=M)5Zva/|z/iqs|v7|-');
    define('LOGGED_IN_KEY',   'p#TGC@adpPQ{ ~$-;EO1v~#}c(%Rjq(8xsUFecS]tm4ptH2H4pSrT|0NiW$i.=|i');
    define('NONCE_KEY',       '`lMlz,i#-T}31eG9&&yR;56uk(N(]t~@m-~L-y+viIQG% fS~Da3hRMDAhv@w|O@');
  4. Change prefix table: In its standard configuration, WordPress add the prefix wp_ before the name of each table. You modify this prefix, by editing the wp-config.php, before the WordPress installation:
    $table_prefix = 'wp_5a8f4B_'; // 'wp_';

    Be careful: if the blog is already installed, you have also to rename all the table of your database,

  5. Hide the WordPress version: The version of WordPress can be a good information for a hacker. By default, WordPress creates a meta tag in the header of each page:
    <meta name="generator" content="WordPress 2.8.4" />

    You can suppress this tag, by inserting the following line in the file function.php of your theme:

    add_filter( 'the_generator', create_function('$a', "return null;") );
  6. Delete or rename the wp-admin account: this account is the first target of attacks. The method is simple: create a new account with administrator rights, and then delete the wp-admin account. If you just want to rename the account, you can execute the following query (with phpmyadmin for example):
    UPDATE wp_users SET user_login='<new login>', user_nicename='<new name>', display_name='< new name >' WHERE user_login='wp_admin';
  7. Move the file wp-config.php: if you run a version 2.7 or later, you can move the file wp-config.php, that contains all the main parameters of the blog. Moving this file somewhere else than root, make the file almost invisible,
  8. Rename the directory wp-content: If you run a version 2.7 or later, you can also rename the directory wp-content that contains themes and plugins. To do that, you have just to rename the directory, and add the following line in the file wp-config.php:
    define('WP_CONTENT_DIR', dirname(__FILE__) . '< new name of the directory >');
  9. Set the user rights precisely : This rules seems to be obvious, but it is not always applied. When you create a user, think to define its role, according what he has to do in the blog, and not more,
  10. Limit the number logins’ retry with plugins such as Limit login attemps, or Login lockdown.
  11. Limit the number of users: if it’s possible, limit the number of people who are able to login to the administration interface of your blog. Give also some rules for password, to avoid too simple passwords.

At the web server level

WordPress is nothing other than a set of PHP scripts. It’s impossible to have a strong security without actions at the web server level. The following actions run with Apache, and can be implemented by modifying the file .htaccess, often stored at the blog root

  1. Forbid to list files: By default, it’s easy to list files of a directory. We just have to use the url of this directory. For WordPress, list files allows to identify plugins, theme, WordPress version … To ensure that anyone can « see » your files, just add the following line to file .Htaccess at the root of the site:
    # disable plugin directory browsing
    Options -Indexes
  2. Secure wp-admin directory: Only authors and administrators need to access to the administration interface. So, only those people need to reach the directory wp-admin. You can restrict access to this directory:
    order deny,allow
    deny from all
    allow from XXX.XXX.XXX.XXX # 1iere IP autorisée
    allow from XXX.XXX.XXX.XXX # 2nde  IP autorisée

    These lines are correct if you have a fix IP. If it’s not the case, you can secure the access with a password,

  3. Restrict the access to the file wp-config.php: This file is very important for the blog, because it contains many parameters of the blog, including details of the database (password included). You can forbid access to this file with the following lines:
    <files wp-config.php>
    order allow,deny
    deny from all
    <files>
  4. Restrict access to all files: The previous rules restrict access to the file through http requests. At a lower level (operating system), we can also define some access rules. With a FTP client, change the access rights of your files:
    Type Code Owner Group Other
    Files 604 Read / Write Read
    Directory 705 Read/Write/Execute Execute

    If you don’t need to have a write access, you can use the code 404 for the files, and 505 for the directory. Be careful with this solution: some plugins require write access (cache plugin for example), and you need write access if you want to add images, or attachments to your posts.

Conclusion

The rules given in this post, are those that can be most often read on the Internet. I let you see the references below for more details.

Please don’t apply these rules without preparation, and check. Without precaution, these action can block the blog.

Security, especially in computing, is a never-ending task: the set of vulnerability / patch is continuous. We will never totally protected against an unknown vulnerability, or a more subtle attack than others. But security should not become a full-time job. We need to know to set limits, based on two main criteria: the frequency of incidents and the cost of each of them.

Applying rules previously described allow us to reduce efficiently the incident frequency, because these rules cover 99% of risks. But if someone succeed to enter, our objective will be to deduce the attack cost, that mean reduce the downtime, and the work to do, to restart the blog. So, I insist again on the backups, which constitute an effective and simple tool, to restart a blog, quickly and without stress.

Références