As part of our product lineup, we offer security monitoring and malware removal services to our Wordfence Care and Response customers. In the event of a security incident, our incident response team will investigate the root cause, find and remove malware from your site, and help with other complications that may arise as a result of an infection. During the cleanup, malware samples are added to our Threat Intelligence database, which contains over 3.65 million unique malicious samples. Our recently launched Wordfence CLI scanner detects 99% of these samples and indicators of compromise, when using the commercial signature set, and can scan your site even if WordPress is no longer functional.
Today, we would like to share a type of malware that serves as a sophisticated backdoor capable of performing a variety of tasks while masquerading as a real plugin. Complete with a professional looking opening comment implying it is a caching plugin, this rogue code contains numerous functions, adds filters to prevent itself from being included in the list of activated plugins, and has pinging functionality that allows a malicious actor to check if the script is still operational, as well as file modification capabilities. Additionally, it offers the ability to create an admin account, and remotely activate and deactivate plugins.
The sample was discovered during a site clean by one of our analysts on July 18, 2023. A signature was developed by the same analyst the following day and released to production within two weeks after undergoing testing. Customers still using the free version of Wordfence received this signature after a 30 day delay on September 1, 2023.
Analyzing the Sample
Due to the malware file being rather large in size, we can’t display the entire sample here and will focus on a few key parts instead.
Malicious User Creation
Since the malicious file runs as a plugin within the context of WordPress, it does have access to normal WordPress functionality just like other plugins do. The code above utilizes the wp_create_user function to create a new user account with the username superadmin and a hardcoded password, which we redacted to prevent abuse. The role of this user is set to administrator before displaying a short message via the _pln_json_die function to indicate that the task was performed successfully.
The following function, _pln_cmd_hide is intended to remove the superadmin account when it is no longer needed. This function is likely present for the attacker to remove traces and reduce the chances of detection once the victim has been successfully compromised.
While often seen in test code, user creation with hardcoded passwords should be considered a red flag, and the elevation of this user to an administrator is certainly reason enough for suspicion.
Bot detection code is often encountered in malware that serves normal content to some users while redirecting or presenting malicious content to other types of users. One common thread shared by these infection scenarios is that site owners find their site looks fine to them but their visitors have reported issues such as seeing spam or being redirected to dubious sites.
Others report that their site looks and behaves completely normally but only shows spam content when visiting from a search engine. Since this kind of malware wants search engines to find the malicious content, it is usually served to them as they index a site. Using keyword stuffing helps increase traffic sent to infected sites. Administrators often report a sudden, unexpected surge in site traffic when their sites are hit by an infection.
While the presence of bot detection code is not enough on its own to classify such a sample as malicious, it certainly is one of the factors that stands out in this piece of malware.
The plugin adds several filters. Two of them are shown below:
add_filter( ‘the_content’, ‘get_plugin_content’, 9999999, 2 );
add_filter( ‘the_page_content’, ‘get_plugin_content’);
When WordPress renders post and page content, the get_plugin_content function provided by the malware is invoked. This type of hook is often used to append disclaimers to posts or pages, manipulate excerpt lengths or inject other desired content into the post or page.
The above content replacement function performs an initial check to see if the currently logged in user is an administrator. If so, they will be shown the normal content. The filter is set to run as late as possible to override other filters, hence the priority of 9999999. Some other conditions are also checked to determine whether unmodified site content is to be served. If the malware determines that these conditions are not met, malicious content is assembled and displayed. Several other functions are invoked to insert spam links/buttons.
Plugin Activation and Deactivation
As mentioned above, the malware makes use of some WordPress functionality such as content filtering when running as a plugin. However, it also provides some remote control functionality that does not rely on it being activated. Instead, in some cases, it just simply includes the relevant files needed for the code to run successfully in the WordPress environment.
The code above can be used to activate and deactivate arbitrary plugins remotely. This is useful to disable unwanted plugins and also to activate this malicious plugin as needed. The malware contains other cleanup functions that allow it to remove malicious content from the database in addition to the admin user deletion we already discussed.
The following code is used to enable the malicious features of this backdoor:
The _pln_is_colonel function checks for the presence of a particular user agent string that is needed in order to control features of this backdoor. If the parameter is present, several $_REQUEST parameters will be checked and, if set, their corresponding functions are executed.
Taken together, these features provide attackers with everything they need to remotely control and monetize a victim site, at the expense of the site’s own SEO rankings and user privacy.
In today’s post we presented a backdoor, with features that allow it to work as a standalone script and as a plugin. Remote plugin activation and admin user creation and deletion as well as conditional content filtering allow this backdoor to evade easy detection by the inexperienced user.
Our Premium, Care, and Response users are protected by our malware scanner during file uploads against the upload of this sample as well as many of its variants, and are also protected by our layered approach which uses several other rules that also protect our free users. This means that Wordfence will block any attempts by attackers to compromise a WordPress site by uploading this file. Properly configured scans running on sites with Wordfence Premium, Wordfence Care, and Wordfence Response will also detect this sample in the unlikely event it is uploaded to a site during an infection.
It’s important to remember that detection of a compromise is just as important to security as ensuring your site remains protected. By using the Wordfence plugin, and ensuring it has been optimally configured along with following security best practices, you’re ensuring your site remains as protected as possible. Nothing can ever be 100% secure, and risk can never fully be mitigated, so it’s important to have monitoring on your site in the event your site is still compromised despite following all best practices. The Wordfence scanner will alert you to any infections so you can initiate an incident response, and also block malicious malware uploads in the event an attacker gets past a site’s first line of defense.
If you believe that your site might be infected, you can enlist the help of our Incident Response team by purchasing our Care, or Response offering or follow this guide to remove the infection yourself.
If you have a malware sample that was missed during a Wordfence scan, please let us know by sending the sample to us at firstname.lastname@example.org.