pixelgravitas
Report a Hack

Home/Case Studies/WordPress backdoor cleanup

Case study · Hacked-site cleanup

WordPress backdoor cleanup: nine hidden shells and seven fake admins, on a site that looked fine.

Short answer: db89foundation.com, a WordPress site, had a backdoor in three places at once: nine PHP files that gave an attacker control of the server, seven administrator accounts they had created for themselves, and a login token stored in the database. A first scan missed every one of the files. Comparing each file against WordPress.org's official copies found all nine. This is what we found, how we found it, and the order we removed it in.

Hidden files9web shells and loaders, none caught by the first scan
Fake admins7created over four days with no admin logged in
Unnoticed~7 weeksfrom the first fake admin to discovery
Core now3,338files checked, every one matching WordPress 7.1.3

At a glance

Three backdoors,
in three different places.

db89foundation.comCase file
PlatformWordPress 6.8.2 (out of date) on PHP 7.4.33, which no longer gets security fixesExposed
FilesNine PHP backdoors in the site root and deep inside wp-includesFound
AccountsSeven administrators the owner never createdFound
DatabaseA login token and a pointer to one of the fake adminsFound
Found byComparing every file with WordPress.org's official checksumsLocated
Now3 of 10 cleanup steps confirmed done; the full list is belowIn progress

What we found in the files

Nine files that
shouldn't have existed.

None of these were plugins or themes, so nothing in the WordPress dashboard showed them. Each one was named to look ordinary.

WhereWhat it didWhy it was hard to see
db.php in the site rootA loader for Japanese SEO spam. It fetched its instructions from a remote server (j250811_13.qlebsack.com), showed spam pages to Google while the owner saw a normal site, could redirect visitors arriving from Japanese Google results, could rewrite robots.txt, and copied itself into two genuine WordPress admin files so it would survive being deleted.Wrapped in 15 layers of compression and encoding, padded with junk functions.
mass.php in the site rootA “mass file uploader”: a web page for uploading any file to the server.13 layers of the same wrapping.
Seven files in wp-includes/js/dist/script-modules/interactivity/Seven copies of the ALFA web shell, which gives full control of files, the database and the server from a browser. A rogue .htaccess sat beside them.Named about.php, index.php, wp-login.php and alfa-rex with odd extensions (.php7, .php56, .PhP7), inside a folder that normally holds only JavaScript.

The two admin files db.php wrote itself into were wp-admin/tools.php and wp-admin/includes/class-wp-debug-data.php. That is a common trick: delete the loader, and the copy in a file you'd never think to check puts it back. Replacing WordPress core with an official copy removes both at once, which is why core was replaced rather than repaired.

Nothing here was in a plugin. Every plugin downloaded from WordPress.org still matched its official release exactly. The attacker didn't need to change plugins, because they could write files anywhere.

What we found in the database

Two more ways back in
that no file scan sees.

Deleting files doesn't touch the database. These would have let the attacker back in even after a perfect file cleanup.

Seven fake administratorsCreated between 17 and 20 August 2026, with no administrator signed in before any of them, so code made them, not a person at the login screen. The tell-tale signs: machine-looking usernames, email addresses on random domains or at wordpress.org, and one address made to look like the owner's.
A stored login tokenTwo entries in the wp_options table: sso_token, and _wp_user_id, whose value was the ID of one of the fake admins. Neither belongs to WordPress or to any plugin on the site. On their own they do nothing; together with planted code they are a key to sign in as that admin.

A database row can't run by itself, so once the files were gone the token was inert. It was removed anyway: if the attacker ever got code back onto the site, a ready-made login would be waiting for them.

To look for the same thing on your own site, this query lists the two names we found, any option holding code-like content, and any option whose whole value equals a user ID. Change wp_ if your tables use another prefix. A few harmless matches are normal; on a hacked site the last line is what gives the game away.

