Installing and operating a WordPress blog is so easy that you can do it without needing to know much about what’s going on behind the scenes, especially if you use a hosted service that provides the Linux, Apache, MySQL, and PHP (LAMP) underpinning, as many people do. Lots of bloggers use WordPress, and, consequently, lots of hackers scrutinize it for security vulnerabilities. Fortunately, you can take a number of simple steps, covered here, to significantly reduce your exposure when using popular third-party scripts such as WordPress.
On the surface it’s simple: Install WordPress, change a few settings, select a theme, and you’re up and running with a full-featured, professional-looking blog. Installing and operating a WordPress blog is so easy that you can do it without really needing to know much about what’s going on behind the scenes. Even for Windows professionals who don't have much experience with a Linux, Apache, MySQL, and PHP (LAMP) platform, setting up and managing a WordPress blog is hardly intimidating, especially if you use a hosted service that provides the LAMP underpinning, as many people do.
The basis of hundreds of thousands of active blogs, WordPress is among the most common blogging platforms. Hundreds of user-contributed plug-ins and themes are available to get WordPress to do almost anything you want it to do. Given the number of users and tools, finding support for the platform isn't hard, but finding insecure WordPress installations is also pretty easy.
Widely used scripts such as WordPress undergo lots of public scrutiny. Although WordPress developers have been responsive when security issues have been raised, hackers delight in targeting popular software, so more vulnerabilities will likely be found. Fortunately, you can take a number of simple steps, which I cover here, to significantly reduce your exposure when using third-party scripts such as WordPress. Although the focus here is on WordPress, many of these same tips will help you secure just about any script.
WordPress Attack Surface
Any application has risks and exposures that increase the attack surface (i.e., give an attacker more opportunities to find holes). A larger attack surface means the odds of someone finding a vulnerability are greater. An analogy is having a building with one locked door vs. a building with a hundred doors. The building with more doors has more chances of having faulty locks or doors someone left unlocked.
The WordPress platform has a fairly large attack surface that increases its potential for vulnerabilities. First, WordPress has an extensive admin section that consists of more than 100 files. More files mean more code, which means more complexity and potentially more attack vectors.
Another risk is that WordPress can accept input from anonymous users in the form of comments and trackbacks. Although WordPress does filter this input to prevent most known attacks, allowing anonymous input greatly increases the attack surface.
WordPress implements a number of semantic Web technologies, such as XMLRPC, that enable automated finding, sharing, publishing, and integration of information. Although certainly useful, these technologies increase the attack surface and introduce further complexity. A security strategy must address each of these technologies.
The risks associated with blogging software are often compounded by the fact that many bloggers aren't familiar with securing the LAMP platform, or they have another company host their blog and so have no control over the security of the layers underlying their WordPress blog. All too often, even hosting services don't follow the best security practices. Each component in a LAMP platform must be individually secured, but here we focus on the WordPress platform itself.
Tip 1: Stay Updated
Before working on specific fixes, make sure you have the latest WordPress distribution installed on your server. As with any application, security researchers and hackers report WordPress vulnerabilities that require an update. Once they do, that information is public for any hacker to exploit. As soon as WordPress announces and publishes a security update, you should download and install it. If you don’t keep your blog software up-to-date, it will be an easy target.
Tip 2: Limit Admin Access
The greatest exposure for a WordPress installation is the wp-admin directory used for administering the blog and authoring posts. Obtaining access to this area means gaining access to the entire blog and likely the entire Web site. An attacker can use a script to automate thousands of attempts at brute-force guessing your admin password.
The best defense for the wp-admin exposure is to deny every IP address access to the wp-admin directory except for your own and those of any authors on the blog. Of course, this isn't always completely possible, but even if you can narrow the IP address ranges a little you will reduce this attack surface. For example, say you have a dynamic IP address in a class B range. Limiting to that range will significantly reduce the number of people who can access the directory.
In Apache, you can use a .htaccess file to restrict access by IP address. Create an empty text file named .htaccess on your system and open it in a text editor.
The first step is to prevent access to the .htaccess file itself. You can do that by typing the following lines in the .htaccess file:
deny from all
Next, you need to specify which IP addresses should have access to the blog. Type lines similar to the following, but that specify your allowed address ranges, after the previous lines in the .htaccess file. Notice the different ways of specifying the allowed addresses:
allow from 127.0.0.1
allow from 10.2
allow from 192.168.0.0/16
allow from example.com
deny from all
These lines allow the specified IP addresses through and deny all other addresses.
Upload the .htaccess file to the wp-admin directory of your WordPress installation. Set the permissions on the file to 644, which allows everyone read access but allows only you, the file owner, write access. Once in place, this .htaccess file will deny access to anyone not having an IP address on the allowed list. Note that the .htaccess file limits access only via HTTP, so if you have any problems with the .htaccess file, you can FTP to your site and simply rename the file to remove the IP address restrictions.
Tip 3: Password-Protect Admin Access
IP address restrictions won't work for every situation, and they won’t block all potential attackers. A threat could, for example, originate from your own organization. Although WordPress has built-in user management and authentication features that require a logon to access the admin section, I prefer to have an additional layer of protection to ensure that Apache itself will enforce a password to access any files in the admin area. The main reason for this is that given the complexity of the admin area, a hacker could find a function that doesn’t properly check user permissions.
For example, shortly after the release of WordPress 2.3, hackers found a way to bypass administrator authentication to add links to the blog’s blogroll. They were able to do this because a function in link.php didn’t properly check whether the current user had the permissions to add links.
Another benefit of the extra layer of authentication is that it provides a clear barrier to the administration functions. Without it, an attacker might find a way to use a cross-site scripting attack to silently trick you into performing administrative functions. For example, an attacker might disguise a link that, if clicked, would automatically perform some privileged action on the blog without you knowing it.
You can add password protection manually by using a .htpassword file with Apache, or your Web hosting service's control panel might provide password protection capabilities. Alternatively, a quick way to password-protect the wp-admin directory is with the AskApache Password Protect plug-in that you can download from http://www.askapache.com/wordpress/htaccess-password-protect.html. This WordPress plug-in adds a configuration page in the admin area that you can use to set a username and password on the wp-admin directory.
Tip 4: Use SSL for Administration
Although an extra layer of authentication will help control access to administrative functions, the method described in Tip 3 employs basic authentication, which doesn't use strong encryption. Anyone on the network between you and the server can potentially intercept your password and cookie to gain your logon credentials. To help prevent this, you should always use Secure Sockets Layer (SSL) when you access the admin area of your blog. Check with your hosting service to see whether it supports SSL, or if you host your own site, go to http://httpd.apache.org/docs/2.2/ssl/ for more information about using SSL with Apache. Either way, you'll need to obtain and install an SSL certificate.
Once you have SSL working, a couple plug-ins are available to enable SSL on the WordPress blog. You can download Secure-Admin at http://haris.tv/2007/01/11/wordpress-ssl-plugin-secure-admin-patched-and-working/. This plug-in lets readers use regular HTTP connections to browse the blog but automatically redirects logon and administrative requests to use HTTP Secure (HTTPS). Furthermore, it restricts cookies to transmission only over SSL connections.
The other option is a plug-in called Force SSL, available at http://www.almosteffortless.com/wordpress/force-ssl/, which forces all connections to your blog, including those simply for reading blog posts, to use SSL. This might not be desirable in many cases, but you might actually want this in some instances.
Tip 5: Change Usernames
Most Web applications are vulnerable to brute-force password-guessing attacks on user accounts. An automated script can easily test thousands of passwords in an attempt to find one that works. A brute-force attack is much less likely to succeed if the attacker also has to guess the username. Unfortunately, WordPress by default creates an administrator account named Admin that's also used for authoring blog posts. The username appears on blog posts, so it's very public. To limit your exposure to brute-force attacks, you should replace the default Admin account with an account of a different name and create a separate account with limited privileges for writing posts.
You need to create a new admin account rather than just renaming it because WordPress doesn't allow you to change an existing username. Browse to the /wp-admin/users.php directory on your blog and scroll down to the Add New User section. Set an uncommon username and select the Administrator role, as Figure 1 shows. Next, log off the blog and log on again with the new username. Return to the Users page and delete the original Admin account.
Now that you have this account set up, add another user account for authoring new posts. When you add the new account, set the role as either Editor or Author. Once you have these accounts set up, never use the administrator account for authoring and never use the authoring account for administration. Another tip for limiting exposure to brute-force attacks is to set a nickname for your authoring username. WordPress lets you have a username for authentication and a different nickname that's displayed on your blog posts. That way, authoring a post doesn't reveal the username you use to log on. To set the nickname, click Edit next to the username for which you want to add a nickname. You can't edit the username field, but you can scroll down and set any nickname you want.
Another defense against brute-force attacks is the Login LockDown plug-in available at http://www.bad-neighborhood.com/login-lockdown.html. This plug-in blocks IP addresses that have made multiple failed logon attempts within a certain time range. Login LockDown won't stop a determined attacker, but it will make a brute-force attack more difficult. Of course, the best defense against a brute-force attack is to always use a strong password and change it regularly.
Tip 6: Limit File and Directory Access
Deny from all
<Files ~ "\.(css|jpe?g|png|gif|js)$">
Allow from all
Save the file and upload one copy to the /wp-content directory and another copy to the /wp-includes directory. Note that although WordPress needs to access a number of PHP scripts in these directories, these requests are done internally and therefore won't be restricted by the above .htaccess files. It's also important to prevent others from being able to browse the contents of your Web directories. If a directory has no default document, such as index.htm or index.php, many Apache installations will show a directory listing for the current directory, which might expose sensitive files. In the root directory of your blog, create a new .htaccess file, or if one already exists, add the following line at the end of the file:
Options All -Indexes
With this option set, a directory won't show a directory listing, even if it doesn't have a default document.
Tip 7: Prevent Search Engine Indexing
Hackers often use search engines to locate blogs that contain insecure scripts. Someone might, for example, discover a vulnerability in a WordPress PHP file and do a Web search to find sites that have that file. Thus, it's best to exclude the wp-admin and wp-includes directories from search engine indexes. You can accomplish this by placing a robots.txt file in the root directory of your blog with the following contents:
Note that not all search engines honor these settings and robots.txt does nothing to prevent access to the two directories, but for the most part, it will prevent them from showing up in search results.
Tip 8: Set Correct Permissions
Perhaps the most serious mistake administrators make is to set incorrect permissions on WordPress files and directories. When faced with an Access Denied error, too many administrators give everyone full control—represented by the 777 permissions value—rather than tracking down the real problem. To make matters worse, quite a few plug-in authors recommend setting permissions to 777 on some directories to make their script work properly. You should never have to set permissions to 777 to make a script work. Usually, changing file ownership will fix the problem. If you give everyone full control over a directory, they can upload and execute anything they want on your Web site.
In addition to setting proper permissions, setting the wp-admin and wp-includes directories to read-only is always a good practice. This won’t prevent someone with enough privileges from changing a file, but read-only files work surprisingly well in blocking or limiting damage from automated attacks. You can set files to read-only through your FTP client, by using CHMOD at a console, or by using a Web interface to the file system that many Web hosting companies provide.
Tip 9: Use Plug-ins and Themes with Caution
As I've already demonstrated, WordPress can accept plug-ins that allow users to enhance it or add new features. WordPress also lets users design custom themes to quickly change the look and feel of a blog. Hundreds of WordPress users have contributed their own plug-ins and themes for use by the WordPress community. Although these plug-ins and themes are quite popular, you should implement them with caution.
Often, these user-contributed scripts have not gone through any security testing, and sometimes they contain significant security bugs. They could even contain backdoors placed there by the developer. Always have a qualified programmer well-versed in security review the code in the plug-ins and themes you want to add to your Web site. The best strategy is to avoid adding too many plug-ins and themes and focus on those that provide important features on your blog. Blogsecurity.net regularly reviews popular WordPress plug-ins for security flaws, so watch that blog for important updates.
Tip 10: Remove Unused Features
Features and complexity are always a security concern because they add more code, and more code means more potential for flaws in code. If you feel your blog is at enough risk to warrant the extra effort, you might want to remove features you don't use. For example, you could prohibit file uploads. One thing that WordPress usually does well is to gracefully handle missing functions. Sometimes all it takes to disable a feature is to remove the associated PHP files for that feature. Other times, however, you might need to make adjustments to scripts that look for those features, especially to theme template scripts, some of which are notorious for not working when certain functions are missing. For that reason, removing features is probably something best reserved for blogs for which the risks are great enough to make the extra research and testing pay off.
If you do remove any features, it's always a good idea to document any changes you make. Having that information will be a great help when it comes time to upgrade WordPress.
Creating a blog for your organization might be a great PR tool, but a hacked blog is a PR nightmare. Using a common blog platform such as WordPress does have some risks, and securing a WordPress installation does take some care, but just remember that even a little security can go a long way.