Skip to main content

Recovering from the self-healing WordPress infection

Written by Salvador Aguilar

If one WordPress site in your hosting account was infected, treat every site in that account as compromised until proven otherwise. This infection is built to reinstall itself from multiple hiding places at once β€” including your browser β€” so a partial cleanup doesn't hold.

For site owners, admins & agenciesDo this on every site on the hosting account

⚠️ Cross-site contamination is the point of this guide.

On shared hosting, this malware actively scans for sibling WordPress installs under the same account and copies itself into every one it finds. Cleaning your main site while an old side project three folders over stays infected just gives it a way back in. Repeat every step below on each WordPress install you control on that hosting account, not just the one that showed symptoms.

1. Review admin users, then rotate every password

A large share of these infections start with stolen, reused, or leaked credentials β€” not a code exploit. Passwords harvested in unrelated breaches get tried automatically, in bulk, against thousands of WordPress logins until one matches. If any admin on this site reuses a password that's ever appeared in a public breach, this is likely how the door was opened.

  1. Go to Users β†’ All Users and filter by role. Look specifically at everyone with Administrator β€” that's the role attackers create for themselves.
    ​

  2. For each admin, ask: do I know this person, and do they still need full admin access? Remove or demote anyone you can't account for, anyone who left the team, and anyone who only ever needed to publish posts.
    ​

  3. Reset the password for every admin account that remains β€” not just the one you suspect was compromised. Open each user's profile, scroll to Account Management, and click Generate Password rather than typing your own; use a password manager to store a unique, 20+ character password per site.
    ​

  4. Do the same for Editor and Author accounts if the site accepts public registration or has ever had a support/contractor account added.

Illustrative mockup of the Users screen β€” not a screenshot of your actual site.

This infection also hides admin accounts from the Users screen. Researchers have observed rogue accounts (patterns like admin_a1b2, adm_9f3e) that are filtered out of the visible user list and recreated automatically by a scheduled task if deleted through the UI. If your visible admin count doesn't match what your host or a database tool (phpMyAdmin, WP-CLI's wp user list) reports for the wp_users table, there's likely a hidden account β€” that discrepancy is worth escalating to your host or a malware-removal specialist rather than working around it yourself.

2. Rotate your security keys (salts)

The eight security keys in wp-config.php are what WordPress uses to sign login cookies. Changing them invalidates every active session on the site instantly β€” your own, your team's, and any attacker's β€” even a session built from a cookie stolen days ago that hasn't expired yet.

  1. Open WordPress.org's official secret-key generator and copy the eight lines it returns.

  2. Open wp-config.php through your host's file manager or SFTP.

  3. Find the block of eight define('...KEY'...) / define('...SALT'...) lines and replace the whole block with the new one you generated.

  4. Save the file. Everyone β€” including you β€” will be logged out of wp-admin immediately. That's expected; log back in with your newly reset password.

// wp-config.php
define('AUTH_KEY', 'NEW-9k2j...');
define('SECURE_AUTH_KEY', 'NEW-p03m...');
…6 more, all freshly generated…

❓ No file access? Several web hosting providers expose a one-click "regenerate keys" or "change security keys" option in their own dashboard β€” check there first if sFTP isn't available to you.
​
If you have SSH access and WP-CLI is available you can easily run this command:


​wp config shuffle-salts

3. Audit Application Passwords

Application Passwords are a separate credential system WordPress uses for the REST API and third-party integrations β€” a mobile app, a form plugin, a publishing tool. They live outside your normal login password, don't rotate when you reset it, and are easy to overlook during cleanup.

  1. Go to Users β†’ Profile (your own account) and open every other admin's profile in turn. Scroll to Application Passwords.
    ​

  2. Review the list: name, date created, last used, last IP. Revoke anything you don't recognize, anything unused for months, and especially anything with a random-looking name.
    ​

  3. For integrations you do recognize and still use, revoke the existing entry anyway and generate a fresh one β€” the old value can't be viewed again, so you'll need to paste the new password into that app or plugin's settings.

Illustrative mockup of the Application Passwords panel.

Check this after you've dealt with hidden admin accounts (step 1). An application password tied to a rogue account you haven't found yet won't show up here until that account itself is exposed.

4. Put a CAPTCHA on your login form

Credential-stuffing tools work by trying thousands of leaked username/password pairs against your login form automatically. A CAPTCHA breaks that automation β€” it doesn't need to stop a determined human, it just needs to stop a script.

Some popular plugins are:

5. Turn on two-factor authentication

A CAPTCHA stops bots; 2FA stops humans who already have a valid password. It's a second, independent layer: even if a password leaks again in some future breach β€” or an admin reuses one out of habit β€” login still requires a code from a device the attacker doesn't have. Rotating passwords fixes today's breach; 2FA limits the damage of the next one.

  • Two-Factor - Maintained by WordPress core contributors; TOTP, email codes, backup codes
    ​

  • WP 2FA - Policy-based rollout β€” can require 2FA for all admins
    ​

  • miniOrange 2FA - OTP via SMS, email, or authenticator app

  1. Install one plugin and require it for every Administrator and Editor account at minimum.

  2. Have each admin pair an authenticator app (Google Authenticator, Authy, 1Password) rather than relying on email codes alone, and save the printed backup codes somewhere offline.

6. Clean the reinfection out of your browser

This is the step that gets skipped, and it's the one that causes sites to reinfect right after they've been declared clean. The malware registers a Service Worker β€” a small background script your browser keeps running for the site's domain, independent of cookies or cache. It can silently re-upload the malicious plugin using your still-open admin session the next time you visit wp-admin, even on a server that's otherwise spotless. Every admin, on every browser and device they've used to log into this site, needs to do this.

Illustrative mockup of the browser DevTools Service Workers panel.

Chrome / Edge (Chromium)

  1. Visit the site, then open DevTools (F12 or right-click β†’ Inspect).

  2. Go to the Application tab β†’ Service Workers in the left sidebar.

  3. Click Unregister next to any entry for the site's domain.

  4. Still in Application, open Storage β†’ Clear site data to remove cached files, IndexedDB and local storage the worker may have used to reinstall itself.

Firefox

  1. Go to about:debugging#/runtime/this-firefox and find the site under Service Workers.

  2. Click Unregister.

  3. Then go to Settings β†’ Privacy & Security β†’ Cookies and Site Data β†’ Manage Data, search for the domain, and remove it.

Safari

  1. Enable the Develop menu if it isn't visible: Safari β†’ Settings β†’ Advanced β†’ Show features for web developers.

  2. Open Develop β†’ [your Mac name] β†’ yoursite.com and use the Storage panel to unregister its service worker, or simply choose Develop β†’ Empty Caches.

  3. Then go to Safari β†’ Settings β†’ Privacy β†’ Manage Website Data, search for the domain, and click Remove.

⚠️ Repeat this on every device an admin has logged in from β€” phone, laptop, a second browser profile. A single missed browser is enough to trigger a reinstall.

7. Apply the principle of least privilege

Give every account, integration and credential the minimum access it needs to do its job β€” nothing more. It doesn't stop the first compromise, but it caps the damage: a stolen Author password can't create rogue admins, and a leaked Application Password scoped to one plugin can't touch the rest of the site.

Who

Default role

Not

Writers / marketing

Author or Contributor

Administrator

Agency / contractor, project-only

Editor, time-boxed

A permanent admin account

A plugin or third-party app

Its own low-privilege user + scoped Application Password

Your personal admin's credentials

True site administrators

The smallest number that can still run the site

Everyone on the team, by default

Keep hosting-panel and SFTP credentials separate from WordPress admin logins, and never reuse a password across sites β€” even ones you own. One leaked site shouldn't be a key to the rest of your hosting account.

8. Stay clean going forward

  • Keep WordPress core, themes and plugins updated β€” enable automatic updates for anything you trust to update safely.
    ​

  • Delete unused plugins and themes entirely; don't leave them deactivated on disk.
    ​

  • Add define('DISALLOW_FILE_EDIT', true); to wp-config.php to block plugin/theme editing from wp-admin.
    ​

  • Implement a RASP solution such as ThreatShield to filter malicious requests at their run time.
    ​

  • Take regular offsite backups and actually test that you can restore one.
    ​

  • Run ongoing malware and file-integrity monitoring rather than a one-time scan β€” this family is built to come back, and dedicated protection like Monarx's Agent and ThreatShield is designed to catch reinfection attempts at the file and runtime level.
    ​

  • Confirm you've repeated steps 1–6 on every WordPress site in the hosting account β€” not only the one that first showed symptoms.
    ​

  • If anything here turns up more than you can confidently clean yourself, a professional cleanup is cheaper than a repeat infection.

Based on Monarx's research into the self-healing WordPress infection β€” read the full technical report. Screens shown in this guide are illustrative mockups, not screenshots of any specific site.

Did this answer your question?