SELECT option_name, LEFT(option_value, 80) AS value, autoload
FROM wp_options
WHERE option_name IN ('sso_token', '_wp_user_id')
   OR option_value REGEXP 'eval\\(|base64_decode|gzinflate|str_rot13'
   OR option_value IN (SELECT ID FROM wp_users);

Why the first scan missed it

Looking for bad code
versus checking for good code.

1

Pattern scan: wrong files

The first scan searched every file for known malicious code. It flagged harmless library files inside plugins as critical, and found none of the nine shells. Code wrapped in 15 layers has no fixed pattern to search for.

2

Checksums: all nine

WordPress.org publishes a fingerprint of every core file for every release. Comparing each file on the site against that list turned up every extra file in the core folders and every changed one, without needing to recognise the malware at all.

3

Plugins: cleared

The same check against WordPress.org's plugin checksums showed the flagged library files were identical to the official releases, so they were cleared instead of being deleted and breaking the site.

Our scanner was rebuilt around this on 8 October 2026, the day after we first looked at the site. Run against a copy of it, the new check flagged all nine files as critical and left genuine WordPress files alone.

One more thing this caught: the first attempt to replace core copied the new files over the old ones but left the file that records the version number behind, so WordPress still believed it was 6.8.2. The comparison reported 270 files from 7.1.3 on a site claiming 6.8.2, labelled them genuine code rather than malware, and a proper update from the dashboard finished the job. The scan after that: all 3,338 core files match WordPress 7.1.3, no files added to core folders, no malware signatures.

The cleanup, in order

Files first, then everything
a file cleanup leaves behind.

The order matters. Delete the fake admins while a shell still exists and the shell can make new ones; reset passwords before the sessions are cleared and a stolen session keeps working.

Cleanup status3 of 10 done
Web shells and loadersAll nine files deleted: db.php, mass.php and the seven shell copies, plus the rogue .htaccess beside them.Done
WordPress coreReplaced with an official 7.1.3 release and checked: all 3,338 core files match, nothing added to core folders.Done
Backdoor login tokenThe sso_token option removed from the database.Done
Fake administratorsSeven attacker-created admin accounts deleted, with their content reassigned to a real user.Planned
Linked optionThe _wp_user_id option, which pointed at one of the fake admins, removed.Planned
File managersAll three file-manager plugins removed: the two the attacker added, and the one installed earlier for maintenance. File work now goes through the hosting panel instead.Planned
Unlicensed builder copiesTwo old copies of a premium page builder, one downloaded from GitHub, replaced with a licensed release or removed.Planned
Passwords and sessionsEvery real user's password reset, all sessions and application passwords cleared, and WordPress's secret keys (salts) rotated.Planned
PHP versionMoved from PHP 7.4, which no longer gets security fixes, to PHP 8.2 or 8.3.Planned
GoogleSearch Console checked for security issues and pages we didn't write; a review requested if anything was flagged.Planned

“Planned” means agreed with the site owner and not yet confirmed finished. We update this page as each step is confirmed, rather than marking the whole job done in advance.

How they got in

Not proven, so every
open door gets closed.

The security plugin on the site had stopped recording events long before the attack, so there was no log of the first break-in. We don't know for certain which door was used, and we won't pretend to. What we do know is which doors were open:

A file-manager pluginOne had been installed earlier for maintenance. A plugin like this can upload and edit any file from the browser, so an old version with a known hole, or anyone who gets an admin login, can use it to plant a shell. It is the most likely way in.
Out-of-date WordPressCore was on 6.8.2 while newer releases with security fixes were available.
Unlicensed premium codeTwo old copies of a premium page builder, one a “-main” folder downloaded from GitHub. Copies like these get no security updates and are a common way malware arrives.
An unsupported PHP versionPHP 7.4.33 stopped receiving security fixes at the end of 2022.

Two more file-manager plugins appeared after the break-in, installed by the attacker. That's a common move: if one way back in is found and removed, the others still work. The lesson for any site: a file manager left installed is a door that never closes. Use the host's file manager or SFTP, and remove the plugin when the job is done.

