How to Fix a Hacked WordPress Website – 2019

I recently did a talk at a WordPress Meetup on the topic “How to Troubleshoot a Hacked Website” – it’s something I do very regularly, so I had a lot to speak about. However, I thought it would be prudent to at least read a few blog posts on the topic to see if I was missing anything. Well, that was an eye-opening experience! Some of the advice out there is terrible, and at best won’t fix the problem, and at worst will trash your site.

In this post, I take you step by step through my process for fixing a hacked website. This process is going to find and fix any issues that you might have with the least amount of time and effort. If you find this useful, please comment below – I’d love to hear from you. Of course, if you are still having problems by the end of it, let me know that too. And if you’re just not inclined to do it yourself, head on over to WP Butler and we can take care of it for you.

The Ultimate Guide to Fixing a Hacked WordPress Website

Before we dive in, let’s just take a breath. Have you really been hacked? Maybe you’re just seeing a bug or error? Ask yourself the following questions:

  • Are you seeing content that you did not add yourself?
  • Do you find unexpected URLs when you search Google for site:yourdomain.com?
  • Are you being redirected away from your site to another site?
  • Has your web host reported malicious activity?
  • Is your browser telling you that your site is dangerous?

If you’ve answered yes to any of these questions, let’s proceed!

Step 1 – Backup Your Site, Now

First, we need to take a snapshot of everything, as it is, right now. I do this anytime I’m doing anything on someone else’s website. I always want to be able to restore a site to the exact state it was when I began working on it just in case my activities make things worse. But also, nervous web hosts have been known to delete files that have been compromised.

The easiest way to backup your site is to get into your hosting account and export the database, then zip up all the files. If your web host has backups built in to their service, that’s even simpler. Download the files to your local machine, again, just in case. Don’t delete the zip file from the hosting account, because if it needs to be restored, you’ll have to wait around while you upload it again. However, don’t keep it in the public_html folder – move it to the root of your hosting account.

Now that we have everything we need to restore the site, let’s move on.

Step 2 – Log into the WordPress Dashboard

Our aim is to log into the WordPress Dashboard so that we can install the WordFence plugin. WordFence is typically used as a Web Application Firewall (WAF), but it has an exceptional tool for scanning a site and finding malware and other issues. If you can log into the Dashboard, jump ahead to Step 8.

If you can’t access the Dashboard, we need to start reducing complexity. Plugins, and even some themes, make WordPress more complex by introducing additional functionality. Any of these may be preventing you from successfully logging into the Dashboard. So we now need to (temporarily) remove them.

Step 3 – But First, Do You Already Have a Backup?

Before we start, do you already have a backup? Maybe you’ve already been diligently backing up your site on a regular basis? Maybe your web host does it for you? Maybe you have a maintenance package with a web developer, and they are doing it for you. It’s going to save you a lot of time if you can click a button and restore the last working backup. It’s not going to necessarily fix the hack – websites are often hacked months before the symptoms show. But if you can restore a backup and get into the Dashboard, we can install WordFence and fast-track the fix.

Of course, if you need to log into the Dashboard in order to restore the backup, you’re out of luck. Just thought I’d ask. Let’s keep going.

Step 4 – The WordPress Debug Log

As stated earlier, the goal here is to get access to the WordPress Dashboard. But we want to do this without making extra work for yourself. The last thing we want to do is start randomly deleting elements of your website. Let’s think about this.

First, turn on the WordPress debug log. Open up your wp-config.php file, scroll down until you see the line /* That's all, stop editing! Happy blogging. */, then add the following lines of code just above:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
define( 'SCRIPT_DEBUG', true );

This code tells WordPress to write any issues it encounters to a file in the wp-config folder called debug.log.

Once you’ve saved the wp-config.php file, try and log in again. Whether you can enter a username and password, or whether just opening the login page causes the error, the details should now be written to that file. Open the debug.log and let’s take a look.

What you’re looking for is a PHP fatal error. This means, the page that you were looking at encountered an error that it was unable to recover from. You don’t need to understand the error itself, but you’re looking for a clue as to what’s causing it. If you see the error relates to a file in a /wp-content/plugins/ folder or a /wp-content/themes/ folder, then we have a good starting point in our attempt to access the Dashboard.

Step 5 – Reducing Complexity

Now, we will begin reducing the complexity of your WordPress website. If you got a hint from the debug.log as to what might be causing the issue, let me explain how to use that.

First on the chopping block is plugins. To deactivate a plugin without logging into the Dashboard, all you need to do is rename its folder in the /wp-config/plugins/ directory. Then, the next time WordPress tries to load a page, it can’t find that particular plugin any more, so it automatically deactivates it.

