A Complete Guide to Removing Malware from WordPress 1

A Complete Guide to Removing Malware from WordPress

Table of contents

Removing malicious code from your WordPress site is not one of the easiest tasks. That is exactly why such services can sometimes cost up to a hundred euros per site. And even then you cannot always be one hundred percent sure that the service provider did their job one hundred percent. Recent studies show that as many as 84% of sites contain vulnerabilities. This means that any of them can be infected at any moment. Throughout this comprehensive guide you will learn how to remove malicious code from your WordPress site, how to fix vulnerabilities, how to get your site off blacklists and how to prevent such troubles in the future.

Disclaimer

A lot depends on the hosting too. For example, if you have another site installed in a subfolder or subdomain and both are located on the same host, please isolate them. If you have several sites on the same hosting, do not forget that you will need to perform this procedure for each of them. If you have other sites, make sure you have isolated them from each other, because malicious code can jump from one site to another.

1. Close Access to Your Sites Before Starting the Malware Removal Process

It is very important that during the process of removing the malicious code nobody except you can access the site. Some hosts let you put your sites into maintenance mode. However, if your host does not have such a service, you can close access to the sites as follows:

1.1. Apache

Open your .htaccess file (in some cases htaccess.txt) and paste the following code at the very top (just do not forget to change the IP address to your own):

order deny,allow
# Deny access from all IPs deny from all
# Allow access from specific IP
allow from 127.0.0.1

1.2 Nginx

Open the nginx.conf file and enter the following lines in it:

location / {
# allow your IP below
allow 127.0.0.1;
# drop rest of the world
deny all;
}

2. Install Antivirus Software on All Computers from Which You Have Access to the Sites

It is a very common thing for the FTP access, as well as the username and password for your hosting admin area, to be stolen with the help of various keyloggers or other computer viruses. That is why it is very important that the computers from which you access the admin panel or FTP have some kind of antivirus installed. For example, as a precaution you can scan your computer for viruses using software from Malwarebytes. Also do not forget to check your Windows settings and make sure the firewall is on. And, in general, do not forget to regularly update your OS, browsers and the corresponding extensions.

3. Change All Access Credentials (Hosting, SSH, FTP, MySQL, WP Users)

After you have closed public access to your site and scanned your PC for malware, change all passwords. Start with the password for the hosting admin area, then remove all FTP accounts and create new ones with pre-generated passwords (some hosts offer such a service themselves, but if necessary you can always use Keepass2, Dashlane, LastPass or any other password manager).

3.1. Change the Database Credentials

As soon as you change the password for MySQL or MariaDB (or any other database), you will need to update the corresponding information in the wp-config.php file

3.2. Change the Salts

Salts are used for secure password storage. Originally passwords were stored as plain text inside the system, but later additional security measures were invented. One of them is the salt. Since new salts are generated randomly for every password, it is very important to replace them with new ones in the wp-config.php file

You can generate new ones here: https://api.WordPress.org/secret-key/1.1/salt/

3.3. Change Access to the WordPress Admin

Log in to your WordPress site, open the Users section and delete all inactive accounts. Then click Edit on the active accounts one by one under Account Management, log out all sessions and click Generate to generate passwords for all users. But first make sure that you do not have an account with the username Admin or Administrator.

4. Make a Full Backup of Your Site

If your host does not provide any backups, be sure to download all the content from your server and the database to local storage.

4.1 SSH

Some servers give you SSH access, which can noticeably simplify your life when removing malicious WordPress code. The process may differ depending on the host. Once you have successfully logged in to the site using SSH, run the following command: zip -r backup-pre-cleanup.zip .

This may take some time, but in the end an archive with all the files from your hosting will be generated. You can then download this file directly using SFTP.

4.2. SFTP

SFTP is the secure version of the FTP protocol. It is used to transfer files from one computer to another. You can get your SFTP credentials in the same place where you got your FTP access. Just do not forget that the SFTP port is 22, not 21 as with FTP. You can access the server via SFTP/FTP through special client programs such as FileZilla. Then you can make a local folder on your computer – for example, naming it backup-pre-cleanup – and simply drag all the content of your server into it. Just note that this will take more time than archiving the files over SSH.

4.3. The Database

Many hosts have a PhpMyAdmin panel that lets you manage your database. You can easily export the entire database using the corresponding option in PhpMyAdmin. Save all of this to the same folder as before: “backup-pre-cleanup”.

