WordPress Malware Scanner: How to Detect Backdoors and Malicious PHP

php dev.to

A WordPress website can look completely normal while malicious code is quietly running in the background.

Attackers can hide PHP backdoors inside plugins, themes, uploads directories, mu-plugins, cron jobs, or even the WordPress database. Removing the obvious malicious file is also not always enough. If a hidden backdoor remains, the attacker may simply reinfect the website.

That is why a proper WordPress malware scanner should do more than search for a few known malware signatures.

In this guide, we'll look at how WordPress malware works, how to detect suspicious PHP code, how backdoors hide, and how developers can build a layered approach to WordPress security.

What Is WordPress Malware?

WordPress malware is malicious code that has been injected into a WordPress website without the owner's authorization.

It can be used to:

  • Create hidden administrator accounts
  • Steal credentials
  • Redirect visitors to malicious websites
  • Inject SEO spam
  • Upload additional malware
  • Execute arbitrary commands
  • Send spam emails
  • Modify WordPress files
  • Inject malicious JavaScript
  • Maintain persistent access to the server

Common malware locations include:

/wp-content/plugins/ 
/wp-content/themes/ 
/wp-content/uploads/ 
/wp-content/mu-plugins/ 
/wp-includes/
/wp-admin/

Enter fullscreen mode Exit fullscreen mode

Attackers may also hide malicious code inside database records, WordPress cron events, or server configuration files.

Why Malware Can Be Difficult to Detect

One of the biggest problems with malware detection is that malicious code does not always look obviously malicious.

For example, developers may encounter functions such as:

eval();
base64_decode(); 
gzinflate(); 
str_rot13(); 
assert(); 
shell_exec(); 
system(); 
passthru();

Enter fullscreen mode Exit fullscreen mode

These functions are not automatically malware.

Legitimate applications can use some of them.

The problem appears when they are combined with suspicious behavior.

For example:

eval(base64_decode($payload));

Enter fullscreen mode Exit fullscreen mode

This pattern deserves investigation because encoded content is being decoded and executed dynamically.

A good scanner therefore should not simply say:

"base64_decode() found = malware."

Enter fullscreen mode Exit fullscreen mode

Instead, it should analyze the surrounding code and determine whether the combination of functions, variables, inputs, and execution behavior is suspicious.

Common WordPress Backdoor Techniques

1. Obfuscated PHP

Attackers frequently obfuscate malicious code to make manual inspection difficult.

For example:

$code = base64_decode('...'); eval($code);

Enter fullscreen mode Exit fullscreen mode

Another example can involve compression:

eval(gzinflate(base64_decode('...')));

Enter fullscreen mode Exit fullscreen mode

The goal is simple:

Malicious code

Encode

Compress

Hide inside PHP

Decode at runtime

Execute

A malware scanner should therefore inspect both the visible source code and suspicious encoded payloads.

2. Variable Function Execution

Another common technique is executing a function dynamically.

For example:

$function = $_GET['action']; 
$function($_POST['data']);

Enter fullscreen mode Exit fullscreen mode

This can become extremely dangerous when attacker-controlled input reaches a function that can execute code or commands.

A scanner should pay particular attention to:

$_GET
$_POST
$_REQUEST
$_COOKIE

Enter fullscreen mode Exit fullscreen mode

Dynamic function calls

call_user_func()
call_user_func_array()

Enter fullscreen mode Exit fullscreen mode

The important point is not that every use is malicious.

The important question is:

Can untrusted input control what the application executes?

3. PHP Files Inside the Uploads Directory

The WordPress uploads directory is another location worth checking.

For example:

/wp-content/uploads/2026/09/image.php
Enter fullscreen mode Exit fullscreen mode

A PHP file inside an uploads directory can be suspicious because the directory normally stores media files such as:

.jpg
.png
.gif
.webp
.pdf
.mp4

A scanner should therefore flag unexpected executable files for manual review.

However, security tools should avoid assuming that every unusual file is automatically malicious.

False positives are a real problem in malware scanning.

4. Fake Plugins and Themes

Attackers can create plugins that look legitimate.

For example:

speed-cache-helper 
wordpress-performance-tool 
seo-optimizer 
security-update
Enter fullscreen mode Exit fullscreen mode

