Has your WordPress been hacked?

There have been a number of vulnerabilities discovered in WordPress since it started, including one earlier this month. They all have pretty much the same objective: to try to get access to your blog in order to post links to their own sites.

In this post I am going to look at ways you can tell if your blog has been hacked, suggest some ways to fix it, and then discuss techniques to prevent being hacked again.

Before we start, the most important thing you can do to prevent being hacked in the future is to regularly update your blog software. The easiest way is to use subversion. I’ve written how to upgrade your blog with subversion in an earlier post.

Symptoms

So firstly, you’ll probably want to find out if your blog has been compromised. There are a few things to look out for:

Unauthorised Admin Users

Disable JavaScript in your web browser, then navigate to the Users page in the WordPress admin panel. If you see some additional administrator users there that you didn’t expect, you have probably been hacked. They sometimes use an e-mail address like [email protected]

Strange Files in the Uploads Folder

Strange files may also appear in your WordPress uploads folder, including ones that have hidden PHP code inside them (try grepping for “events or a cale” or php).

grep -R -l "php" wp-content/uploads/

The files might have random names like:

faceboutique-spot-less-150×150.bak.php
mandseyeshadowpalette.bak
cliniqueblusher_old.jpeg
.wp-cache.cache.php

The uploads folder is writeable by apache, so hackers use this area to save malicious code to your server. They may then include such code as a plugin.

Strange Records in the Database

Check for suspicious data in wp_options by running the following queries:

SELECT *
FROM  `wp_options`
WHERE  `option_name` LIKE 'active_plugins';

Hackers use the plugin system to include their rogue scripts. You may see some strange files being listed as a plugin. You can delete this row and manually re-activate any plugins via the admin.

SELECT *
FROM  `wp_options`
WHERE  `option_name` LIKE  'permalink_structure';

This will show you the permalink structure – the most recent vulnerability modified this so look out for anything abnormal.

SELECT *
FROM  `wp_options`
WHERE  `option_name` LIKE  '_transient_rewrite_rules';

You can delete this row if it exists (it should be rebuilt dynamically)…. it may contain cached

SELECT *
FROM wp_posts
WHERE post_content LIKE  '%iframe%' OR post_content LIKE  '%noscript%' OR post_content LIKE  '%display:%';

This will look for posts that contain iframes, or hidden links.

Fixing a hacked WordPress Installation

The cleanest way is to re-install WordPress, re-import your posts and comments via the import tool and then to copy in any files that you know are safe…

  • Back up your database and site code.
  • Export your posts, comments, tags and categories in a WordPress WXR File (Tools – Export).
  • Set up a new mysql database, username and password. Ensure the user only has access to the WordPress db.
  • Install a fresh copy of the latest version of WordPress (with the correct permissions), and configure it to point at the new db.
  • Delete any files that include PHP from the uploads folder.
  • Import your posts, comments etc from the WordPress WXR XML file. There is an option to get WordPress to fetch image uploads, but I haven’t had that much luck with this. To get it to work, you will need to install your new blog in a parallel location so that it can access the old blog. When I tried, it seemed to grab the files, but not update the location urls in posts, thus requiring a script to update the urls in the db. Instead, you might find it easier to just copy your uploads folder across – but they won’t then show in the media gallery. Neither route seems ideal!
  • Re-install your themes and plugins.
  • Move the old blog to a location outside your web root as a backup, or delete it all together.
  • Set up new WordPress users with secure passwords.

It’s not a fun job!

Securing WordPress

  • Ensure you have the right permissions set on your WordPress scripts. Only the uploads folder should be writeable by the web server.
  • Use a separate database, db username and db password for WordPress.
  • Add an additional layer of authentication above the WordPress admin area, e.g. http authentication in Apache. NB: When I did this, it seemed to stop uploads from working with the flash uploader (gave a HTTP ERROR), so I had resort to using the basic browser uploader.
  • Some people also recommend removing the default “admin” user, and setting up an administrator with a new name – to make it harder to brute force crack your passwords.

Further Information

Here’s some of the pages I read while researching this article….