When a WordPress site is hacked, the obvious approach is usually:
- Find the malicious file
- Delete it
- Run a malware scanner
- Assume the site is clean
That works for simple infections.
But in more advanced cases, the malicious file you can see is only one part of the compromise.
The real problem is often persistence.
A site can look clean after remediation and then become infected again because another component is still capable of restoring the malware.
Malware can exist across several WordPress layers
In real cleanup cases, I have found malicious code or persistence mechanisms in places like:
wp-content/mu-plugins/- Fake WordPress plugins
- Theme
functions.php - Database
optionstable - Cron jobs
.user.ini- Service workers
- Compromised uploads
- Random PHP files inside
wp-content - Modified WordPress core files
- Injected JavaScript
- Hidden administrator accounts
- Hosting-level configuration
The important part is that these components may not operate independently.
For example:
Cron
↓
Malicious PHP file
↓
Database option
↓
Injected JavaScript
Deleting only the PHP file may solve the visible symptom temporarily while leaving the restoration mechanism untouched.
A clean scan is not proof that the site is clean
Malware scanners are useful.
I use them too.
But a scanner result should be treated as a signal, not absolute proof.
During a proper investigation, I also want answers to questions such as:
- Were any administrator accounts created?
- Were plugin files modified?
- Is there an unfamiliar fake plugin?
- Are there suspicious entries in the database?
- Are cron jobs loading unknown code?
- Has
.user.inibeen modified? - Is another website in the same hosting account compromised?
- Are credentials still exposed?
- Are SEO spam URLs still indexed?
- Is the domain blacklisted?
- What caused the compromise in the first place?
And most importantly:
What can recreate the malware after I delete it?
That question is often more valuable than simply asking where the malware is.
Reinfection does not always mean the attacker hacked the site again
This distinction matters.
Suppose you remove a malicious file at:
wp-content/uploads/example.php
A few hours later, it appears again.
It is tempting to conclude:
“The attacker got back into the site.”
Maybe.
But another possibility is that something already present on the server restored it.
That could be:
cron
or:
.user.ini
or a malicious database entry, fake plugin, mu-plugin, theme injection, or another PHP loader.
In that situation, the second infection is not necessarily a second intrusion.
It is the original compromise continuing to operate.
One recent case used multiple persistence paths
I recently investigated a WordPress infection where malicious components were distributed across several locations.
The persistence involved areas such as:
mu-plugins
fake plugin
theme functions.php
database options table
cron
.user.ini
service workers
wp-content files
Removing one component was not enough.
Several pieces could contribute to restoring or loading other malicious components.
This kind of case changes the way you approach remediation.
Instead of thinking:
Find malware → Delete malware
the workflow becomes closer to:
Detect symptoms
↓
Map compromised components
↓
Identify relationships
↓
Remove persistence
↓
Remove payloads
↓
Find initial access
↓
Verify cleanup
↓
Monitor for reinfection
My general WordPress malware cleanup workflow
I prefer to separate remediation into several stages.
1. Confirm the compromise
Before deleting anything, identify the symptoms.
Examples:
- Redirects
- Spam pages
- Unknown JavaScript
- New admin accounts
- Browser warnings
- Google Safe Browsing alerts
- Suspicious PHP files
- Modified plugin files
2. Determine the scope
Do not assume only one website or one directory is affected.
Check:
WordPress files
database
hosting account
other websites
server configuration
DNS/CDN
administrator accounts
scheduled tasks
3. Investigate persistence
This is one of the most important steps.
Search for anything capable of restoring another malicious component.
4. Remove malicious components
Only after understanding the relationships between them should cleanup begin.
Otherwise you can end up deleting symptoms while leaving the mechanism alive.
5. Investigate the entry point
Potential causes include:
- Vulnerable plugins
- Stolen credentials
- Abandoned plugins
- Compromised hosting accounts
- Exposed admin access
- Another infected site under the same account
6. Recover reputation and search visibility
Some infections continue causing problems even after the server is clean.
Examples include:
- Indexed Japanese SEO spam
- Google Safe Browsing warnings
- Search Console security issues
- Spam URLs remaining in search results
- Domain reputation problems
7. Monitor after cleanup
A successful cleanup is not:
“The scanner says zero malware.”
A better standard is:
“The malicious components are gone, the persistence paths are gone, the likely entry point has been addressed, and the site remains clean afterward.”
I turned this workflow into a book
After working on WordPress malware cleanup for years, I started documenting the process I use across real cases.
That eventually became:
WordPress Malware Removal for Developers & Site Owners
It covers areas including:
- Diagnosing compromised WordPress sites
- Determining infection scope
- File-system cleanup
- Database malware
- Redirect malware
- SEO spam
- Fake plugins and themes
- Hidden administrator accounts
- Persistence and reinfection
- Hosting and server issues
- Blacklist recovery
- Post-cleanup monitoring
The focus is on practical investigation rather than simply installing another security plugin.
The book is currently available using a Pay What You Want model, starting at $9.99:
Final thought
When cleaning a hacked WordPress site, do not stop after finding the first malicious file.
The more useful question is:
What else must still exist for this infection to come back?
Finding that answer is often where the real malware removal work begins.
Suggested DEV tags: wordpress, security, cybersecurity, webdev
Top comments (0)