A plugin with a familiar name is not necessarily the plugin it claims to be.
A plugin folder you do not remember installing, named like a well-known plugin or like part of WordPress itself. A Hello Dolly that has grown extra code. A plugin that is active but does not appear in the list. Attackers who can write files install their backdoor as a plugin, because a plugin loads on every request and a plausible name gets left alone. This guide covers how to check every plugin against WordPress.org and the filesystem, recognise the impostors, and remove them without losing the evidence.
Prepared by G. Schad, WordPress and Linux security specialist
A plugin you did not install, a modified hello.php, or an active plugin missing from the list
Mechanism
A backdoor packaged as a plugin, named to be overlooked
Best test
wp plugin verify-checksums for plugins hosted on WordPress.org
Limit
Premium and custom plugins have no public checksums to compare against
What it looks like
The shapes an impostor plugin takes
A real plugin’s name on a site that never used it
A folder named like a popular plugin — a wp-polls folder on a site that never ran WP-Polls, for example — whose files are not that plugin’s code. The name is borrowed so the folder looks familiar in a listing.
A name that sounds like WordPress itself
Folders and plugin names built from words such as core, compat, helper, cache, security or update, so that they read as part of WordPress or the host rather than as a plugin somebody installed.
A modified hello.php
Hello Dolly ships with WordPress as a single file, wp-content/plugins/hello.php, and is rarely looked at. Code appended to it, or a hello.php that has been activated on a production site, deserves a read.
A single file with an encoded body
A plugin that is one PHP file — a valid header, then one long line of base64 or escaped text — is a loader with a plugin header on top.
A plugin that is not in the list
Code can remove its own entry from the Plugins screen with the all_plugins filter while staying active. The folder is still on disk and the plugin is still in the active_plugins option.
An activated plugin with no admin footprint
No settings page, no menu item, no description that matches what it does. Real plugins exist to be used; a backdoor exists to be left alone.
Where to look
How to check every plugin against WordPress.org and the disk
Start with the filesystem, because it cannot be filtered, then compare it with what WordPress reports. WP-CLI commands that load WordPress also run every active plugin, including the one under suspicion.
Figure 1 · Genuine or impostor
Six checks that separate a real plugin from one wearing its name.
Check
Genuine plugin
Impostor
Folder name
One you installed, matching its source
A real plugin’s name on a site that never used it
Plugin header
Author and URI of the real developer
Missing, copied, or pointing nowhere
verify-checksums
Passes, or premium with no checksums
Files differ, or no checksums for an .org name
Contents
Many readable files
One file, or one long encoded line
Timestamps
Install and update dates
Written inside the incident window
Plugin list
Listed with a settings page
Hidden, or listed with no footprint
What each check shows for a genuine plugin and for a backdoor packaged as one. No single check is conclusive; together they rarely leave doubt.
01
List the plugin folders with their dates
Every plugin folder and single-file plugin, with full timestamps:
shell
$ ls-la--time-style=full-iso wp-content/plugins/
A folder written inside the incident window, or one nobody on the team can name, goes on the list to read. index.php is the normal empty file.
02
Find the single-file plugins
PHP files directly in the plugins folder rather than in a plugin’s own folder:
shell
$ find wp-content/plugins -maxdepth 1 -type f -name'*.php'-ls
On most sites this is index.php and the bundled hello.php. Anything else is a single-file plugin and should be read in full.
03
Compare every plugin with WordPress.org
For plugins hosted on WordPress.org, this compares each file with the published release:
WP-CLI
$ wp plugin verify-checksums --all
A mismatch means files were changed. A plugin that WordPress.org has no checksums for is either premium, custom, or not the plugin its folder name suggests — check which.
04
See what is active, whatever the list shows
The active_plugins option is the record of what loads; the database query avoids loading the plugins themselves:
WP-CLI
$ wp db query "SELECT option_value FROM wp_options WHERE option_name = 'active_plugins'"
Replace wp_ with your table prefix from wp-config.php. An active entry that does not appear on the Plugins screen is being hidden.
05
Read the header of anything unexplained
The plugin header names the plugin, its author, and its home page:
A real plugin’s header matches its WordPress.org page or its vendor. A missing author, a URI that leads nowhere, or a header copied from another plugin is a fake.
06
Search the plugins for code that hides things
Filters that edit the plugin list or the user query:
Some legitimate plugins use these — multisite and white-label tools, for example. A match in a plugin you cannot name, especially beside encoded strings, is not legitimate.
Hello Dolly is the sample plugin bundled with every WordPress download, as the single file wp-content/plugins/hello.php. It does nothing a production site needs, which makes it a convenient host for appended code: the file name is familiar, it is often present on sites that have never activated it, and nobody reads it.
Read the end of the file, where appended code usually sits:
shell
$ tail-n 30 wp-content/plugins/hello.php
The genuine plugin prints a random line from the song in the admin area and nothing else. Anything that reads request data, decodes strings, writes files or adds users is not Hello Dolly. Whether or not you find anything, the simplest fix is to preserve the file and then delete it: no site depends on it.
Removing it
The order that makes the removal hold
A fake plugin is installed by something with write access to the site. Remove the plugin and that access together, after preserving it.
01
Preserve the plugin first
Copy the folder, with timestamps, outside the web root, and hash its files:
Note the folder’s creation time; it bounds the window everything else gets checked against.
02
Delete the folder, not just the activation
Remove the fake plugin’s folder or file entirely. WordPress drops a missing plugin from the active list the next time the Plugins screen loads, with a notice that it was deactivated.
03
Reinstall modified genuine plugins
For a real plugin that failed the checksum comparison, delete it and install a fresh copy from WordPress.org or the vendor. Do not repair it file by file.
04
Look at the users and the other layers
A fake plugin often creates or hides an administrator, and rarely works alone. Check the Users screen once the plugin is gone, and the layers listed below.
05
Rotate every credential the site holds
Control panel, SFTP, the database user, WordPress administrators and application passwords, and the keys and salts in wp-config.php — from a device that is not part of the incident.
06
Re-check after a few days
List the plugins folder again and repeat the checksum comparison. A plugin that reappears means something is still installing it.
What else to check
Where the rest of the infection usually is
A fake plugin is an activated backdoor; the same infection usually has unactivated ones too, and any of them can reinstall the plugin. In the ClickFix incident documented on this site, the chain lived in obfuscated PHP files, base64 content in the options table, the active theme’s functions.php, and a .user.ini startup directive at once.
Must-use plugins
Files in wp-content/mu-plugins load without activation and are invisible on the normal plugin list.
Drop-ins
advanced-cache.php, object-cache.php and db.php load before every plugin under names that look like infrastructure.
Rogue administrators
An account the fake plugin created can reinstall it through the admin area after every cleanup.
Edited roles
A tampered wp_user_roles option can give a low-privilege account the capability to install plugins.
For plugins hosted on WordPress.org, wp plugin verify-checksums compares every file with the published release and reports any that differ. For premium or custom plugins, compare against a fresh copy from the vendor or the developer. A plugin that is not on WordPress.org and that no vendor or team member can account for is not genuine.
wp plugin verify-checksums says it could not retrieve checksums. Is the plugin fake?
Not by itself. WordPress.org publishes checksums only for the plugins it hosts, so premium and custom plugins always give that result. It becomes a finding when the folder is named like a WordPress.org plugin — because then checksums should exist.
Should I delete Hello Dolly?
Yes, on a production site. It is a sample plugin with no function a site needs. Preserve a copy first if you are investigating an incident, in case code was added to it.
A plugin is active but does not appear on the Plugins screen. How?
Code can remove entries from the plugin list with the all_plugins filter, and a must-use plugin can hide the Must-Use tab. The active_plugins option and the plugins folder on disk cannot be filtered: compare them with what the screen shows.
Is deactivating the plugin enough?
No. A deactivated plugin stays on disk and its files can still be requested directly over the web, which is how many backdoors are used. Preserve it, delete it, and find what installed it.
My security plugin did not flag it. Why?
A fake plugin is new code rather than a modified copy of something known, so there may be no signature to match, and an encoded body is designed not to match patterns. The checksum comparison, the filesystem listing, and reading the header catch what signatures miss.