· WordPress security

Recovering a hacked WordPress

Introduction

A few weeks ago, I had to repair a hacked WordPress installation.

A lot of the information I needed to successfully clean the WordPress completely of infected files was not centralized in a single guide. So I decided to write one and you are now reading it.

So, your website is hacked, what now? Let’s go through the process of making sure that every infection is removed and it never happens again.

In this first part you’ll recover from a hack. In a second part you’ll learn how to harden the security. I’ll publish the second part a few weeks after the first part.

This post is meant to be exhaustive and clear. If you have any suggestions or feel like something is missing or unclear, please let me know.

The WordPress version I used to write this post is 4.2.2.

Disabling all plugins / going into maintenance mode

The first thing you should do is avoiding further infections. Disable EVERY plugin. We’ll reactivate them later on.

I’d also put the website in maintenance mode. This requires, ironically, a plugin called WP Maintenance Mode. Install it, write a quick message for your visitors and enable it.

Take a backup

Backup your complete WordPress folder and database. You can download all the files using FTP or SSH and export the database to SQL statements using something like phpMyAdmin or the customer panel of your host (CPanel, DirectAdmin…). Don’t store the backup on your webserver as the hackers could also infect this backup.

Restore the original WordPress files

Download a fresh copy of the version of WordPress you were using (which should always be the latest one). Unpack it and replace the directories wp-admin and wp-includes completely with the copy you just downloaded. Do the same with every file in the root folder and remove every file in your root that is not in the downloaded copy except for wp-config.php. The only folder left untouched should be wp-content. WordPress also doesn’t include the wp-config.php file so that should also be preserved (we’ll inspect this file later on in this guide).

Clearing the cache

Delete the folders wp-content/cache and wp-content/plugins/widgets. They will be automatically recreated.

Regenerate salts and hashes

The wp-config.php file contains a few hashes and salts to make sure that your cookies and sessions are unique and secure. As these could have been compromised, it’s absolutely necessary to regenerate them. Open your wp-config.php file in a text editor and overwrite your new hashes with new ones. WordPress offers an online generator so you can easily copy and paste them.

Upgrade to the latest version

If you’re not on the latest version of WordPress, then update ASAP. I’d recommend using these extended instructions instead of the built-in updater, but the built-in updater should be fine for most infected websites.

Upgrade all your themes and plugins while you’re at it.

Restore the original themes and plugins

In this step we’re going to restore the original theme and plugin files like we did with the original WordPress files. Download the themes and plugins from wordpress.org or from the website of the publisher of the plugin or theme (for premium/payed versions). All you need to do is unpack the files into their respective directories in wp-content/themes and wp-content/plugins. Make sure there are no other files than the ones you just replaced in both of these folders.

NB: some plugins (e.g. plugins containing drop-ins) like WP Super Cache also put PHP files in your wp-content directory.

Search and delete infections in your files

The only infected files left could be stored in the subfolders of wp-content that we haven’t looked into yet.

languages

If your WordPress is in English, you can safely delete the contents of the languages folder, otherwise you should download the translation in your language and put in the wp-content/languages while deleting everything else in it.

upgrade

The folder upgrade in wp-content is used by WordPress’ built-in updater and should always be empty except for when you’re updating of course.

uploads and other folders

Next up: search every other folder in wp-content for PHP and server configuration files and delete files if you think they shouldn’t be there. I suggest doing a case insensitive search for *.php and .htaccess and carefully inspecting the results.

find /path/to/wordpress/wp-content/uploads/ -iname "*.php" -or -iname ".htaccess"

You probably shouldn’t have any PHP or .htaccess files in wp-content/uploads/someyear/.

Finally search all the remaining files for typical code injections. PHP injections usually contain the functions eval and base64_decode.

egrep 'eval(|decode(' -r -H /path/to/wordpress/wp-content/

Search and delete infections in your database

While most infections are usually to be found in the files, hackers could also insert executable and obfuscated code into your database. Most often these are XSS injections and WordPress should protect you against them. Still, it wouldn’t hurt to scan your posts and comments for injected code.

The easiest way is to connect to your database right away using something like the previously mentioned phpMyAdmin tool. Login, open the database and go to the SQL page so you can run some SQL commands. The select statements below will show you the posts and comments containing common injections. Use a DELETE query (be careful) or the phpMyAdmin GUI to completely delete the found posts and comments. Don’t forget to change wp_ to the prefix you use.

SELECT * FROM wp_posts WHERE post_content LIKE '%<iframe%'
UNION
SELECT * FROM wp_posts WHERE post_content LIKE '%<noscript%'
UNION
SELECT * FROM wp_posts WHERE post_content LIKE '%display:%'
UNION
SELECT * FROM wp_posts WHERE post_content LIKE '%<?%'
UNION
SELECT * FROM wp_posts WHERE post_content LIKE '%<?php%'
SELECT * FROM wp_comments WHERE comment_content LIKE '%<iframe%'
UNION
SELECT * FROM wp_comments WHERE comment_content LIKE '%<noscript%'
UNION
SELECT * FROM wp_comments WHERE comment_content LIKE '%display:%'
UNION
SELECT * FROM wp_comments WHERE comment_content LIKE '%<?%'
UNION
SELECT * FROM wp_comments WHERE comment_content LIKE '%<?php%'

Using Exploit Scanner and Sucuri Security to detect further infections

Most code injections should be gone by now, but there are a few WordPress plugins available to detect everything that’s left.

Exploit Scanner scans your files for possible hidden infections. Its options allow you to also scan for iframes etc., but they cause a lot of false negatives.

Sucuri Security is a plugin I’d really recommend for any WordPress installation, whether you were hacked or not. The plugin allows you to automatically scan for changed files, notify you about any administrative action, easily reinstall every plugin and theme after a hack…

Take advantage of all possibilities of the free versions of both of them. They will make sure that your WordPress is clean and stays clean.

Check users and passwords

One of the last steps is to check if the hacker didn’t create any new users. While you’re at it, change the passwords of every user with more rights than a regular subscriber.

Restoring your website and keeping it safe

Your WordPress should now be clean of infections and you can start restoring your website. Turn maintenance mode off and deactivate the WP Maintenance Mode plugin. Now activate all the other plugins you used one by one. Make sure to delete any plugin you don’t really need and check if they are still being maintained/updated. I’d also delete every inactive theme. This part of the guide is crucial since it was probably one of the plugins that was used to accomplish the hack.

Harden your WordPress Security

A few weeks after this post, I’ll publish a follow-up guide on improving the security on your WordPress website.

Sources

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pocket

In case you have any further questions, remarks or suggestions about this post, feel free to drop me a tweet or an email! You can also find me on Slack on the Xamarin Chat. I go by the username sam_d.

About the author

Sam is a C# developer who builds mobile (cross platform) apps with Xamarin. He's been a certified Xamarin mobile developer since 2016. Sam likes to experiment with all kinds of programming languages and software frameworks. More info