You can also export the database over SSH using the following command:

mysqldump -p -h hostname -u username database > backup-pre-cleanup.sql

Just do not forget to change the host name, username and database to your own (you can get all this information from the wp-config.php file). After exporting over SSH, be sure to download everything to local storage and delete it from the server.

5. Analyzing Logs and Recent Changes

It is from the logs that you can tell what was changed or added to the server. Download the access logs (if you cannot find them, request them from your host). Open the logs with a program like Sublime and press ctrl + F to search for POST. Look at the dates and determine whether any extra PHP files were added to the server.

You can also check which PHP files were changed recently. To do this, use the SSH command:

find . -type f -name ‘*.php’ -ctime -7

The same applies to JavaScript files – see which of them were recently changed or added:

find . -type f -name ‘*.js’ -ctime -7

-ctime -7 will show you all changed files (as well as changed permissions and attributes) in the last seven days. You can change the number of days depending on your needs:

-7 = changed less than seven days ago

+7 = changed more than a week ago

Just do all this before you change or update a large number of files in your WordPress.

6. Update Your WordPress

One of the most common reasons your site may be infected is outdated code, plugins or themes. Another reason is overloading the site with plugins or weak passwords and usernames.

6.1. Get Rid of All Rarely Used Plugins and Themes

Even if you have deactivated a plugin or theme, it still remains on your server and in some cases can be the very vulnerability through which hackers get to you. So it is always better to be safe and remove such things from the server so as not to leave any vulnerabilities in it.

7. Update Your PHP Version

PHP 7 makes your site twice as fast (compared with PHP 5) and uses half as much memory. The seventh version of the language is also much more secure. So if you have PHP 5.6 or even lower, you should update as soon as possible. Some developers today have stopped supporting old versions of PHP altogether, which means you may be unable to update some of the plugins you have installed.

8. Remove Symlinks (Symbolic Links)

Many attackers use so-called symbolic links to gain access to the root and parent folders on your server. Sometimes symbolic links go unnoticed, and when you try to delete the linked folder, you may delete everything on the server. So make sure there are no symbolic links before changing the permissions of files and folders.

To avoid this, use the following SSH command (or wherever you see a suspicious folder)

find . -type l -exec unlink {} \;

9. Set the Right Permissions

Make sure no file or folder on your server has 777 permissions. By default all folders in WordPress should have 750 permissions, while all files (except wp-config.php, which can have as little as 400) should have 640. You can change the permissions of all folders over SSH to 750 with just one command:

find /path/to/your/WordPress/install/ -type d -exec chmod 750 {} \;

And to change all file permissions to 640, again use the same SSH with the command:

find /path/to/your/WordPress/install/ -type f -exec chmod 640 {} \;

Over SSH you can change the wp-config.php permissions to 400 with the following command (just first make sure it works and – if needed – change the permissions to 440; if it does not work, stick with the default option):

chmod 400 /path/to/your/WordPress/install/wp-config.php

It is possible to make things even stricter, but that depends on the hosting itself. You can read more about file permissions in the WordPress Codex.

10. Removing Malicious WordPress Code (Files)

In this section we will look at various open-source tools for detecting malicious files, in both automatic and manual modes. We always prefer the manual option, because that is the only way to best understand how it all works and to be calmer knowing you have done everything to clean the site properly.

10.1. Compare a Fresh WordPress with the Infected One

Create a new WordPress installation and install exactly the same plugins and themes as on the old one. Create a Compare folder and put two folders in it – Clean and Infected. Using SFTP, download the new WordPress and put it in the Clean folder, then open the backup of the old WordPress and copy it into the Infected folder. Download the Beyond Compare program and compare the two folders. The main focus should be on PHP and JavaScript files. If the program says that files such as index.php and wp-mail.php differ, upload the files from the Clean folder to your site via SFTP and see whether everything started working differently after you did this. If the site breaks in the process, just undo everything by uploading the file from the Infected folder back. This method lets you manually restore an infected WordPress and bring themes and plugins back to their original state. Also, if you know your way around, you can use SSH commands such as: diff -r WordPress-clean/ WordPress-infected/ -x wp-content