A malicious plugin may contain a normal-looking plugin header while hiding a backdoor elsewhere in the code.

This is why checking only plugin names is not enough.

A security scanner should inspect:

  • Plugin files
  • Plugin metadata
  • File changes
  • Suspicious hooks
  • Remote requests
  • Obfuscated code
  • Unexpected executable files

5. WordPress Database Malware

Not every infection lives inside a PHP file.

Attackers can inject malicious content into database tables such as:

wp_options 
wp_posts 
wp_postmeta 
wp_comments
Enter fullscreen mode Exit fullscreen mode

For example, malicious JavaScript may be injected into a post or option.

A database infection can be particularly difficult to notice because a traditional file-only scanner may never inspect it.

This is why modern WordPress security should consider both:

File scanning
+
Database scanning

rather than relying on only one source.

File Integrity Monitoring

Malware scanning answers one important question:

Does this code look suspicious?

File Integrity Monitoring answers another:

Did this trusted file change unexpectedly?

These are different security problems.

Imagine a clean WordPress installation.

You calculate a baseline:

plugin.php SHA-256 → ABC123...

Later, the file changes:

plugin.php
SHA-256 → XYZ789..

The hash changed.

That does not automatically mean the file is infected.

A legitimate plugin update can also change the hash.

But an unexpected modification is an important security event that should be investigated.

A simple integrity workflow looks like this:

Trusted baseline

Monitor files

Detect modification

Compare changes

Investigate

Restore or approve

File integrity monitoring is especially useful after a website has already been compromised.

Malware Scanner vs Vulnerability Scanner

These two terms are often confused.

They solve different problems.

For example, a vulnerability scanner may discover that a plugin contains a known CVE.

A malware scanner may discover that the plugin file has already been modified.

You need both.

Finding a vulnerability does not prove that the site is infected.

Finding malware does not necessarily tell you which vulnerability was originally exploited.

How to Scan WordPress for Malware

If you suspect your WordPress website has been compromised, follow a structured process.

Step 1: Create a Backup

Before modifying anything, create a reliable backup.

Keep the backup separate from the compromised website if possible.

Step 2: Check WordPress Core

Compare WordPress core files against trusted versions.

Unexpected modifications to core files should be investigated.

Step 3: Scan Plugins
Check installed plugins for:

Unexpected files
Modified files
Obfuscated PHP
Suspicious remote requests
Unknown code
Outdated vulnerable versions

Do not assume that deleting one suspicious plugin completely removes an infection.

Step 4: Scan Themes

Check both the active and inactive themes.

Attackers sometimes hide backdoors inside inactive themes because site owners rarely inspect them.

Pay special attention to:

functions.php 
header.php 
footer.php 
404.php 
single.php
Enter fullscreen mode Exit fullscreen mode

But do not assume these files are malicious just because they contain PHP.

Step 5: Check the Uploads Directory

Look for unexpected executable files:

wp-content/uploads/

Enter fullscreen mode Exit fullscreen mode

Especially investigate PHP files that should not normally exist there.

Step 6: Review Administrator Accounts

Check:

Users → All Users

Look for:

  • Unknown administrators
  • Recently created accounts
  • Unexpected email addresses
  • Suspicious usernames

An attacker who creates a hidden administrator account may be able to regain access even after visible malware is removed.

Step 7: Review Cron Jobs
WordPress cron events can be abused for persistence.

Look for scheduled tasks that:

  • Download remote files
  • Execute suspicious PHP
  • Create users
  • Modify files
  • Contact unknown external servers

Step 8: Check .htaccess

A compromised .htaccess file can be used for:

  • Redirects
  • Cloaking
  • Malicious rewrites
  • Search engine spam
  • Request manipulation

Unexpected rules should be reviewed carefully.

Why Removing Malware Is Not Always Enough

Consider this attack chain:

Vulnerable Plugin

Initial Exploit

Malicious PHP Uploaded

Hidden Backdoor Created

Attacker Creates Persistence

Visible Malware Removed

Backdoor Survives

Website Reinfected

This is why incident response should investigate the root cause and persistence mechanism, not just delete the first suspicious file.

Modern WordPress security tools increasingly focus on this broader problem: file scanning alone may miss database-resident malware, rogue access mechanisms, scheduled persistence, or other reinfection paths.

