A website hack is a stressful situation that requires clear, fast action. The main rule: don't panic, act systematically. Most websites can be fully restored within a few hours.
Signs of a Hacked Website
- Redirect to a different site (pharming, phishing)
- Google warning: "This site may be hacked"
- Your hosting provider suspended the account for sending spam
- New files or directories appearing
- Unexplained spike in traffic or server load
- Users reporting antivirus warnings
Step 1: Isolation and Evidence Preservation
cp -r /var/www/site/ /tmp/site-backup-hacked/
find /var/www/site/ -newer /var/www/site/index.php -type f | head -50
ls -lat /var/www/site/ | head -20
Step 2: Finding Malicious Code
apt install clamav -y && freshclam
clamscan -r --infected /var/www/site/
find /var/www/site/ -name "*.php" -exec grep -l "base64_decode\|eval\|gzinflate\|str_rot13\|preg_replace.*e" {} \;
find /var/www/site/ -name "*.php" -newer /var/log/dpkg.log -type f
grep -r "FilesMan\|c99\|r57\|WSO Shell\|webshell" /var/www/site/
Step 3: Cleanup or Restore
grep -r "eval(base64_decode" /var/www/wordpress/ --include="*.php" -l | while read f; do
echo "Infected: $f"
done
for infected_file in $(grep -rl "eval(base64_decode" /var/www/wordpress/ --include="*.php"); do
rm "$infected_file"
echo "Removed: $infected_file"
done
Step 4: Fixing the Root Cause
grep "access.log" /var/log/nginx/access.log | grep "POST /wp-admin\|/xmlrpc.php" | sort | uniq -c | sort -rn | head -20
grep "404\|403" /var/log/nginx/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -20
Step 5: Notify Google
After cleanup: Google Search Console → Security → Request a Review. Removing the warning takes 1–3 days.
Post-Recovery Checklist
| Action | Status |
|---|---|
| Change all passwords (database, FTP, control panel) | |
| Update the CMS, plugins, and themes | |
| Install a WAF (Wordfence, ModSecurity) | |
| Set up file change monitoring | |
| Check file permissions | |
| Request a review in Google Search Console | |
| Notify your hosting provider about the cleanup |
Common Messages During a Hack
| Message | What it means | What to do |
|---|---|---|
| "Deceptive site ahead" in Chrome | Google Safe Browsing found phishing or deceptive content on the site | Clean the site, then request a review in Google Search Console → Security |
| "Your account has been suspended due to abuse complaints" from the host | The site was sending spam or malicious traffic, and the host suspended it preemptively | Contact hosting support, get the list of violations, and fix the cause before requesting reactivation |
| An unfamiliar RewriteRule in .htaccess | The attacker added a redirect sending part of the traffic to a spam or phishing domain | Remove rules you didn't add yourself, keeping only your own |
| siteurl in the wp_options table points to a foreign domain | A WordPress-specific sign: an exploit changed the site address stored in the database | Restore it manually with wp option update siteurl "https://example.com" |
Comparing Cleanup Approaches
| Approach | Speed | Reliability | Cost |
|---|---|---|---|
| Restoring from a clean backup | Fast — minutes to hours | High, if the backup predates the infection | Free, if a backup exists |
| Manual file cleanup | Slow — hours or days | Medium, risk of missing one infected file | Free, but costly in specialist time |
| Paid service (Sucuri, MalCare, etc.) | Fast — usually within a day | High, professional audit and follow-up monitoring | $100–400 for a one-time cleanup |
When Recovery Is More Than a Checklist
- The infection reached the server itself, not just site files (rootkit, tampered system binaries) — this needs a full OS audit, not just the web directory
- Shared hosting where a neighboring account got infected first and keeps reinfecting yours through shared server resources — the only fix is moving to an isolated VDS
- Malicious code arrived through a trusted update of a legitimate plugin (a supply-chain attack) — a plain diff against the original plugin won't reveal it
- An unpatched 0-day vulnerability in the CMS core is being exploited — the stopgap is a WAF rule blocking the exploit until a patch ships
To avoid repeating this, run through "WordPress Security: Complete 2026 Checklist", and keep a ready-made "Incident Response Plan: The First 60 Minutes" on hand for next time.
Verifying the Result
After cleanup, confirm no hidden way back in was left for the attacker:
# Check cron jobs on the server and inside WordPress itself
crontab -l -u www-data
wp cron event list
# Check the admin user list for anything new
wp user list --role=administrator
# Check outbound connections for suspicious addresses
netstat -antp | grep ESTABLISHED
# Re-scan with a second tool for a cross-check
apt install rkhunter -y && rkhunter --check --sk
To block repeated password guessing on the panel and SSH after cleanup, install Fail2ban: Protecting SSH and Nginx from Password Guessing.