WordPress Hacked? Emergency Playbook to Contain & Recover

If your WordPress site got hacked, every minute counts. One compromised admin account or a hidden backdoor can mean stolen data, ruined SEO, lost revenue and a long, expensive recovery. This guide is a no-fluff, step-by-step emergency playbook designed to move you from panic to containment, cleanup and long-term recovery — fast.

You’ll find exactly what to do first (the actions you must take in the first minutes and hour), what safe commands and scripts to run or hand to your host, how to preserve forensic evidence, and the proven remediation sequence to remove malware, close persistence and restore trust. There are clear verification steps so you know when it’s truly safe to re-open the site, plus communication templates for stakeholders and customers and a 30/60/90-day hardening plan to prevent repeat attacks.

Whether you’re a site owner, developer, or IT responder, this playbook gives practical, prioritized actions you can implement immediately — or hand off to your web host or incident response team. Ready to stop the bleeding and take back control? Start with the “Immediate priorities” section below.


Immediate priorities

  1. Breathe & document. Note who found it, when, symptoms (redirects, defacement, popup, Google warning), and any first actions taken.
  2. Put site into maintenance mode / block public access.
    • If you can log in to WP, enable a maintenance plugin or set a static index.html holding page at webroot.
    • If not, ask host to restrict site by IP or enable CDN/WAF “Under Attack” / “Maintenance” mode.
  3. Preserve a snapshot (do not modify files yet).
    • Ask host for a server snapshot or create an archive of current files and DB (read-only).
    • If you have shell access, run the non-destructive snapshot script below (it only collects information).
  4. Change all critical passwords immediately (but do not delete logs or snapshots): hosting, control panel, SSH/SFTP, database, WP admin, payment API keys. Force logout of all sessions.
  5. Notify your host & (if applicable) your incident response team. Ask host to isolate the instance or suspend outgoing network if exfiltration suspected.

Signs your site is hacked

  • Unexpected redirects to other websites
  • Spam content appearing on your site
  • Google warning “This site may be hacked”
  • Defaced homepage
  • Can’t login to admin panel
  • Slow performance or site crashes
  • Unknown admin users
  • Hosting account suspended
  • Strange files in directories

Document everything:

  • Take screenshots of suspicious activity
  • Note the time you discovered the hack
  • Record any error messages
  • Check when the hack likely occurred

Enable Maintenance Mode. Prevent visitors from seeing the compromised site

Option A: Using Plugin (if you can still login)

Install "WP Maintenance Mode" or "Coming Soon" plugin
Activate maintenance mode

Option B: Manual Method (via FTP/File Manager)

Create a file named .maintenance in your WordPress root directory:

<?php
$upgrading = time();
?>

Option C: Via .htaccess

Add this to your .htaccess file:

apache

RewriteEngine On
RewriteBase /
RewriteCond %{REMOTE_ADDR} !^123\.123\.123\.123$ # Replace with YOUR IP
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
RewriteRule ^(.*)$ /maintenance.html [R=307,L]

Then create a simple maintenance.html file.

Change ALL Passwords IMMEDIATELY

Critical passwords to change (in this order):

  1. WordPress Admin Password
    • Go to: Users → Your Profile → Generate Password
    • Use a strong password (20+ characters, mixed case, numbers, symbols)
  2. Hosting Control Panel (cPanel/Plesk)
    • Login to your hosting account
    • Change main account password
  3. FTP/SFTP Password
    • Through hosting control panel
    • Update credentials in any FTP clients
  4. Database Password
    • cPanel → MySQL Databases → Change Password
    • Update wp-config.php with new password
  5. Email Accounts
    • All email addresses associated with the domain
  6. Other Users
    • Force password reset for all WordPress users

Contact Your Hosting Provider or Website Security Professional

Call or create support ticket immediately:

Tell them:

  • “My WordPress site appears to be hacked”
  • “Please check server logs for suspicious activity”
  • “Can you restore from a recent clean backup?”
  • “Has my account been suspended?”

Ask them to:

  • Review server access logs
  • Check for compromised accounts
  • Scan for malware
  • Identify attack vector
  • Confirm if other sites on server are affected

Request:

  • Recent clean backup (before the hack)
  • Log files showing suspicious activity
  • Any security alerts or notifications

Identify the Hack Type

Common WordPress hack types:

A. Malware Injection

  • Symptoms: Redirects, popup ads, hidden iframes
  • Look for: Obfuscated code, base64 encoded strings

B. Pharma Hack

  • Symptoms: Spam pages selling pharmaceuticals
  • Look for: Hidden pages, cloaking scripts

C. SEO Spam

  • Symptoms: Spam keywords, hidden links
  • Look for: Injected links in footer/comments

