How to Find WordPress Backdoors: Where Malware Hides
Where WordPress malware hides and how to find backdoors: uploads, mu-plugins, core files, rogue admins, the options table, cron jobs and .htaccess rules.
To find WordPress backdoors, check the places attackers know site owners rarely open: PHP files in the uploads folder, must-use plugins, modified core files, hidden administrator accounts, the database options table, scheduled tasks and .htaccess rules. A backdoor is what lets an attacker return after you clean the visible damage, so missing one usually means a second infection.
This guide lists where to look and how to check each spot. It is meant for site owners and developers cleaning up their own sites. If you have only just discovered the hack, start with our guide to what to do in the first hour after a WordPress hack, and take a full copy of the site before you change anything.
Before you start: work from a safe position
A few ground rules make the search more reliable.
- Work on a copy when you can. Download the files and database and inspect them on a separate machine or a local test site. Infected code cannot interfere with what you see there.
- Do not trust the WordPress dashboard. Malware can hide users, plugins and files from admin screens. Look at the files and the database directly.
- Run WP-CLI without plugins and themes. WP-CLI is the official WordPress command-line tool. Adding
--skip-plugins --skip-themesto commands stops infected plugin or theme code from loading while you inspect the site. - Compare against known-good copies. The fastest way to spot bad code is to compare a file with the original from WordPress.org, the plugin vendor, or your version control.
1. Modified WordPress core files
WordPress core is the same everywhere for a given version, so changes are easy to detect. WP-CLI can check every core file against the official checksums published by WordPress.org:
wp core verify-checksums --skip-plugins --skip-themes
The command reports files whose contents do not match, and warns about extra files found inside core folders. Add --include-root to also flag unexpected files in the site’s root folder. See the verify-checksums documentation for all options.
Two files are not covered by this check and deserve a manual look: wp-config.php, which is unique to your site, and the root index.php if your setup customizes it. In wp-config.php, look for anything above the opening comment block, long lines of unreadable text, or include and require lines pointing to files you do not recognize.
2. Plugins and themes
The same idea works for plugins from WordPress.org:
wp plugin verify-checksums --all --skip-plugins --skip-themes
This only works for plugins hosted on WordPress.org. Premium plugins and custom code need a different approach: download a fresh copy of the same version from the vendor and compare the folders, or check them against your Git repository.
While you are in the plugins folder, look for:
- Plugin folders that do not appear in your plugin list, or that have generic names.
- Plugins you did not install, especially ones with no readme file or author details.
- Themes you do not use. Inactive themes still contain PHP files that can be requested directly, so delete any theme you do not need.
3. PHP files in the uploads folder
The wp-content/uploads folder is meant for images, PDFs and other media. In a normal site it should contain almost no PHP files. That makes it one of the first places to check:
find wp-content/uploads -type f -name "*.php"
Check every result. A few plugins do place small PHP files there, often a blank index.php to block folder listings, but anything with real code needs a close look. Also check for files with double extensions, or image files that are much larger than they should be.
As a preventive step, you can block PHP from running in the uploads folder at the server level. Our WordPress security hardening checklist covers that.
4. Must-use plugins
Must-use plugins live in wp-content/mu-plugins. WordPress loads them automatically, they cannot be turned off from the dashboard, and they appear on a separate, easy-to-miss tab of the Plugins screen. That makes the folder a favorite hiding place.
ls -la wp-content/mu-plugins
Many hosts add their own must-use plugins, so not every file here is a problem. Ask your host which files they install, and investigate the rest.
5. Recently changed files
Attackers often add or change files around the time of the attack. Listing PHP files changed in the last few days can narrow the search:
find . -type f -name "*.php" -mtime -7
Keep two limits in mind. Updates change many files legitimately, so expect noise. And file dates can be faked, so a file that looks old is not proven clean.
6. Suspicious code patterns
Some PHP functions show up again and again in malware, because they let code decode and run hidden instructions. A text search can surface files worth reading:
grep -rlE "eval\(|base64_decode\(|gzinflate\(|str_rot13\(" wp-content --include="*.php"
Treat the results as leads, not proof. Legitimate plugins use some of these functions too. What stands out in malware is the combination: long strings of meaningless characters, decoding functions stacked inside each other, and code that runs whatever arrives in a request.
7. Rogue administrator accounts
A hidden admin account is the simplest backdoor of all. List every administrator, with plugins and themes skipped so nothing can filter the list:
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered --skip-plugins --skip-themes
Look for accounts you do not recognize, generic names, email addresses on odd domains, and registration dates close to the attack. Also check:
- Users with other roles who were given admin capabilities.
- Application passwords, which let a user log in to the WordPress REST API without their main password. You can list them with
wp user application-password list <user>. - Accounts in your hosting panel, SFTP users and database users, not just WordPress users.
8. The database: options, posts and widgets
Not all malware lives in files. Attackers also store scripts and settings in the database, where file scanners never look.
The options table
The options table (wp_options by default, though your prefix may differ) holds site settings. Check these first:
wp option get siteurl --skip-plugins --skip-themes
wp option get home --skip-plugins --skip-themes
wp option get active_plugins --skip-plugins --skip-themes
The site address should be yours, and the active plugin list should match what you expect. Then look for options with random-looking names or very large values that no plugin explains. Our guide to cleaning up a bloated WordPress database shows how to find the largest options, which is also useful here.
Posts, pages and widgets
Injected JavaScript often sits inside post content or text widgets, where it loads spam or redirects visitors. WP-CLI can search the database for script tags and external domains:
wp db search "<script" --stats --skip-plugins --skip-themes
Expect some legitimate results, such as tracking codes or embedded forms. Look for scripts loading from domains you do not use.
9. Scheduled tasks
WordPress has its own scheduler, called WP-Cron. Attackers use it to recreate deleted files or users on a timer. List all scheduled events:
wp cron event list --fields=hook,next_run_relative,recurrence --skip-plugins --skip-themes
Most hooks will have names that match your plugins. Investigate any that do not. Also check the server’s own scheduled tasks for your hosting user, with crontab -l over SSH or in your hosting control panel.
10. .htaccess and server configuration
On Apache servers, .htaccess files control redirects and how files are handled. The WordPress.org hacked site FAQ calls it one of the files most often changed during an attack. Check every copy, not only the one in the root folder:
find . -name ".htaccess"
Warning signs include redirects that only apply to mobile visitors or to people arriving from search engines, rules that send traffic to outside domains, and rules that allow PHP to run in the uploads folder. Also look for .user.ini or php.ini files that set auto_prepend_file, which makes a file run before every page load.
After you find a backdoor
Finding one backdoor is not the end. Attackers usually leave several, so that cleaning one does not lock them out. Keep going through every section above, then:
- Replace core, plugins and themes with clean copies instead of editing infected files.
- Change every password and replace the secret keys in
wp-config.php. - Find and close the original entry point, usually an outdated or abandoned plugin.
- If Google flagged the site, follow our guide to removing the Google dangerous site warning.
Outdated plugins are the most common entry point we find. Keeping track of them is part of measuring WordPress technical debt, and it is far cheaper than another cleanup.
Need a second pair of eyes?
Backdoor hunting is slow, careful work, and one missed file can undo it. If you want it done for you, our WordPress malware removal service covers the full search, cleanup and root-cause report, with a fixed quote after a short assessment. Get in touch and tell us what you are seeing.
Frequently asked questions
- What is a WordPress backdoor?
- A backdoor is hidden code or a hidden account that lets an attacker get back into your site after you clean it. It is usually small, disguised as a normal file, and placed somewhere people rarely look.
- Can a security plugin find all backdoors?
- No. Scanners catch many known patterns, but they miss new, custom or well-disguised code, and malware can interfere with scanners that run inside WordPress. Use a scanner as one check alongside the manual checks in this guide.
- Why does my WordPress site keep getting reinfected?
- Usually because a backdoor survived the cleanup, or the original entry point was never closed. Common causes are a leftover file in uploads, a must-use plugin, a hidden admin user, or an outdated plugin that is still vulnerable.
- Is it safe to delete files I do not recognize?
- Take a full copy of the site first, then check each file before you delete it. Some odd-looking files belong to caching or security plugins, and deleting the wrong file can break the site.