Recovering a hacked WordPress
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.
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.
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.
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
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.
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