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