What To Do When Your Website Is Hacked: Recover in 10 Steps
[To skip to downloadable file for this post, click here.]
So, my site got hacked. No, scratch that. All of my WordPress sites got hacked. No, that’s not right either. All of my WordPress sites got hacked twice. I’ve repaired it all, prepared the sites for the next vulnerability, and now I’m ready to share my regrets and shame, but mostly experience and tools.
While nobody can guarantee that a WordPress site is not going to be hacked again, there are a few things we can do to lower the risk and make it much easier to bounce back when this happens.
Backups, man! Do you have a recent backup of your site? How long will it take you to get back in the game if you start seeing, all of a sudden, pop-up ads for penis enlargement on your blog? Backups, man, backups. Back up your data, your plugins, your custom styles, everything. Store your backups off-site. All of this is common sense, but most of us start taking this stuff seriously only after a disaster.
At the end of this post, there’s a script that makes backing or restoring a WordPress site a one-step process. But if your site is hacked and you need to go through all the steps before creating the first clean backup, read on.
Step 1: Scan your PC
Often malware is introduced to a website through an infected Windows machine that you use to manage the site. Update your antivirus software and do a full scan of your computer. You want to be sure that your local computer is clean before you start repairing your website from it.
If you do not have an antivirus, AVG is good choice. They have a free version, and the prices for the paid license are very reasonable.
Some malware is very good at hiding from certain types of antivirus software. If you already have an antivirus, it may be a good idea to double-check and scan your PC with another type of antivirus.
Step 2: Verify that your site is infected
How can you be sure that your site has been hacked and has malware? How can you check which of your sites are clean and which are infected? Use an online site scanner. Scan every one of your websites before you start cleaning them up, and repeat the scan as you progress through the steps to restore sanity. Make it a habit to re-scan your sites regularly, or subscribe to Sucuri Monitor or a similar service.
Step 3: Back up your website
Although your site is infected, you still want to keep a copy of all its data and files for reference, at least until you make sure that all is back to normal.
Make a backup copy of your website’s files. If you have SSH access to your hosting provider, copy the entire directory containing your site into a backup location. If you use another way to access your files (such as SFTP, FTP, or web-based file manager), download the whole directory of the site.
Back up the database your site uses. In WordPress, you can download the content through “Tools > Export > All content” in the admin dashboard. Or, preferably, use a command line to export the whole database.
I’ve created a useful script that does both of these steps for a WordPress site automatically (it’s at the end of this article).
Step 4: Talk to your hosting provider
Most likely, the issue affects more than just your website, and your hosting provider is already aware of the problem. Most hosting companies back up their customers’ data regularly, and if your site was infected recently, they can simply restore it to a previous point, when it was not yet infected. They can also help you identify and fix the vulnerability that led to the problem in the first place. If you are lucky and your hosting support rocks, things will be back to normal before you know it. For the rest of us, there are next steps.
Step 5: Try Surgical Repair
This does not always work, but it’s worth a try. If you know the kind of attack that led to the site’s infection with malware (e.g. the infamous TimThumb vulnerability), and you can find good documentation on how the attack works, you can try to clean up the affected PHP files. There are a few WordPress plugins that can help. After every change you make, verify whether the site is infected (use Sucuri Scanner) and if it’s clean, verify that it works. It did? Congratulations! You’re done.
However, this method does not always work (as malware writers are coming up with new ways to hide malicious code), and sometimes you’ll have to scrap all code and install a clean copy.
Step 6: Disable the infected site
Sigh, so you’ve tried to remove the bad code from PHP source, and the site is still broken. You’ll need to set up the WordPress, the theme and plugins from clean slate, re-import the data, and monitor the whole process so that you know at the end of the process your site is clean and fully-functional.
To begin, let’s completely isolate the site from the outside world. The malware that got injected into your site could be acting as a backdoor, bringing more malware in. To prevent the malicious code from re-infecting the site while you’re cleaning it up, temporarily close it down.
A simple way to disable a site that runs under Apache (which WordPress does) is to add a rewrite rule into .htaccess file in the site’s directory, redirecting all requests to a temporary “your site is undergoing maintenance” page.
rewriterule ^(.*)$ http://example.com/maintenance.html [r=301,nc]
(You’ll need to set up the maintenance page somewhere outside of your site, of course).
Now open your website in browser — you should see the maintenance message instead of the site itself.
What have you achieved so far? Your data is backed up, you’re sure that your local machine will not infect the website and you’ve isolated the site from the outside world. Now you’re ready to begin the cleanup.
Step 7: Change Passwords
Change all the passwords. Don’t leave the bastards a chance.
Don’t forget to go through all of the passwords that may have leaked:
- SSH password
- Hosting Control Panel password
- FTP password
- Database password for every database accessible to your account
Step 8: Complete Clean Up
This part will have to be repeated for every website you are repairing. With the right tools (such as the backup/restore script below), it takes about an hour or two per site. Not too terrible.
Create a fresh WordPress application instead of the temporarily-disabled site. Use the newest version of WordPress and a new database.
- At this point, your WordPress should be working and free of malware. Check for malware — if it’s there, you’ve got a problem. Either your PC is infected, or you have a more serious issue on the server. Stop here, call support, run a virus scan on your PC.
- If the site is clean like it should be, proceed.
- Create a backup copy of site directory and database. This is your new clean copy – not very useful yet, but at least it will let you come back to this point if you make a mistake at a later step.
- Install the most recent version of the theme you want to use (make sure the theme does not use modules with known vulnerabilities — such as certain versions of TimThumb).
- Check for malware again. If the site got infected, it’s likely the theme. Roll back to the backup you created two steps back (good thinking!), and use another theme. If it’s clean, make anoter backup copy and proceed.
- For every plugin you need to use:
- Install latest version of plugin
- Check site for malware
- Roll back or create new backups as necessary
Step 9: Restore the data
Now that your site looks and behaves close to what it should, time to import old data. We’ll assume that there are no viruses or malware in the database. That’s a reasonable assumption, but before you act on it, please make sure you’ve backed up all your work prior to this point. Ready?
Export the database your site used to use. You can do it through phpMyAdmin or from command line.. The command will look something like this (all in one line):
mysqldump --user=<old_db_user> --password=<old_db_password>
--databases <old_db_name> --opt --quote-names --allow-keywords
--complete-insert -c > <archive_filename>.sql
And to load it all into the new database, you’ll import it — either through phpMyAdmin or through a command line like this one:
mysql --user=<new_db_username> --password=<new_db_password> <new_db_name> < <sql_file>
Now, for the last time (hopefully) check that your site does not have any malware, and you’re done!
Except that you are not really done. Time to make sure that an ordeal like this never happens again to you and your websites.
Step 10: An ounce of prevention is worth a pound of cure
Or, in metric system, “twenty-eight grams of prevention is about half-a-kilogram of cure”, which sounds admittedly much less elegant.
Here’s what you can and should do to protect yourself against future attacks.
- Follow the advice in the official guide on hardening WordPress.
- Before installing a new WordPress plugin or theme, at least Google for vulnerabilities related to it.
- Monitor your site — use Sucuri or a similar tool.
- Keep your PC clean and secure. Don’t neglect your Windows antivirus.
- Make automatic backups that let you easily restore your site.
- Consider not using WordPress for serious sites. Use Django, Rails, heck, even .NET. Some platforms just take security more seriously than others.
- If your hosting provider is not helping you in terms of backups and recovery, move to one that does. Webfaction (where this site is hosted) is probably the best shared hosting option available.
Here’s the script that runs backups for DesignPractica and can restore a wordpress site in a single command: [dowload]. This is written in Python, simply because it’s the best language ever. You run these scripts like this.
python backup.py <path-to-wordpress-application-directory>
This will create a time-stamped backup directory inside ./wordpress-backup/
python restore.py <path-to-wordpress-application-directory> <path-to-backup-directory>
Note: If your WordPress site was hacked, this means there’s a vulnerability either in WordPress itself or in one of the plugins you are using. Upon restoring from backup, upgrade to all latest versions, and re-scan the site to make sure it did not get infected again. It’s generally a good idea to google for known recent vulnerabilities in WordPress plugins, and take appropriate steps — e.g. avoid affected plugins altogether, use safer alternatives, etc.
Also, if you are hosting your customers’ WordPress sites, make sure your users do not have admin rights. This may sound harsh, but seriously, “editor” role is quite sufficient for day-to-day use. There are good reasons why public hosting companies who support WordPress limit what plugins you may or may not install. There are good reasons not to trust users with this. If all you have is a few simple blogs and “business card” type of sites, sure — install all the experimental stuff you wish. The worst that can happen if they are hacked — you’ll lose your latest blog post or comments. But for large online stores keeping track of their customers, a hacked site may mean serious damage to credibility. If all your customers suddenly start getting spam, if their personal information is compromised, your business is be in serious trouble. If all of your customers’ customers are exposed in this way, you’re dead, as long as your business is concerned.
Well, thanks for reading this long post-mortem. Here are a few affiliate links to the great tools I mentioned in this post. If you decide to purchase their products, do me a favour, go through these links.