Inside a Real WordPress Malware Cleanup: A Hidden JavaScript Injection, and How We Traced It Back to a Single Stolen Password

Worried Your WordPress Site May Be Compromised?

Request a Security Review
WordPress Malware Case Study

Most articles about WordPress malware are written from a safe distance. This one isn’t. Over the past few weeks our team at Group Fractal worked through a live malware campaign that hit several WordPress sites we manage, and we want to share exactly what we found, how the attack was built to avoid detection, and the step-by-step way we cleaned it up. Some of these sites looked completely normal to their owners the entire time they were infected. That is the part worth paying attention to.

If you run a WordPress site, you are not an unusual target. According to Sucuri’s 2023 Hacked Website Report, WordPress made up 95.5% of all the infections their team cleaned that year, well above its share of the CMS market, and the vast majority of those compromises trace back to the surrounding ecosystem of plugins, themes, and credentials rather than the WordPress core itself. We have been building and maintaining sites for fifteen years, and this incident was a sharp reminder that the most dangerous compromises are rarely the loud ones. Here is the whole story, and at the end we explain how we can help if you think you might be caught up in the same campaign.

The short version

A WordPress site was serving malicious JavaScript to ordinary visitors while showing clean pages to the site owner, to Google, and to every security scanner.

The attacker got in with a valid administrator password that had been stolen from a computer by an infostealer, not by brute-forcing the login.

Once inside, they uploaded a disguised plugin that injected a remote script, wired up a second backup injection in the theme, and created a hidden admin account.

We removed all of it, rebuilt the affected files from clean sources, rotated every credential, and traced the break-in to a single source IP using the host’s access logs.

The real fix was not on the website at all. It was the infected machine where the password was stolen. Until that is dealt with, cleaning the site only buys time.

What is a WordPress JavaScript injection attack?

A JavaScript injection is when an attacker arranges for a small piece of their own JavaScript to load on your pages, so it runs in your visitors’ browsers. From there it can do whatever they want: redirect people to scam pages, show fake prompts that trick users into pasting malicious commands into their own computer (the pattern often called “ClickFix”), swap in spam links, or quietly harvest information. Your site becomes the delivery vehicle, and your visitors and your reputation pay for it.

 

This matters because the website itself often keeps working perfectly. The pages load, the forms submit, the business runs. The damage is happening one layer down, in the browser of every real person who visits. What made this particular case worth writing about was not the payload. It was how carefully it hid.

How can a hacked WordPress site look completely normal?

Because good web malware is written to disappear whenever it might be caught. Before doing anything, the malicious script in this case checked who was visiting. If the request came from a search engine crawler, a security scanner, or common automated tools, it did nothing at all. If the visitor was on an admin or login page, it did nothing. Only for an ordinary human visitor on a normal page would it actually run and contact the attacker’s server for instructions.

That single design choice explains why it went unnoticed:

The site owner, who is almost always logged in as an administrator, never saw anything wrong.

Google’s crawler was served clean pages, so search listings looked fine and no obvious warning appeared.

Automated scanners that announce themselves were skipped entirely.

A site can be actively attacking its own visitors and still look healthy from every angle the owner normally checks. This is the single most important thing to understand about modern web malware: “it looks fine to me” is not evidence that a site is clean.

How did the attacker get in?

Not by guessing the password. The site’s login logs were full of the usual background noise of failed login attempts from bots all day long, all blocked. Buried in that noise was one login that simply succeeded, because it used a real administrator password.

This is the norm, not the exception. Verizon’s 2025 Data Breach Investigations Report found that stolen credentials remain the single most common way attackers gain initial access, used in roughly 22% of breaches, and that 88% of basic web application attacks involved stolen credentials. Attackers favor credentials because they are predictable and, increasingly, cheap to obtain.

In this case the password had been stolen earlier by an infostealer, a type of malware that quietly runs on a person’s computer and copies saved passwords out of their web browser, then sends them to the attacker. So the chain looked like this: a work computer got infected, the browser-saved logins on that machine were harvested, and some time later an attacker used one of those logins to walk straight into the site as an administrator.

Once authenticated, the rest took under three minutes. From the host’s access logs we could reconstruct the exact sequence: log in, open the plugin installer, upload a plugin, activate it. The “plugin” was disguised with an innocuous name and a vague description, and activating it is what dropped the malicious script into the active theme and planted the injection. The same automated routine also created a second administrator account with a harmless-sounding name, so that even if the password were later changed, the attacker would still have a way back in.

How do you know if your WordPress site is infected?

If you want to check your own site, here is what this campaign tended to leave behind. None of these are normal, and any one of them is worth investigating.

  • A plugin with a random-looking name, often a generic word followed by a string of hex characters, with a vague description such as “simple js plugin.”
  • An unexpected JavaScript file sitting inside your active theme’s folder, sometimes named to look like a stylesheet (for example a .js file with a CSS-sounding name).
  • A <script> tag in your theme’s header pointing to that file, which you or your developer did not add.
  • An administrator account you do not recognize, frequently created on the same day the other changes appeared, using an on-domain or throwaway email address.
  • Visitors, or Google Search Console, reporting redirects or odd behavior you cannot reproduce yourself because you are logged in.

A practical first check, if you have command-line access through SSH and WP-CLI, is to verify your core and plugin files against their official versions and look at recently modified files:

wp core verify-checksums

wp plugin verify-checksums --all

find wp-content -name "*.php" -mtime -30 -printf "%TY-%Tm-%Td  %p\n" | sort

If verify-checksums reports files that do not match, or you find recently modified files you cannot explain, treat the site as compromised until proven otherwise. And always check from a logged-out browser, ideally on a device and network you do not normally use, because that is the only view that matches what your visitors actually see.