D. Backdoor

  • Symptoms: Recurring infections, hidden admin accounts
  • Look for: Shell scripts, suspicious PHP files

E. Brute Force Success

  • Symptoms: Unauthorized admin access
  • Look for: Login logs, new admin users

F. Defacement

  • Symptoms: Homepage replaced with hacker message
  • Look for: Modified index.php, wp-config.php

Backup Current Site (Even if Infected)

Why backup infected site?

  • Preserve evidence
  • Reference for what was changed
  • Recover content if needed

How to backup:

Via cPanel:

1. cPanel → File Manager
2. Select public_html folder
3. Compress → Create Archive
4. Download the archive
5. Also backup database from phpMyAdmin

Via FTP:

1. Connect via FileZilla
2. Download entire /public_html/ directory
3. Download from root directory (above public_html)

Database backup:

1. phpMyAdmin → Select database
2. Export → Quick → SQL format
3. Download file
4. Store securely offline

Remove Malicious Code
Critical files to check first:

wp-config.php (WordPress root)

Should only contain database configuration
Look for: Extra code at beginning or end
Compare with fresh WordPress wp-config-sample.php


index.php (WordPress root)

Should be minimal and clean
Look for: Redirects, obfuscated code


.htaccess (WordPress root)

Should only have WordPress rewrite rules
Look for: Redirects, suspicious RewriteCond


functions.php (In your theme folder)

/wp-content/themes/your-theme/functions.php
Look for: Base64 strings, eval(), unknown functions


Footer.php / Header.php

Look for: Hidden iframes, suspicious scripts



Common malicious code patterns:
php// Base64 encoded malware
<?php eval(base64_decode('...')); ?>

// Obfuscated code
<?php $a='base'.'64_dec'.'ode';$b=$a('...'); eval($b); ?>

// Hidden iframes
<iframe src="http://malicious-site.com" style="display:none"></iframe>

// Suspicious functions
eval()
base64_decode()
gzinflate()
str_rot13()
assert()
preg_replace() with /e modifier
create_function()
How to clean:

Compare with clean files

Download fresh WordPress from wordpress.org
Use diff tool to compare files
Restore clean versions


Manual removal

Open suspicious files in text editor
Remove malicious code if you can. If not we suggest you to order website malware removal services from us.
Save and upload clean version

Check Database for Malicious Content

Access database via phpMyAdmin:

A. Check for Rogue Admin Users

sql

SELECT * FROM wp_users;
SELECT * FROM wp_usermeta WHERE meta_key = 'wp_capabilities';

Look for:

  • Unknown usernames
  • Recently created accounts
  • Users with administrator role

Delete rogue users:

sql

DELETE FROM wp_users WHERE user_login = 'suspicious_username';
DELETE FROM wp_usermeta WHERE user_id = 'suspicious_user_id';

B. Search for Spam Content

sql

-- Search posts for suspicious content
SELECT * FROM wp_posts WHERE post_content LIKE '%viagra%';
SELECT * FROM wp_posts WHERE post_content LIKE '%<iframe%';
SELECT * FROM wp_posts WHERE post_content LIKE '%base64%';

-- Search for hidden posts
SELECT * FROM wp_posts WHERE post_status = 'private' OR post_status = 'draft';

-- Check for spam in comments
SELECT * FROM wp_comments WHERE comment_approved = '1' ORDER BY comment_date DESC LIMIT 50;

C. Check wp_options Table

sql

-- Look for suspicious entries
SELECT * FROM wp_options WHERE option_name LIKE '%hack%';
SELECT * FROM wp_options WHERE option_value LIKE '%<script%';
SELECT * FROM wp_options WHERE option_value LIKE '%base64%';

-- Check critical options
SELECT * FROM wp_options WHERE option_name IN ('siteurl', 'home', 'admin_email');

D. Clean Spam Content

sql

-- Delete spam posts (BE CAREFUL!)
DELETE FROM wp_posts WHERE post_content LIKE '%viagra%';

-- Delete spam comments
DELETE FROM wp_comments WHERE comment_content LIKE '%<a href%';

-- Remove suspicious options
DELETE FROM wp_options WHERE option_name = 'suspicious_option';

⚠️ BACKUP DATABASE FIRST before running DELETE queries!


Replace WordPress Core Files

Download fresh WordPress:

  1. Go to https://wordpress.org/download/
  2. Download latest version (or your current version)
  3. Extract ZIP file locally

Replace core files via FTP:

DO NOT delete these:

  • wp-config.php (your database configuration)
  • wp-content/ folder (themes, plugins, uploads)
  • .htaccess

REPLACE these folders/files:

  • /wp-admin/ (entire folder)
  • /wp-includes/ (entire folder)
  • All files in root (except wp-config.php and .htaccess)

Steps:

1. Connect via FTP
2. Download wp-config.php as backup
3. Delete /wp-admin/ folder from server
4. Delete /wp-includes/ folder from server
5. Upload fresh /wp-admin/ folder
6. Upload fresh /wp-includes/ folder
7. Upload fresh root files (index.php, wp-login.php, etc.)
8. Restore your wp-config.php

Review and Clean Plugins

Identify problematic plugins:

A. Deactivate All Plugins

1. Dashboard → Plugins
2. Select all plugins
3. Bulk Actions → Deactivate → Apply

Can’t access dashboard? Via FTP:

  • Rename /wp-content/plugins/ to /wp-content/plugins-old/

B. Check Each Plugin

For each plugin:

  • Is it from wordpress.org repository?
  • Is it recently updated?
  • Does it have good reviews?
  • Is it nulled/pirated? (DELETE IMMEDIATELY)

C. Delete Suspicious Plugins

Red flags:

  • Unknown plugins you didn’t install
  • Plugins with random names (wp-system, wp-cache, etc.)
  • Nulled/pirated premium plugins
  • Plugins not updated in 2+ years
  • Plugins from unknown sources

D. Reinstall Clean Versions

1. Delete plugin folder via FTP
2. Download fresh from wordpress.org
3. Upload via FTP or
4. Install from Dashboard → Plugins → Add New

Review and Clean Themes

A. Check Installed Themes

Dashboard → Appearance → Themes

Delete:

  • Unused themes (keep only active theme + one default)
  • Themes from unknown sources
  • Nulled/pirated themes
  • Old abandoned themes

B. Scan Active Theme

Check these files in /wp-content/themes/your-theme/:

  • functions.php (most commonly infected)
  • header.php
  • footer.php
  • index.php
  • Any .php files in theme root

C. Download Fresh Theme

If theme is from:

  • WordPress.org: Download fresh copy
  • ThemeForest: Download from your purchases
  • Theme author: Download from official source

D. Replace Theme Files

1. Backup current theme (even if infected)
2. Delete theme folder via FTP
3. Upload fresh theme
4. Reconfigure theme settings if needed

Check Uploads Directory

Scan wp-content/uploads/

Look for:

  • .php files (shouldn’t exist in uploads!)
  • .js files
  • .ico.php files
  • Files with double extensions (.jpg.php)
  • Recently uploaded suspicious files

Find PHP files in uploads:

Via SSH:

bash

find /path/to/wp-content/uploads/ -name "*.php"

Via FTP:

  • Browse uploads folder
  • Sort by “Type” or “Extension”
  • Look for anything except images/videos/documents

Action:

  • Delete any .php files from uploads
  • Check for suspicious image files with code injected
  • Review recently uploaded files

Secure wp-config.php

Add security measures to wp-config.php:

php

<?php
/**
 * WordPress Database Configuration
 */
define('DB_NAME', 'database_name');
define('DB_USER', 'database_user');
define('DB_PASSWORD', 'strong_password_here');
define('DB_HOST', 'localhost');
define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', '');

/**
 * Authentication Unique Keys and Salts
 * Generate new ones at: https://api.wordpress.org/secret-key/1.1/salt/
 */
define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');

/**
 * WordPress Database Table prefix
 * Change from default wp_ to something unique
 */
$table_prefix = 'xyz_'; // Change this!

/**
 * Security Enhancements
 */
// Disable file editing in dashboard
define('DISALLOW_FILE_EDIT', true);

// Disable plugin/theme installation
define('DISALLOW_FILE_MODS', true);

// Limit post revisions
define('WP_POST_REVISIONS', 3);

// Enable automatic updates
define('WP_AUTO_UPDATE_CORE', true);

// Force SSL for admin
define('FORCE_SSL_ADMIN', true);

// Hide WordPress version
define('WP_HIDE_VERSION', true);

/**
 * Debugging (DISABLE on production!)
 */
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);

/* That's all, stop editing! Happy publishing. */
if ( !defined('ABSPATH') )
    define('ABSPATH', dirname(__FILE__) . '/');

require_once(ABSPATH . 'wp-settings.php');

Change these immediately:

  1. Generate new security keys: https://api.wordpress.org/secret-key/1.1/salt/
  2. Change database table prefix (requires database changes too)
  3. Update database password

Set correct file permissions:

bash

# wp-config.php should be 640 or 600
chmod 600 wp-config.php

Update .htaccess File

Replace with clean WordPress .htaccess:

apache

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

# Additional Security Rules

# Protect wp-config.php
<files wp-config.php>
order allow,deny
deny from all
</files>

# Disable directory browsing
Options -Indexes

# Protect .htaccess
<files ~ "^\.htaccess">
order allow,deny
deny from all
</files>

