dbsec1

“Why should I care about WordPress security?”

That is the question I usually get when I start talking about how to install WordPress securely. Believe it or not, many people think the chance of a hacker — or precisely, cracker or web site intruder — getting into their blog and causing havoc is slim to none.

The bad news is, it happens more often than you think.

I’m sure you’ve seen search results in Google that were tagged with the This site may harm your computer message directly below the title, or read stories about this blog and that blog being hacked.

If you perform a quick search on the National Vulnerability Database, you’ll find that WordPress has an increasing number of vulnerabilities. It was 2 in 2004, but the number quickly increased over the years to 63 in 2007.

This isn’t an attack on WordPress. It’s simply that no software is immune to security problems. This is made even worse when the application is very popular and opensource.

In this article, I’m going to show you some quick fixes that you can do to block the holes that may occur during or after WordPress installation. Some of the tips here are for more advanced users though, and make sure that you always take a backup of your database before writing any sort of MySQL query.

1 – Secure WordPress Database

WordPress requires access to a database and it doesn’t care if you share that database with other web applications. For simplicity, you should create a database just for WordPress though so even if someone breaches your blog through one database access, not all of your data are in jeopardy.

Basically, here are things you should do with WordPress database creation:

  • Create a database for WordPress. WP uses only a few tables but giving whole database just for the blog instead of sharing it is more like limiting its access.
  • Create and grant limited access to a database user. Create a user to access this database only and grant limited access to SQL commands on this database (select, insert, delete, update, create, drop and alter).
  • Pick a strong database password. It can be as random as possible because you don’t have to remember it.

For the majority of us, you would do all this from your webhost’s control panel, when you set up the database. But for the MySQL-confident, you can use these queries:

1
2
3
4
5
$ mysql -u root -p
mysql> create database 'myblog';
mysql> grant select, insert, delete, update, create, drop, alter on myblog.* to 'bloguser'@'localhost' identified by 'mypassword';
mysql> flush privileges;
mysql> exit;

If you use cPanel to create your database, pick the right checkboxes to give the database user just enough privilege to perform WordPress operation.

db-privileges

2 – Populate wp-config.php Properly

Go through each line in wp-config.php, not only the first block for database configuration.

Use WordPress secret key generation tool to generate random salts for WordPress cookies. These keys are used to insure better encryption of information stored in WordPress user’s cookies.

You also want to modify the WordPress table prefix to something other than wp_. Adding random characters and numbers to the end of wp, such as wp23jk1_ obfuscates it enough but still allows you to recognize the tables as those belong to WordPress.

3 – Don’t Use the Default admin Username

If you install WordPress manually, this involves modifying the database. Fantastico users are able to pick admin user and password as part of the installation process. There are more fields to fill in but you may end up with more secure WordPress installation.

1
2
3
4
5
$ mysql -u bloguser -p
Password: mypassword
mysql> use myblog;
mysql> update wp23jk1_users set user_login='myadm' where user_login='admin';
mysql> exit;

You may use phpMyAdmin and paste the SQL command (the update line) to execute it.

update-wp-admin

Alternatively, you may edit the value manually using phpMyAdmin web interface.

update-user-manual

Now your admin user name is myadm instead of admin.

4 – Pick Secure Password for Admin

Changing your admin username to something else is not a guarantee that people will not be able to guess it. For instance, if you use your username as the displayed meta data in every post, or you enable author specific page in multi-author blog, you will reveal your user name to the world.

With that assumption, you should pick secure password for your WordPress login. Combine upper and lowercase characters and numbers.

5 – Use Secure Login via Encrypted Channel

WordPress users who have SSL enabled for their domain (Talk to your host about this first. You won’t have this by default!) should use that encrypted channel to access WordPress Dashboard. You can force admin sessions over HTTPS by setting FORCE_SSL_ADMIN variable in wp-config.php to true.

Copy and paste the following into your wp-config.php file.

1
define('FORCE_SSL_ADMIN', true);

6 – Upgrade as New Version Becomes Available

When WordPress releases new version, especially one that includes security fixes, upgrade as soon as time permits, even though it doesn’t include features that you use.

7 – Backup Your Database and Files

Install a plugin or use cronjob to create database and file backups on a regular basis. This may not be directly related to security, but in case you detect intrusion, you will be glad you make a backup.

Refer to this post to backup your WordPress database directly to a Gmail account.

8 – No Directories Should be Available for Browsing

By default in most hosting, index of directories are shown in web browsers. This has a purpose but it also means that you reveal the content of any directory that has no index.html or index.php.

Modifying this behavior is easy with Apache, just add the following line of code to the .htaccess file in the root directory (In the same place as the wp-config.php file).

1
Options All -Indexes

9 – Protect WordPress Administration Files

WordPress administration files reside in wp-admin directory of your WordPress installation, except wp-config.php. The latter contains basic WordPress configuration that can not be modified through the Dashboard.

You may use .htaccess to restrict access and allow only specific IP address to this directory and file. If you have static IP address and you always blog from your computer, this can be an option.

Note that you may also allow access from a range of IPs. Refer to Apache’s documentation on mod_access for complete instruction on how to set this up.

You need to put a .htaccess file in wp-admin.

Example:

1
2
3
Order Deny,Allow
Allow from ww.xx.yy.zz
Deny from all

Protecting wp-admin directory with user and password combination also adds another level of security. Apache has complete information on authentication, authorization and access control.

Example:

1
2
3
4
AuthType Basic
AuthName "WordPress Dashboard"
AuthUserFile /home/user/.htpasswds/blog/wp-admin/.htpasswd
Require user adminuser

and then generate the encrypted password using the htpasswd command.

1
$ htpasswd -cm .htpasswd adminuser

cPanel has a feature called Web Protect which allows you to accomplish the same thing.

If you implement all of those above, you should be accessing the wp-admin directory from the allowed IP address, authenticate with adminuser and then login normally to your WordPress Dashboard with your WordPress admin account (myadm).

10 – Restrict File Access to wp-content Directory

The wp-content directory contains your theme files, uploaded images and plugins. WordPress doesn’t access the PHP files in the plugins and themes directories via HTTP. The only requests from web browsers are for image files, javascripts, and CSS.

For that reason you may restrict wp-content so that it only allows those file extensions but not PHP or any other file extensions. This prevents people from accessing any files directly.

Include the following lines in .htaccess within wp-content:

1
2
3
4
5
Order Allow,Deny
Deny from all
<files  ?\.(jpg|gif|png|js|css)$? ~>
	Allow from all
</files>

11. Hide WordPress Version in the Header Tag

Although you have deleted the WordPress version meta data from your theme, you may still get WordPress version line in the page returned by the blog software. The culprit is, since version 2.5 WordPress has added the feature to generate this code.

Add the following line to the functions.php file in your theme directory: (Create a blank PHP file with this name if your theme doesn’t already have one)

1
<?php remove_action('wp_head', 'wp_generator'); ?>

It is important to note that even with all of those above implemented, there is no guarantee that your blog will be safe. Just that you decrease the chance tremendously and discourage those crackers from targeting your blog.

New exploits are discovered every so often and when a fix has not been made available yet, everyone is at risk. However, by implementing all or some of the tips above, at the very least it should give you peace of mind that you are not leaving your house unlocked.

Do you have any other tips, or do you do something differently? If so, please share!

Click here if you want to learn more about WordPress security.

About the author: Hendry Lee helps solopreneurs and small business owners overcome strategic and technological challenges in starting and growing their blogs. Get fresh blog tips from his blog, updated daily.

Enjoy this post? You should follow me on Twitter!