Also take into account that the wp-config.php file will differ from site to site. Use this method only to determine whether the original files were changed or whether any extra files were added to the system’s main folders (note that /wp-content/uploads/ is not a system folder).

10.2. Remove All PHP Files from the Uploads Folder

PHP files should never be located in the uploads folder, yet attackers often exploit this weakness – as a result many backdoors and droppers end up exactly here. Open your SSH console and go to /wp-content/uploads/ (you can use cd commands for easier navigation – for example, cd /wp-content/ and then cd /uploads/) and run the following command:

find . -name “*.php”

10.3. Detecting Backdoors and Malicious Code (Manually)

Backdoors and malicious code are often very well hidden (sometimes they are also added to the headers of original system scripts) so that the relevant antivirus tools do not find them. One of the most popular functions in this regard is eval(), base64_decode(), gzinflate(), str_rot13() To detect such files, open the SSH console and run the following command: find . -type f -name ‘*.php’ | xargs egrep -i “(mail|fsockopen|pfsockopen|stream\_socket\_client|exec|system|passthru|eval|base64_decode) *(”

Also search for backdoored images using commands like:

find wp-content/uploads -type f -iname ‘*.jpg’ | xargs grep -i php

And iframes:

find . -type f -name ‘*.php’ | grep -i ‘<iframe’

10.4. Finding/Removing Backdoors and Malware (Automatically)

There are various tools and scanners with which malicious code can be found automatically. Here we list only open-source tools that have earned a good reputation. But always remember that most malware and backdoors are designed to remain unnoticed by such tools, so a manual audit is never superfluous.

10.4.1 Ai-Bolit malware scanner

A decent tool for detecting malicious code. It also scans JavaScript code and has different detection levels. It works as a PHP script that you upload to your site, and it starts scanning as soon as you run it. It uses both patterns and heuristic analysis. It finds a lot, sometimes even too much (there are false positives).

The tool’s website: https://revisium.com/aibo/

10.4.2 PHP malware scanner

This tool looks for PHP extensions and checks files against text rules as well as regexps. The rules are based on both its own samples and publicly available material about malware and webshells.

Github: https://github.com/scr34m/php-malware-scanner

10.5. Repeat Step 10.1 and Make Sure No Suspicious Files Are Left

When running malware scanners, delete files one by one and always check whether the site continues to work after deleting a given file. When you have completely cleaned your site of suspicious files, download the cleaned WordPress folder into the Infected folder and compare it with the Clean folder again using Beyond Compare. Also keep in mind that the file structure (except /wp-content/) should be identical. Look for encrypted and obvious file names such as N73He.php and hax0r.php. Sometimes attackers add their files to every folder as a message to the user. For example, such a message may contain something like “hacked by Team_CC”.

You can remove these files over SSH:

find . -type f -name “filename.php” -exec rm -f {} \;

11. Removing Malicious Code from WordPress via the Database

It very often happens that databases are infected with malicious code, and it is loaded along with posts, pages and user comments, as well as other site content. We have already exported a backup of the WordPress .SQL database. There are different ways to remove malicious code from the WordPress database.

11.1. Looking for Suspicious Content Right in the Backed-Up Database

You can open the SQL database directly with Sublime. Then use ctrl + f to find suspicious content.

Look for iFrame: <iframe
Look for base64: base64_decode
Look for eval(): eval()
Look for scripts: <script

Find everything suspicious and try to understand where everything is located. Do not delete them directly from your database backup – instead go to step 11.3.

11.2. Looking for Suspicious Content via PhpMyAdmin

If you have access to PhpMyAdmin, you can search directly using the search option. If you are sure you have come across suspicious code, try to understand where it was taken from and go to step 11.3.

11.3. Manually Going Through Pages, Posts, Comments and Revisions

Look into posts, pages and their revisions. Find suspicious posts using steps 10.1 and 10.2 and open them one by one in the editor in text mode. Delete all suspicious code and reformat the content. Do not forget to go to the Revisions section and pay attention to comments in order to delete possible spam.

12. Check the Site Manually and from the Search Engines’ Point of View

Look at your site from a visitor’s point of view. See whether anything suspicious is going on. Google your site. Then enter a query like this into Google: site:mywebsite.com. If you see a bunch of Chinese characters or suspicious pharmaceutical offers in the results, your site has most likely been infected with SEO malware. Such malicious code can only be found through search engines like Google, since it remains unnoticeable to visitors and the site owner. Install the User-Agent Switcher extension for Google Chrome, which will let you look at your site from the search engines’ point of view. You can also configure a custom agent in the extension settings. The most popular agent used by Google is the bot:

Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)

