What to do if your blog has been hacked

I’ve recently worked on a couple of blog sites that had been victim to malicious activity. The evidence was different in both cases and for one consisted of search results that promoted drugs that enhance performance. And we’re not talking about blog performance 🙂 For both sites there was hidden text and html code in all the posts containing offsite links to seeming random and unrelated websites. The job I had was to remove any sign of malicious code and sanitize the sites. Additionally I was getting browser warnings indicating malware was present on the page I was navigating to. The warnings suggested I don’t continue lest my PC be infected further.

Investigating a hacked WordPress site

With WordPress there are a few good ways to speed up the job of troubleshooting a hacked site and speed may be of essence with something like this. I asked the client when there were first signs of the malicious content or behavior – believe me it’s actually very useful to know the exact date & time you first experience the issue as you’ll see later. So, if that time information is not available or cannot be remembered viewing the server error logs promptly could give you some more information. Armed with that information and presuming you can get into the site’s admin dashboard you try the following fairly standard actions to help uncover the culprit and mitigate further issues:

  • Disable all plugins
  • Switch to default theme
  • Use Theme Authenticity Checker

The Theme Authenticity Checker plugin does a quick scan of all installed themes for unnecessary code – typically this code consists of statements or functions like “eval( blah blah);” code injected somewhere in any of a themes files. Pay attention to anything TAC highlights – perhaps removing un-needed themes. For any theme that is highlighted as containing potentially malicious code you’ll need to edit the affected file or remove and re-install the theme files from the originals. That’s a drag if you’ve made theme modifications but it means you can revert to being back online. In one of the cases here I was re-enabling the plugins one at a time and I found that a plugin was causing one issue (preventing the blog from displaying) and by removing it from the plugins folder I could continue.

However, perhaps your blog site is non-functioning and you can’t get into your site’s admin dashboard? Well, now’s the time you use FTP or SSH connect to the server hosting the website. Remember I said how useful it is to remember the date & time you first noticed the hacking / issue? Well, here’s where you can navigate to the following folders and look for files that have been changed around the same date/time:

  • wp-content
  • wp-admin
  • wp-includes
  • wp-content/themes/*
  • wp-content/plugins/*
  • the folder above wp-content – sometimes public_html or public

* The above folder list is not exhaustive but typically this is where the malicious code is to reside

In each of these folders look for other folders or files that have recently been created. These are sure indications that modifications have been made and you need to target those files or folders.

Fixing a hacked site

After searching in the above folders on the clients sites here’s what I found:

  • A folder called “backup” and in there was malicious file  “backup-loader” that had code to display an authentic looking message on the WordPress dashboard.
  • An include statement at the top or within the index.php
  • A file/folder combination called “__notes/notes” that was included in index.php
  • Malicious code in wp-includes/theme.php
  • Malicious code in functions.php – an eval statement that referred to a setting in the wp_options database
  • Malicious javascript code in the wp_options database

With FTP you can download, use a code editor, and then upload fixed files. With SSH using a code editor directly to removing the malicious code in the php files. Identifying the code to remove was pretty easy as often the code segments looked out of place and therefore easy to remove and test. The wp_options code required the use of a MySQL database client like PHPMyAdmin to manually edit the table and remove the code and the related entry / record to prevent re-infection.

Cleanse and Sanitize

I said before that one of the effects of this hacking was that all the posts and pages had been injected with additional HTML code. Again with a MySQL client I looked through the blog database tables and found that also infected were the “revision” records for each affected post or page. Each malicious link was hidden from view with a CSS “style display:none” command and each link was injected in random locations within the post content. This made cleansing a labor intensive job (I could have possibly written some code to scan and remove but time didn’t permit) as I had to manually edit each post in the database – copying and pasting to a code editor and then pasting it back into the database, view the page or post, view the source to ensure the malicious code was gone.

Check in with Google Webmaster Tools as well to see if Google has identified malware on your site. If it has then follow it’s suggestions as to how to get the information Google stores about the site updated to reflect the current, non-malware, site.

WordPress Security Review

Once your site is cleansed and working you might take a look at further locking down access to reduce the chances of this happening again. Changing your admin and FTP passwords regularly is always good practice but there are more hints and tips in my WordPress Security post.

I successfully managed to fix these sites using the techniques described above – if you ever experience similar incidents then this short guide will help you. I do recommend now after all of this, taking a database backup and upgrading to the latest version of plugins and WordPress as soon as possible.

Thoughts, ideas always welcome in the comments.

*Update* After I completed this project I came across an updated version of Exploit Scanner – more information here. A useful tool to assist in fixing a compromised WordPress installation.