Check your own site

Six checks that would have
caught this weeks earlier.

None of these need special tools. If any of them turns something up, don't delete it straight away: take a copy of the files and database first, so there's a record of what was there.

Count your administratorsUsers → filter by Administrator. Every account should be someone you can name.
Look in the site rootYour hosting file manager. Anything ending in .php that isn't a WordPress file (wp-*.php, index.php, xmlrpc.php) needs a reason to be there.
Look where PHP shouldn't bewp-includes/js, wp-includes/css and wp-content/uploads should contain no PHP files at all.
Verify coreIf you have WP-CLI, run wp core verify-checksums. It compares every core file with the official release.
Search Google for yourselfSearch site:yourdomain.com and scroll past the first page. Pages you never wrote are the spam a loader like db.php serves.
Run the options queryThe query above takes seconds in phpMyAdmin and finds the kind of database entry a file scan never will.If you think you're hacked →

If you'd rather not do this yourself, our WordPress malware removal service covers exactly this work, files, accounts and database, with a fixed quote before anything starts. See pricing →

More case studies

See all →

Questions, answered

WordPress backdoors:
common questions.

What is a WordPress backdoor?

A WordPress backdoor is code or an account an attacker leaves behind so they can get back in after you've changed your password or deleted the obvious malware. It can be a PHP file, a few lines added to a genuine file, a hidden administrator, or a value in the database that some other code reads.

How do I find a backdoor in WordPress?

Compare your files against the official copies instead of reading them. WordPress.org publishes a checksum for every core file and for every version of the plugins it hosts. Any file that doesn't match, or that shouldn't exist at all, is the shortlist. Then check every administrator account and search the options table for values that look like tokens, user IDs or encoded code.

What is a web shell?

A web shell is a PHP file that gives whoever opens it in a browser control of the server: browsing and editing files, uploading more, running commands and changing the database. The ALFA shell found on this site is a common, heavily obfuscated example.

Why didn't my security plugin find the malware?

Pattern-based scanners look for known pieces of malicious code. Shells like these are wrapped in many layers of encoding and junk code, so there is no fixed pattern to match. Comparing files against official checksums doesn't need to recognise the malware, only to notice that a file isn't the one WordPress shipped.

How do hackers create admin users in WordPress?

Usually through code they've already planted, not through the login page. A shell or loader can write a new administrator straight into the database. On this site, seven admin accounts appeared over four days with no administrator logged in beforehand, which is the sign they were created by code.

Is it enough to delete the malicious files?

No. Fake admin accounts, stolen passwords, valid session cookies, application passwords and values left in the database all survive a file cleanup. Each is a way back in. A cleanup isn't finished until every one is removed or reset and the way in is closed.

What does the Japanese keyword hack have to do with a backdoor?

The loader on this site, db.php, was built to serve Japanese spam pages to Google while showing the owner a normal site. The spam is what attackers sell; the backdoor is what keeps them in. We cover a spam-page cleanup in detail in the Wone8 Estates case study.

Can a hacked WordPress site be cleaned without a backup?

Yes. This one was. Core was replaced from an official release and verified file by file, and the database was cleaned in place. A backup from before the infection is useful, but many backups already contain the backdoor, because infections often sit quietly for weeks.

How long can a backdoor go unnoticed?

Weeks or months. On this site, the first fake administrator was created on 17 August 2026 and the compromise was found in the first week of October, about seven weeks later. The security plugin on the site had stopped recording events long before that.

Start here

Accounts or files on your site you didn't put there?

Send the URL. We'll check it from the outside and tell you what the cleanup involves, in writing, before any work starts.

  • 1We check the live site the way visitors and Google see it.
  • 2You get written findings and a fixed quote for the cleanup.
  • 3You decide. Nothing starts until you say yes.

Report a hacked site

Three fields on purpose. We reply within one business day, and we don't add you to a mailing list.

Report a hacked site