Skip to content

Malware Removal Guide

Signs of Infection

  • Site defaced or redirecting
  • Unexpected admin users
  • Unknown files in WordPress installation
  • SEO spam injected into content
  • Security plugin alerts
  • High server load / outgoing traffic
  • Blacklisted by Google

Immediate Actions

# 1. Take the site offline
wp maintenance-mode activate

# 2. Notify stakeholders

# 3. Gather evidence (logs, timestamps)
journalctl -u nginx --since "24 hours ago" | grep -i "error\|POST" > /tmp/incident.log

# 4. Start clean

Full Cleanup Procedure

1. Backup Everything

# Backup database and files before cleaning
mysqldump -u root -p wordpress > /tmp/wp-infected-backup.sql
tar czf /tmp/wp-infected-files.tar.gz /var/www/html/

2. Identify Malware

# Scan for suspicious files
# Check recently modified files
find /var/www/html -type f -mtime -7 | grep -v wp-content/uploads

# Check for eval/base64 injections
grep -r "eval(" /var/www/html --include="*.php"
grep -r "base64_decode" /var/www/html --include="*.php"
grep -r "preg_replace.*/e" /var/www/html --include="*.php"

# Check uploads for PHP files
find /var/www/html/wp-content/uploads -name "*.php"

# Check for hidden files
find /var/www/html -name ".*" -type f

3. Check Core Integrity

# Verify WordPress core files
wp core verify-checksums

# Files that fail checksum are likely infected
# Exceptions: wp-config.php, wp-content/

4. Check Database for Malware

# Search for injected content
wp db query "SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%<script%'"
wp db query "SELECT option_name, option_value FROM wp_options WHERE option_value LIKE '%base64%'"
wp db query "SELECT option_name, option_value FROM wp_options WHERE option_name LIKE '%widget%' AND option_value LIKE '%eval%'"

# Check for unknown admin users
wp user list --role=administrator

# Check user creation time
wp db query "SELECT user_login, user_registered FROM wp_users ORDER BY user_registered"

5. Clean

The most reliable method is a clean reinstall:

# Reinstall WordPress core
wp core download --force --skip-content

# Delete all plugins
wp plugin delete --all

# Delete all themes (except default)
wp theme delete $(wp theme list --status=inactive --field=name)

# Reinstall plugins from known sources
wp plugin install wordfence --activate
wp plugin install wordpress-seo --activate

Alternative: Manual Clean

# Remove suspicious files
rm -f /var/www/html/404.php /var/www/html/wp-admin/network.php
# (adjust paths based on findings)

# Clean database
wp db query "UPDATE wp_posts SET post_content = REPLACE(post_content, '<malicious_code>', '')"
wp db query "DELETE FROM wp_options WHERE option_name LIKE '%malware%'"

6. Reset User Credentials

# Reset all passwords
wp user list --format=ids | xargs -I{} wp user update {} --user_pass=$(openssl rand -base64 18)

# Delete unknown users
wp user delete <suspicious_user_id>

# Regenerate salts (forces logout of all sessions)
wp config set AUTH_KEY "$(openssl rand -base64 40)" --raw
wp config set SECURE_AUTH_KEY "$(openssl rand -base64 40)" --raw
wp config set LOGGED_IN_KEY "$(openssl rand -base64 40)" --raw
wp config set NONCE_KEY "$(openssl rand -base64 40)" --raw

7. Harden After Cleanup

wp-config.php
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true);  // Block plugin/theme install
# Block PHP execution in uploads
location /wp-content/uploads/ {
    location ~ \.php$ { deny all; }
}

8. Restore Content Only

# Export clean content
wp export --dir=/tmp/ --post_type=post,page

# Or just restore posts from clean backup
# Import into clean install
wp import /tmp/wordpress.xml --authors=create

Prevention

# Regular checks
0 6 * * * /usr/local/bin/wp core verify-checksums --path=/var/www/html >> /var/log/wp-security.log

# File integrity monitoring (AIDE)
apt install -y aide
aideinit
0 2 * * * /usr/bin/aide --check | mail -s "AIDE Report" admin@example.com

Plugins

  • WordFence — firewall + malware scanner
  • Sucuri Security — malware scanning + monitoring
  • GOTMLS — malware scanner
  • iThemes Security — hardening + scanning

Checklist

  • Site taken offline during cleanup
  • Full backup taken before any changes
  • Core files verified (wp core verify-checksums)
  • Database scanned for injections
  • Unknown admin users removed
  • All passwords reset
  • Security keys regenerated
  • File permissions fixed
  • Plugins/themes reinstalled from official sources
  • Hidden files and backdoors removed
  • Monitoring and scanning enabled