If you found a fatal error in the debug.log pointing to a particular plugin, try renaming only that plugin folder.

However, if you did not find any issues in the debug.log, what we’re going to do is just rename the plugins folder itself. Then, WordPress won’t be able to find any plugins, and they will all be deactivated.

It doesn’t matter what you name it – plugins.bak, plugins-deactivated, pluginsssss – as long as it’s been renamed, WordPress will deactivate anything it can’t find.

Can you log into the Dashboard now? If not, next on the chopping block is your theme. You can only ever have one theme activate at a time, so rename that theme and try the Dashboard again.

Still no luck? Go to the root of your WordPress installation and rename the .htaccess file. This might be a bit tricky – any file that begins with a '.' in a unix filesystem is a hidden file. So if you don’t see it, it’s likely hidden! Whether you’re accessing the filesystem via FTP or File Manager in cPanel, check the option to view hidden files.

Finally, if all that fails, take a close look at your wp-config.php file. If you’re not familiar with it, open the wp-config-sample.php as well and compare the two files. Anything that doesn’t look like it should be there can probably go. Technically, you should be able to recreate the wp-config.php file by copying out the database details – that is, the MySQL settings and $table_prefix.

Having done all of this, if you still cannot access the Dashboard, the next thing we need to do is reinstall WordPress.

Step 6 – Reinstall WordPress

This step differs dramatically from other tutorials, so pay close attention. Most tutorials tell you to download the latest version of WordPress from wordpress.org/download and install it. The problem with that is that you may not have the latest version of WordPress installed. And now is not the time to do an update! That will add a new layer of complexity to this task. What we want to do is reinstall the same version of WordPress that you currently have installed.

First, let’s find out what version of WordPress you are currently using. Open the file /wp-includes/version.php and look for the following line of code:

$wp_version = 'x.x.x';

Once you know what version of WordPress you have, you can download it from wordpress.org/download/releases.

To install this version of WordPress, and ensure any malicious code is removed, first I delete everything in your hosting account except the wp-content folder and the wp-config.php file. (Of course, if you have non-WordPress files in your hosting account, don’t delete them…) Now, you want to unzip the clean version of WordPress, delete the wp-content folder, then upload everything else into your hosting account.

Now, you have a fresh version of WordPress, with no themes or plugins adding unnecessary complexity. You should be able to log into the Dashboard now…

Step 7 – Still No Luck? Check the Database

By this stage, we can assume the WordPress code is clean. At least, clean enough to log into the Dashboard. If you still can’t – maybe you’re being redirected away to an external URL when you try – the problem must be in the database.

Check the wp_options table and ensure the siteurl and home entries are correct. After that, simply search the entire database for the URL to where you are being sent.

I’ve seen all sorts of interesting hacks:

  • The siteurl changed to another URL
  • HTML redirects appended to every post and page
  • A 301 redirect set up on /* (every URL on your domain)

That last example is particularly problematic because it tells the search engines that your page URLs have permanently moved to a new location.

Once you’ve cleaned up any malicious records, you will now be able to access the WordPress Dashboard.

Step 8 – Install WordFence, Scan and Fix

You’ve made it! You now have a somewhat-functional version of WordPress. If you click into the Plugins and Themes sections, you will see that they have been deactivated. You can now rename any folders back to what they were originally – they won’t be reactivated until you do so manually.

Search for “wordfence” in the Plugin repository, and install it. Before starting the scan, go to All Options, and under “Basic Scan Type Options”, select High Sensitivity for a more thorough scan.

The free version of WordFence does an exceptional job finding malicious code in your WordPress installation. It will even fix some files for you, but if you’re not sure how to fix the code yourself, it’s best to delete the plugin or theme that’s been infected and reinstall it from scratch.

WordFence will flag out-of-date plugins as a potential issue, but leave any updates until the end – you don’t want to make this process any more complicated than it has to be.

You may need to run the scan a couple of times, but by the time you’ve finished all the tasks, you will have a clean website.

The Aftermath

Once the site is clean, you’re going to want to prevent future hacks. The WordFence firewall is very helpful, and I recommend using it in conjunction with the iThemes Security plugin.

You will also want to:

  • Reset all your passwords, including the database
  • Check you don’t have unrecognized Administrator accounts
  • Reset your salts (found in the wp-config.php file)
  • Update your theme, plugins and the WordPress core
  • Remove any unnecessary files (inactive plugins, for example)
  • Re-save your permalinks

Leave a Comment