How do you clean a hacked WordPress site without making it worse?

We work every incident in the same order, because skipping ahead is how people destroy the evidence they later need or leave a backdoor in place.

Step 1

Preserve first.

Before changing anything, copy the malicious files to a quarantine folder and record their fingerprints and exact timestamps. Those timestamps become your timeline and tie every artifact to the same intrusion.

Step 2

Contain.

Deactivate the malicious plugin, clear the cache, then immediately re-check the live site. In our case the injection was still running, which told us there was a second delivery method we had not found yet. Removing the obvious thing and assuming you are done is a common and costly mistake.

Step 3

Find everything.

Search the file system and the database for every reference to the payload. The second injection turned out to be a script line the attacker had hardcoded directly into the theme’s header file, which is why deactivating the plugin alone did not stop it. Confirm there is nothing hidden in must-use plugins, scheduled tasks, or the database.

Step 4

Eradicate and rebuild.

Remove the malicious files, then reinstall the theme and verify all core and plugin files against their official sources, so anything else the attacker touched is overwritten with known-good copies.

Step 5

Remove persistence and rotate.

Delete the attacker’s hidden administrator account, invalidate every active login session at once, and reset all administrator passwords.

Step 6

Harden and verify.

Confirm, from a logged-out visitor’s perspective, that the injection is gone and the site is healthy, and document everything for the record.

What is the real root cause, and how do you stop it coming back?

Here is the uncomfortable truth this kind of incident forces. The website was never really the problem. The website was the symptom. The problem was a computer with an infostealer on it and a browser full of saved passwords.

This is exactly where the broader data points. Verizon’s 2025 report noted that when researchers analyzed credential logs harvested by infostealers, 46% of the compromised systems that held corporate logins were unmanaged personal devices mixing personal and work credentials. In other words, the weak link is very often a person’s own laptop, not the server. If you clean the site but not the machine, the attacker simply waits for the next saved password to be used and walks back in. And because that one infected machine likely held saved logins for many sites, every site those credentials could reach is potentially exposed, not just the one showing symptoms.

That is why our response did not end at the website. It extended to identifying the source machine, getting it cleaned, and rotating credentials across everything that machine could reach. The practical lessons we would pass on to any site owner or agency:

Security Practice #1

Stop letting browsers save your CMS and hosting passwords. The convenience is exactly what infostealers harvest.

Security Practice #2

Turn on two-factor authentication for every administrator. A stolen password alone should not be enough to log in.

Security Practice #3

Keep the number of administrator accounts small and review them regularly. Old contractor accounts and forgotten logins are pure risk.

Security Practice #4

Keep plugins and themes updated and remove ones you no longer use, since the extensible ecosystem, not the WordPress core, is where most compromises begin.

Security Practice #5

Assume “the site looks fine” tells you nothing, and check from the outside, logged out, on a clean device.

Security Practice #6

If one site in a portfolio is hit, treat the whole portfolio, and the people managing it, as in scope until you have ruled the rest out.

Frequently Asked Questions

Frequently Asked Questions

How do I know if my WordPress site has malware if it looks fine to me?
You usually cannot tell while logged in, because this kind of malware deliberately hides from administrators and search crawlers. Check from a logged-out browser on a device you do not normally use, watch Google Search Console for security notices, and verify your files with wp core verify-checksums. The absence of obvious symptoms is not proof a site is clean.
What is a JavaScript injection attack?
It is when an attacker gets their own JavaScript to load on your pages so it runs in your visitors’ browsers, where it can redirect them, show fraudulent prompts, inject spam, or steal information. The website itself often keeps working normally, which is why the damage can go unnoticed for a long time.
Can WordPress malware really hide from Google and from security scanners?
Yes. Sophisticated injections check who is visiting and stay completely silent for crawlers, scanners, and logged-in administrators, only activating for ordinary human visitors. This cloaking is specifically designed to keep the site looking clean to the people most likely to catch it.
How did the attacker get in if the password was strong?
A strong password does not help if it has been stolen. In this case it was harvested from an infected computer by an infostealer, then reused to log in normally. Stolen credentials are the most common initial access method in breaches today, which is why two-factor authentication matters so much.
Is changing my passwords enough to fix a hacked site?
No. You also have to remove the malware and every backdoor the attacker left, and, critically, deal with the infected machine the password was stolen from. If that machine is still compromised, resetting the password just hands the attacker a fresh one to steal.
How do I stop this from happening again?
Enable two-factor authentication on all admin accounts, stop saving CMS and hosting passwords in browsers, keep plugins and themes updated and minimal, limit administrator accounts, and make sure the devices your team logs in from are clean and protected.
WordPress Security & Malware Cleanup

Worried your site might be affected? We can help.

We do this work for a living, and we would rather help you catch this early than meet you after it has spread. If your WordPress site is showing any of the signs above, or you simply want a clean second opinion, Group Fractal can run a proper check, clean an active infection without destroying the evidence you need, trace how the attacker got in, and put the protections in place that stop it happening again. We are also happy to review an entire portfolio if you manage sites for others, because as this incident showed, these campaigns rarely stop at one site.

You do not need to wait until something visibly breaks. The most damaging version of this attack is the one nobody sees. If any of this sounds familiar, reach out and we will take a look.

Request a Security Review

About Group Fractal

Group Fractal is a digital agency that has spent fifteen years building, growing, and protecting websites for businesses across a wide range of industries. Our work spans search and content strategy, paid media, marketing automation, and the technical web work that keeps all of it running, including WordPress security and incident response. This article is based on a real engagement; client and site details have been anonymized.

Worried Your WordPress Site May Be Compromised?

Request a Security Review