We all know why bad actors infect sites: monetary gain, boosts in SEO ratings for their malware or spam campaigns and a number of other reasons explained in our post on hacker’s motivations.
It defeats the purpose of the attack if the malware is easily and quickly removed. However, attackers have developed some methods for protecting their work: they make it easy to reinfect websites after the initial compromise.
In this post, we’ll explore ways to help you remove malware infections that immediately reinfect the target website through the use of malicious processes. We’ll also look at the steps you can take to remove this infection from a compromised website.
What does reinfection malware look like?
In many cases, we find a modified index.php on the compromised website like this:
Example of an infected index.php file that automatically re-generates itself through a malicious process running in the background
It doesn’t matter if your site is on WordPress or not: the attackers will usually replace the index.php with an infected copy of a WordPress index.php file.
We also often find hundreds (or sometimes thousands) of infected .htaccess files scattered throughout the website directories. This is designed to prevent custom PHP files or tools from running on the site or to allow the malicious files from running in case there’s some mitigation already in place.
Example of an infected .htaccess file which interferes with the ability to run most PHP scripts
In rare circumstances, the attackers will leave a copy of the original index.php file on the server named old-index.php or 1index.php that we can rename back to index.php. In most cases, the infected files will have been changed to 444 permissions and attempting to remove or clean those files directly is unsuccessful since the malware will immediately create a new infected copy.
How to clean up PHP reinfection malware
1 – Look for malicious processes like about.php, lock360.php or radio.php
As we saw from the infected .htaccess, the attackers have created a list of files allowed to run on the server: about.php, radio.php, lock360.php, etc, which prevent any other PHP files from loading.
These files will usually not exist on the server but instead run as malicious processes. The persistent, running processes on the server are what allows the malware to automatically and immediately reinfect the site once the infection is removed.
2 – Look for all running PHP processes and stop them
Once you’ve found the culprit, you’ll want to stop the malware from running. Create a file from one of those names and add the following content.
For example, if you’ve found radio.php running:
<?php echo shell_exec("ps aux | grep -i php | awk {'print $2'} | xargs kill -9") ?>
Note: The file name must match one of those listed in .htaccess as those are the only files that are allowed to run on the server. This will ensure our command is successfully run.
The contents of this file will look for all running PHP processes and attempt to stop them.
3 – Load the file in your browser
Next, load your new file in the browser.
hxxps://yourwebsite[.]com/radio.php
You won’t see any content in the browser but if the process was successful, you should be able to rename or delete .htaccess and index.php without seeing a new infected copy being created. If you are not able to access the file you created, you will need to proceed with the SSH steps below.
It is important to note that some malware may not re-create the infected files immediately, and you will want to load your site a couple of times, checking for the reinfected files after each attempt.
Once you have confirmed that the files are not going to return, you will need to remove the remainder of the infection.
4 – Check for persistence via WordPress core files
If the malware is still present, it is possible that the re-infector exists somewhere in the core WordPress files.
One method we frequently see is a modified wp-includes/plugin.php file designed to re-create the index.php and .htaccess:
Reinfector malware placed within the WordPress core files
After removing that content, the index.php and .htaccess should be unlocked and you can proceed with cleaning those files along with the remainder of the infection. Though plugin.php is a common point of attack, we have seen similar code on other core files.
One option you have is to replace all of the core site files with fresh copies, and to reinstall your themes and plugins. Some reinfectors are heavily obfuscated and are designed to remain well hidden. It is also not uncommon for the attackers to upload fake plugins to the wp-content/plugins directory that will not be visible from wp-admin.
5 – Proceed via SSH
If previous attempts to clean the infected index.php or .htaccess have been unsuccessful, you may need to gain SSH access or load a CPanel terminal to check running processes.
Run the top command (and press the ‘c’ key to expand the output) or “ps -aux” and look for anything strange there.
Often these cases will reveal something like this:
wp-content/uploads/2021/lock360.php
Or this:
wp-includes/l.php
In this case, we can see the process running with PID 664739 and we can kill that process.
If the offending process was responsible for recreating index.php, you should be able to rename the file without seeing a new copy dropping in, and you should be able to proceed with cleaning the remainder of the infection.
6 – Deal with memory-based malware
In rare cases, the malware will reside in php-fpm memory. If index.php is still being re-created after the above steps have been completed, run top and check for the presence of php-fpm.
PHP-FPM processes running on a server
Though this usually will not correct the problem, you can attempt to clear OPCache. Create a file in the site’s document root named opcache.php:
<?php if(function_exists("opcache_get_status") && is_array(opcache_get_status())) { if (opcache_reset()) { echo "OPCache has been cleared."; } else { echo "OPCache could not be cleared."; } } else { echo "OPCache is not available"; }
OPcache improves PHP performance by storing pre-compiled script bytecode in shared memory, thereby removing the need for PHP to load and parse scripts on each request. Because of this, malware can persist in OPcache after being cleaned from the site files or database.
You can then test that in the browser and this should attempt to flush the OPcache:
hxxp://yourwebsite[.]com/opcache.php
If OPcache is not enabled, or clearing that did not fix the issue, php-fpm will need to be restarted. You may need sudo access to re-start the service. However, if there are multiple sites on the server then they will all need to be cleaned, otherwise they will likely reinfect each other.
Please note that restarting the service will break all active sessions in all sites – there isn’t any way to target a specific php-fpm pool for these purposes. Restarting php-fpm will also depend on the Linux distribution in use and the specific name/version of the service.
If the malware is still there, reach out to us. We can help investigate further.
Conclusion
Though attackers are always looking for new ways to infect sites, there are some common steps you can take to minimize those infections.
- Put your website behind a Firewall.
- Regularly change all admin passwords associated with your site. This includes the admin dashboard, CPanel/FTP, ssh and email. You can check out our post on the process of creating secure passwords.
- Keep all plugins, themes and your CMS up to date at all times.
- Remove any unneeded plugins or themes – attackers are always exploiting new and undiscovered vulnerabilities.
And if you’re struggling to remove the infection or you have some persistent malware that keeps coming back to haunt your site, our experienced analysts are available 24/7 to help remove website malware and keep your site protected.