Recovering from a Hacked WordPress Site

(…another in a series of posts mostly for myself – so I’ll have a place to remember things….but maybe the random visitor will find something useful here.)

One of the sites I visit is a Q&A forum type place about WordPress development. And there is always a question about ‘how do I fix a hack of my WordPress site?’.

If you ask the googles, you’ll find lots of answers; some are actually good answers. Some aren’t. So I thought I’d put down what I would do if I was in that situation. (I’ve had to do this before, for other sites and clients.)

Step 1: Secure Access

If your WP site gets hacked, someone got into the site somehow. Doesn’t really matter how they did. So my first step is to secure access to the site.

This means that I will first change the password on my hosting place. Strong passwords, of course, and one that I have never used before (or will use elsewhere).

Next, I look at the external access to my files. This means looking at all FTP user accounts, and changing the ones that I use to develop or access the site. (Or in the case of client sites, their access.). And looking for user accounts that I don’t recognize. Those will get immediately deleted. Then I will create a brand-new FTP user account, again with a strong password. All other FTP accounts will get deleted.

Then I look at the credentials for the WP database. I’ll change the password for that database. If the site is well-visited, I might create a new database user, assign it to that database. The access rights for that database will be limited; nobody gets all of the possible database rights.

Since I have changed (or added) the database credentials, I’ll go into the WP config file where those credentials are stored and change it to the new account. A quick check then to ensure that the site still works. If it is OK, I’ll delete the old database user account.

Just for grins, I’ll also change the passwords for any email accounts on that site. That is probably not needed, but couldn’t hurt. I’ll just have to remember to notify those email accounts of the change. Most of my sites are single-user (me), so that’s usually not a big deal

Step 2: Update everything

Next, I’ll log into the admin area of the site. I’ll create a new admin-level user, give it a strong password (of course), and then log out and log in with that new user account. Once logged in, I’ll delete the old admin account.

While in the user accounts area, I’ll create a user called ‘admin’. Strong password, but that account gets the lowest privileges. (Some hack attempts like to try to use the user called ‘admin’. So, I let them try.)

Next, I’ll look at any other user accounts. If there are several or more, I’ll screenshot the list, and then reduce their access levels to the lowest privileges. I’ll fix that access later when things are cleaned up.

Now, into the Admin, Update screen and reinstall the latest version of WP.

The next step is a bit more time-consuming – deleting and reinstalling all themes/plugins. Not just installing, delete everything first, then reinstall as needed. Hopefully, I’ve remembered to keep the number of active (and inactive) themes and plugins to the minimum. (Usually a good idea not to have plugins that aren’t active. Just delete them.)

To reinstall all plugins, I have to delete them first. Many may have some complex settings screens, so screenshots of those are done (and printouts if needed). Once I’ve documented all plugin settings, I’ll deactivate and then delete them all – using the option (if presented) to delete the files associated with the plugins.

This may break the site, of course, or at least not make it work like it normally does. So I may do this during low-activity times. (Some of my sites are always low-activity, so I just ‘do it’.)

After all plugins are fully removed, I start reinstalling the ones that are needed, using my reference screenshots/printouts to re-set the options for each as needed. I only use plugins from the WP repository, even the ones that I write. That way, I make sure that I get the most current version of the plugins – even though I check and update plugins (and themes) daily.

Once I have finished with all of the plugins, I do the same for themes. Screenshot the settings, delete the themes (files included), then reinstall from the WP Theme Depository. Put back all the settings (from my screenshots) as needed.

In both cases, I may use my FTP client to look at the theme and plugins folders to make sure that they have actually been deleted. Then I’ll reinstall.

A check of the site to make sure it works OK completes this step.

Step 3 – Investigate

Now I have (with any luck) a clean WP install, with current (and clean) themes and plugins.  I need to make sure that anything left over is not going to cause a problem.

First, I check the htaccess file. I know what that file should look like (look at the WP Codex for help), so I make sure that the file is how it is supposed to be.

Next, I use my favorite FTP program (WinSCP) to log into the site – after changing the user/pass to the new one. I then poke around all of the site folders for files that I don’t recognize. I usually sort by date (oldest first), and look for files that are earlier than today. Remember that I reinstalled everything, so everything that is valid should have today’s date stamp. I don’t rely on that date sort, though, I look at all of the files; the date sort is just the first pass through all the files.

And I look at all site folders, not just the root folder. Rouge files will jump out because of their name or datestamp. I sometimes move those rouge files into a non-site folder in case I want to look at them later. As I move files, I make sure the site is till working properly.

Step 4 – Product (ecommerce) and other files

I take a look at all of the media files on the site, on the off-chance that one of them is compromised. But usually those aren’t a problem.

What might be a problem is ecommerce/product files. It may be that a product file is the compromised access point. I’ll look at every single product, every single field for that product, to make sure that all is well. That can be a bit time-consuming, but so can a re-infection if a product is the infection point.

Step 5 – Posts and Pages and Comments

It may be that a post or page has some rouge code in it. Now, by default, WP will not execute code inside a post/page. But, on the off-chance it does, I want to ensure that all posts/pages are OK. Depending on the site, I may use a SQL command or two to look for indicates of code inside a page/post. If it is a smaller site, I’ll just look at all posts/pages. I may sort by date, if I am aware of the approximate date that the hack got into my site.

It’s not likely that a Comment will be the infection point, since I do have some protection against spammers – via my own plugins  (FormSpammerTrap for Comments) and Akismet. But a quick look at Comments is a good idea. I set up the anti-spam features to immediately discard all potential spam, so usually don’t have a problem with that.

Step 6 – Final Cleanup

By this point, the site should be back to normal. I’ve been checking the site as I go through each step, looking for indications of continued infection.

If I had to reduce privileges on user accounts, I put those back to normal.  And I make sure that backups are in place and working. Not just the database, but all files (WP, themes, and plugins).

Winding Up

The above steps are a really good start at cleaning up a site. Some would argue that a ‘Nuke from Orbit’ – starting from scratch by deleting everything, but that may not be an option for most sites. My procedure takes a bit of time (many hours – more than 8, usually), so it’s not easy. (And, if I am doing it for a client, it’s not inexpensive.)

But, I’ve been successful in site cleanups before with this process.

What do you think? Add your ‘thinky bits’ in the comments.

Leave a Reply

Name and email are required. Your email address will not be published.