A Better WordPress Security Strategy
Instead of depending on a single security feature, use multiple layers.

Each layer answers a different security question.

What Should a Modern WordPress Malware Scanner Detect?

A useful scanner should look beyond simple signatures.

Important detection categories include:

PHP Backdoors

Detect suspicious code that allows attackers to execute commands or maintain access.

Obfuscated Code

Look for encoded, compressed, or heavily obfuscated payloads.

Suspicious File Changes

Compare important files against a known-good baseline.

Malicious JavaScript

Look for injected scripts, hidden iframes, and suspicious external resources.

Uploads Directory

Identify unexpected executable files.

Database Injections

Inspect relevant database content for suspicious payloads.

Cron Persistence

Review scheduled events that may download or execute malicious code.

Rogue Users

Detect unexpected administrator accounts and privilege changes.

Redirect Malware

Identify suspicious redirects and cloaking behavior.

Avoiding False Positives

One of the biggest challenges in malware scanning is false positives.

For example:

$encoded = base64_encode($data);
Enter fullscreen mode Exit fullscreen mode

is not automatically malicious.

Likewise:

eval();
Enter fullscreen mode Exit fullscreen mode

inside a legitimate development tool does not necessarily mean the entire website is compromised.

A good security scanner should provide:

  • File path
  • Line number
  • Detection reason
  • Severity
  • Detection type
  • Context
  • Review option

Instead of simply displaying:

MALWARE FOUND

a better result is:

High Risk

File:

wp-content/plugins/example/plugin.php
Enter fullscreen mode Exit fullscreen mode

Line:
184

Reason:
Encoded payload is dynamically executed using eval().

Recommendation:
Review the surrounding code before removal.

This gives developers enough information to make a safe decision.

WordPress Security Should Be Layered

There is no single feature that can guarantee a WordPress website will never be hacked.

Security is a process.

A strong WordPress security strategy should include:

Regular updates
+
Vulnerability scanning
+
Malware scanning
+
File integrity monitoring
+
Secure authentication
+
WAF / request protection
+
Audit logging
+
Reliable backups

If one layer fails, another layer may detect or limit the damage.

How Nexura Security Fits Into This Approach

Nexura Security is designed around a layered WordPress security model rather than relying on a single protection mechanism.

Its security features include vulnerability scanning, security audit logs, security headers, database security checks, cron auditing, and security reporting.

The goal is simple:

Detect problems early, provide useful security information, and help WordPress administrators understand what is happening on their website.

For WordPress developers and site owners, combining vulnerability detection with malware detection, integrity monitoring, and security auditing provides a much stronger security strategy than relying on only one scanner.

WordPress Malware Detection Checklist

Before considering a compromised WordPress website clean, review the following:

☐ WordPress core checked
☐ Plugins checked
☐ Themes checked
☐ Uploads directory checked
☐ PHP files reviewed
☐ Obfuscated code investigated
☐ Database checked
☐ Cron jobs reviewed
☐ Administrator accounts reviewed
☐ .htaccess reviewed
☐ File integrity checked
☐ Vulnerabilities scanned
☐ Security logs reviewed
☐ Passwords and credentials rotated
☐ WordPress and plugins updated
☐ Clean backup verified

Final Thoughts

WordPress malware detection is more complicated than searching foreval() or base64_decode().

Attackers can hide malicious code inside files, databases, scheduled tasks, plugins, themes, and server configuration.

That is why a modern WordPress malware scanner should combine multiple detection techniques and provide enough context for developers to investigate suspicious findings.

The best security strategy is not:

Install one plugin and forget about security.

It is:

Prevent → Detect → Investigate → Recover → Monitor

When these layers work together, it becomes much harder for attackers to remain hidden and much easier for website owners to respond when something goes wrong.

## Final Thoughts

WordPress security is an ongoing process. Malware scanning can help detect suspicious code, while vulnerability scanning, file integrity monitoring, and security auditing provide additional layers of protection.

If you want to explore these security features in one WordPress security solution, take a look at Nexura Security.

👉 Learn more about Nexura Security

Keep your WordPress installation updated, monitored, and protected.

Source: dev.to

arrow_back Back to Tutorials