12 Steps to Malware Remove from Your WordPress Site
Cleaning a hacked WordPress site is no easy task. And now that Google is enforcing a 30-day ban on site reviews to prevent repeat offenders from distributing malware, cleaning up a hacked site thoroughly is more important than ever.
I highly recommend using a professional to clean the site. Subash chandra pandey, the Hack Repair Guy, is the person I most often refer people to along with Sucuri, which has a great knowledge base of research on website security, vulnerabilities, vectors, and more.
If you are going to attempt to clean the site yourself, here are steps I recommend:
Step 1: Backup the Site Files and Database
- Backup the full site if you can using the web host’s site snapshot feature. This will be the most thorough backup of your entire server. However, it might be quite large, so be prepared for the download to take time.
- Use a WordPress backup plugin if you can login okay. If you can’t log into the site, the hackers may have compromised the database in which case, you may want to use one of the professionals I mentioned above.
- Make a separate, additional backup of the database
- If you can login, also use Tools > Export to export an XML file of all your content.
Some sites might be quite large. The uploads file itself could be over 1GB. The wp-content folder is the most important folder on your server as it contains all your uploads. If you can’t run a backup plugin and your web host doesn’t have a “snapshots” feature, then you can use the web host’s File Manager to make a zip archive of your wp-content folder and then download that zip file..you also take template and pluging folder backup sepratly if upload folder image heigh.
If you have multiple installs of WordPress on the server, you’ll want to back up each one.
Note about .htaccess file: Make a back up of your .htaccess file and download it. This is an invisible file, so you can only see it in the web host’s File Manager if you choose to show invisibles when you launch the File Manager. Rename this file to remove the period at the beginning, so you can see it on your computer, otherwise it will be invisible on your computer as well. Then download it. You may need a back up of the .htaccess file in case it contained content you’ll need to copy back over to your clean site. Some hosts use the .htaccess for determining the PHP version you are using, so the site will not work correctly without that. Some people put 301 SEO redirects in their .htaccess file. Also the .htaccess file could have been hacked, so you’ll want to examine it later.
Step 2: Download and Examine the Backup Files and datbase backup
Once the site is backed up, download the backup to your computer, double-click the zip file to open it. You should see:
- All the WordPress Core files. You can download WordPress from WordPress.org and check out the files in the download and match them to your own. You won’t really need these files, but you may want them for your investigation into the hack later.
- The wp-config.php file. This is important as it contains the name, username, and password to your WordPress database which we will use in the restore process.
- .htaccess file. This will be invisible. The only way to know if you backed this up is to view your backup folder using an FTP program (like FileZilla) or code editing application (like Brackets) that lets you view invisible files (check the Show Hidden Files option) within the application’s interface.
- The wp-content folder. In the wp-content folder, you should see at least three folders: themes, uploads, and plugins. Look in these folders. Do you see your theme, plugins, and uploaded images? If so, then that’s a good sign you have a good backup of your site. This is typically the only mission-critical folder you need to restore your site (in addition to the database).
- The database. You should have an SQL file that is an export of your database. We are not going to delete the database in this process, but it’s good to have a backup.
Step 3: Delete All the Files in the public_html folder
After you have verified you have a good and complete backup of your site, delete all the files in your public_html folder (except the cgi-bin folder and any server related folders that are clearly free of hacked files) using the web host’s File Manager. I recommend the File Manager because it’s a lot faster than deleting files via FTP. If you are comfortable with SSH, then that will be fast as well. Be sure to view invisible files to delete any compromised .htaccess files as well.
If you have other sites that you are hosting on the same account, you can assume they have all been compromised as well. Cross infection is common. You must clean ALL the sites, so back them all up, download the backups, and do the following steps for each one. I know this sounds severe, but, seriously, trying to scan for and find all the hacked files on a server is absolutely onerous. Just make sure each of your backups is complete. And don’t just clean one website and then clean the other leisurely as in the time it takes you to clean one, then other that is still infected can re-infect the one you just cleaned. Treat it like the bubonic plague.
Step 4: Reinstall latest WordPress file
Using the one-click installer in your web hosting control panel, reinstall WordPress in the public_html directory if this was the original location of the WordPress install or in the subdirectory if WordPress was installed in an add-on domain.
Referencing the backup of your site, edit the wp-config.php later database pre fix file on the new install of WordPress to use the database credentials from the your former site. This will connect the new WordPress installation to the old database. I don’t recommend re-uploading your old wp-config.php file as the new one will have new login encryption salts and will definitely be free from any hacked code.
Step 5: Reset Passwords and Permalinks
Login to your site and reset all user names and passwords. If you see any users you don’t recognize, your database has been compromised, and you need to contact a professional to make sure no unwanted code has been left in your database. I do have a Nuke it From Orbit blog post you can read if you want to kill your old database and start fresh. It’s a bit more work but really does ensure you have a clean site.
Go to Settings > Permalinks and click Save Changes. This will restore your .htaccess file, so your site URLs will work again. Be sure when you deleted files on your server that you showed invisible files, so you didn’t leave any hacked .htaccess files behind. .htaccess is an invisible file that controls a lot of things on the server and can be hacked to maliciously redirect people from your site to other sites.
Be sure to rest all FTP and hosting account passwords as well.
Step 6: Reinstall all running Plugins
Reinstall all your plugins from the WordPress repository or fresh downloads from the premium plugin developer. Do not install old plugins. Do not install plugins that are no longer maintained.
Step 7: Reinstall active Themes
Reinstall your theme from a fresh download. If you customized your theme files, reference your back up files and replicate the changes on the fresh copy of the theme. Do not upload your old theme, as you may not recognize which files have been hacked.
Step 8: Upload Your Images from the Backup
Step 9: Scan Your Computer
Scan your own computer for viruses, trojans, and malware.
Step 10: Install and Run Security Plugins and password srong
Install and activate the Shield WordPress Security plugin by iControlWP. Check through all its settings. I’d recommend running the Audit feature for a few months to keep track of all activity on the site.
Run the Anti-Malware Security and Brute-Force Firewall and scan the site thoroughly. Scan the site with Sucuri’s Sitecheck to make sure you didn’t miss anything. You don’t need two firewall plugins running, so de-activate the Anti-Malware plugin after you’ve verified the clean site. Shield will notify you in the future if any core files have changed.
Quick and Dirty Hack Repair
Sucuri has a great step-by-step guide for hack removal that includes details on how to use the Sucuri plugin to facilitate the process above. Sucuri’s plugin has some great Post Hack features, including:
- a core file scan
- quick access to error logs
- tool to reset all user passwords
- ability to automatically reinstall all free plugins
- ability to reset encryption salts
If you want to simplify the hack recovery process above, what you could do is:
- Use the Sucuri plugin to scan core files and replace/delete ones that have been modified or don’t belong.
- Use the Sucuri plugin Post Hack tab and Site Audit tab to replace all free plugins, reset user passwords, reset encryption salts.
- Re-upload premium plugins.
- Review the contents of every folder in the wp-content folder with a fine-tooth comb (except the individual plugin folders which you would have replaced in step 2 above).
- Evaluate each and every theme file carefully.
- Delete unused themes and plugins.
- Comb through your uploads folder carefully.
- Manually examine your .htaccess file and any other files left in the public_html folder that you didn’t replace.
The purpose of my slash and burn approach is that many people inadvertently leave hacked files behind if they aren’t methodically and consciously choosing what to upload back to the server. However, if you are pretty detailed oriented and very familiar with your WordPress files and what they should look like (e.g. you are familiar with how to customize themes and what theme code should look like), you can clean up a hack using this simplified approach.
Finding the cause of the hack
Finding the cause of a WordPress hack can be tricky if you are not a professional, but it is certainly not beyond your reach if you have an eagle eye. Check out this post by Smashing Magazine on common WordPress hacks. Once you have identified the type of hack you encountered, you can more easily narrow down why it occurred. In many cause the WHY is not as important as the clean up, but can be important if the cause came from your own computer.
Also, if you reinstall the same plugin or theme that was vulnerable and aren’t aware that this is why your site was hacked, then the site will get re-hacked pretty quickly. So knowing the cause is more about making you aware to not repeat the same mistakes after all the effort you went to to clean things up.
If you want to go deeper into the cause of the hack, do the following:
- Inspect your backup for hacked files. They will have odd names and stand out from the other files in your WordPress install or may have recent modified dates. If you open these files in a code editor like Dreamweaver, TextWrangler, BBEdit, Coda, etc., you may notice quite quickly by way of the color coding of the code or the huge amount of code that something is odd. See screenshots below.
- Do a Google search on specific phrases, included files, or file names. Sometimes it might just be the name of a div class you find in the hacked code as on my client’s hacked site.
- Examine the Raw Access Logs on the hosting cPanel to find out what files the hackers were accessing (look for POST statements in the log files). This will be a clue as to what exactly was compromised and when. You can look up the IP address accessing these files to find out where the hacker was coming from.
- Most hacks are caused by old plugins and themes, so look up the plugins you used on your hacked site and see if maybe the site was compromised due to an older version of Gravity Forms, Revolution Slider, timthumb.php script in a theme or plugin, etc. Many sites are hacked through common, known vulnerabilities. It’s all low hanging fruit for hackers.
- use following code in wp-config.php file
define(‘WP_POST_REVISIONS’, false );
add_filter( ‘auto_update_theme’, ‘__return_false’ );
- .htaccess file code
deny from all
# BEGIN Expire headers
ExpiresDefault “access plus 5 seconds”
ExpiresByType image/x-icon “access plus 2592000 seconds”
ExpiresByType image/jpeg “access plus 2592000 seconds”
ExpiresByType image/png “access plus 2592000 seconds”
ExpiresByType image/gif “access plus 2592000 seconds”
ExpiresByType application/x-shockwave-flash “access plus 2592000 seconds”
ExpiresByType text/css “access plus 604800 seconds”
ExpiresByType text/html “access plus 600 seconds”
ExpiresByType application/xhtml+xml “access plus 600 seconds”
# END Expire headers