If you now follow the links as the Google bot with that user agent and see no other content, consider that you have successfully removed the SEO malware. If the strange content has not disappeared, go back a few steps and see what you overlooked.

13. Restore Public Access to the Site

If you have gone through all the steps, double-checked everything and are now sure that the site is clean, remove the restrictions from your website (but only from the site you have just cleaned – if you have any other sites on this hosting, it is better not to open them until you repeat the same process with them). If your host blocked access, ask them to rescan the site, tell them you have followed the instructions for removing malicious code from your site and ask them to restore public access to your project.

14. Ask to Be Removed from Blacklists

The best way to check whether your site is on anyone’s blacklists (for example, in search engines) is to use VirusTotal. For example, if you were blacklisted by Google, you can simply go to Google Webmaster Tools and request a rescan. It may take a few days, but if Google does not find malicious code on your site, it will remove it from its blacklist. If you ended up on the blacklists of other search engines, go to their sites and also request a rescan. In most cases you will need to fill in a form manually to request a rescan, and the process may differ between blacklists.

15. Additional Hardening of WordPress

There are a few things you should do in addition to everything listed above. There are a few simple tweaks that will let you easily prevent the most common infections.

15.1. Disable PHP Execution in the /uploads/ and /cache/ Folders

You can easily add a few lines of code to your Apache or Nginx configuration that will prevent the use of PHP inside the upload and cache folders. In many scenarios this can knock out a backdoor, since the malicious code simply will not be able to run.

Nginx:
# Deny access to PHP files in any /uploads/ or /cache/ directories
location ~ /uploads/(.+)\.php$ { access_log off; log_not_found off; deny all; }
location ~ /cache/(.+)\.php$ { access_log off; log_not_found off; deny all; }

Apache:

Create a .htaccess file in the upload and cache folders and write the following lines of code in it:

# Kill PHP Execution

deny from all

15.2. Remove File Editing from the Admin Panel

It is a good idea to disable the ability to edit files directly from the WordPress admin. To do this, just add the following line to the wp-config.php file:

## Disable Editing in Dashboard
define(‘DISALLOW_FILE_EDIT’, true);

15.3. Hide the Default Admin Panel

WordPress sites are often brute-forced by botnets and hacker scripts. One reason for this is that most sites use /wp-admin/ as the admin location, and the fact that many site owners use the standard administrator username and a weak password. Thus it is no trouble at all for attackers to get access to many WordPress sites and infect them with the malicious code they want, install backdoors, send spam and redirect traffic. It can be hard to change the location of the wp-admin folder manually so that everything works as it should. So for this purpose it is better to use third-party plugins such as WebARX.

15.4. A Web Application Firewall, Uptime Monitoring and Vulnerability Alerts

It would be good to get a web application firewall that is constantly updated. A firewall for sites is now a must-have, just like antivirus for computers. There are many plugins that will make your life easier and spare you from adding scripts manually. For example, Wordfence, iThemes Security and SecuPress.

15.5. Use Secure Hosting and Update Applications in a Timely Manner

Your hosting should be kept updated (make sure it supports at least PHP 7.2), properly configured and secure. If you save money by choosing cheap hosting from an unproven company, the appearance of problems is only a matter of time. You can secure your site as much as you can, but if the hosting is hacked, all your efforts will go down the drain. Look for services designed specifically for WordPress. As a rule they have WP CLI built in so that all your sites and the precautions on them are constantly updated. One of the most popular is WP Engine.

Conclusions

Never skimp on money for detecting, preventing and protecting sites. There are many solutions on the market that let you get rid of malicious code on your site. However, without proper precautions your site will be infected again and again. Removing malicious code from a site may not be the easiest process, and the more complex your site is (for example, if it is some commercial project), the more complex the process itself can be. Be sensible and always think several steps ahead. Paying 80 euros for a complete security solution for your site is much, much cheaper than spending a ton of time restoring and cleaning sites, let alone paying professionals to remove malicious code from your projects.

Take care of yourself and your sites!


Our specialization is WordPress website development and maintenance. Contact us for a free consultation — [email protected], +371 29394520