# Block access to wp-includes folder
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>

# Block PHP execution in uploads
<Directory "/path/to/wp-content/uploads/">
<Files "*.php">
Order Deny,Allow
Deny from All
</Files>
</Directory>

# Protect against script injections
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]

Hardening Phase

Set Correct File Permissions

Recommended permissions:

bash

# Directories: 755
find /path/to/wordpress/ -type d -exec chmod 755 {} \;

# Files: 644
find /path/to/wordpress/ -type f -exec chmod 644 {} \;

# wp-config.php: 600 (most secure)
chmod 600 wp-config.php

# .htaccess: 644
chmod 644 .htaccess

Via FTP (FileZilla):

1. Right-click on folder/file
2. File permissions
3. Set numeric value (755 for folders, 644 for files)
4. Check "Recurse into subdirectories" for folders

Enable Two-Factor Authentication

For WordPress Admin:

Method 1: Wordfence 2FA

1. Wordfence → Login Security
2. Two-Factor Authentication → Enable
3. Scan QR code with app (Google Authenticator, Authy)
4. Enter code to verify
5. Save recovery codes

Method 2: Two Factor Authentication Plugin

1. Install "Two Factor Authentication" plugin
2. Users → Your Profile
3. Two-Factor Options → Enable
4. Choose method (TOTP recommended)
5. Scan QR code with authenticator app
6. Test and save

Recommended 2FA apps:

  • Google Authenticator (iOS/Android)
  • Authy (iOS/Android/Desktop)
  • Microsoft Authenticator
  • 1Password (has built-in TOTP)

Limit Login Attempts

Install Limit Login Attempts Reloaded:

1. Plugins → Add New
2. Search "Limit Login Attempts Reloaded"
3. Install and Activate
4. Settings → Limit Login Attempts
5. Configure:
   - Allowed retries: 3
   - Minutes lockout: 20
   - Hours until retries reset: 12
   - Lockout: Increase to 24 hours after 4 lockouts

Change WordPress Login URL

Why? Bots constantly attack /wp-admin/ and /wp-login.php

Install WPS Hide Login:

1. Plugins → Add New
2. Search "WPS Hide Login"
3. Install and Activate
4. Settings → WPS Hide Login
5. Change login URL to something unique:
   - Example: yoursite.com/my-secret-login-page
   - Avoid: admin, login, wp-login
6. Save changes
7. IMPORTANT: Bookmark new login URL!

⚠️ WARNING: Save your new login URL or you’ll be locked out!


Disable XML-RPC (Common Attack Vector)

XML-RPC is used for:

  • Pingbacks
  • Trackbacks
  • Remote publishing
  • Mobile apps

If you don’t need it, disable it:

Method 1: Via Plugin

Install "Disable XML-RPC" plugin
Activate (no configuration needed)

Method 2: Via .htaccess

apache

# Block XML-RPC
<Files xmlrpc.php>
Order Deny,Allow
Deny from all
</Files>

Method 3: Via functions.php

php

// Disable XML-RPC
add_filter('xmlrpc_enabled', '__return_false');

Test if disabled:

  • Visit: yoursite.com/xmlrpc.php
  • Should show error or blank page

Disable File Editing in Dashboard

Already added to wp-config.php, but verify:

php

// In wp-config.php
define('DISALLOW_FILE_EDIT', true);

This prevents:

  • Editing theme files from dashboard
  • Editing plugin files from dashboard
  • Hackers from modifying files if they breach admin

To edit files, you’ll need:

  • FTP access
  • File Manager in cPanel
  • SSH access

Update Everything

Update in this order:

  1. WordPress Core
   Dashboard → Updates
   Update Now
  1. Plugins
   Dashboard → Plugins
   Check for updates
   Update all plugins
  1. Themes
   Dashboard → Appearance → Themes
   Update available themes
  1. PHP Version
   cPanel → MultiPHP Manager
   Select PHP 8.0+ (check theme/plugin compatibility first)
  1. MySQL/MariaDB
   Contact hosting for database version upgrade
   Recommended: MySQL 8.0+ or MariaDB 10.5+

Enable automatic updates:

php

// In wp-config.php
// Core auto-updates
define('WP_AUTO_UPDATE_CORE', true);

// Plugin auto-updates (enable in Dashboard → Plugins)
// Theme auto-updates (enable in Dashboard → Themes)

Check Search Engine Status

Google Search Console:

1. Login to Google Search Console
2. Security & Manual Actions → Security Issues
3. Check for warnings
4. If warnings exist: Request Review

If your site was de-indexed:

1. Search Console → URL Inspection
2. Test live URL
3. Request Indexing
4. Submit updated sitemap

Bing Webmaster Tools:

Similar process for Bing
Check for security warnings
Request recrawl