If your WordPress site is hacked, the first hour is about containment, not cleanup: take a copy of the infected site for evidence, change your hosting, SFTP and admin passwords, and take the site offline or into maintenance mode so visitors are not served malware. Then the real work starts: replacing core and plugins with clean copies, finding every backdoor the attacker left, cleaning injected database content, rotating all credentials, and asking Google to lift its warning. This is the process I follow on every malware cleanup, with the actual commands.
Signs your WordPress site has been hacked
Sometimes it is obvious and sometimes it only shows up for certain visitors. These are the symptoms I see most often:
- Visitors from Google are redirected to a spam, pharma or scam site, while you see the site normally when you type the URL directly.
- Chrome shows a red "Dangerous site" or "Deceptive site ahead" warning.
- Google results show pages you never created, often in Japanese or full of product keywords.
- Admin users you did not create, or your own admin account locked out.
- Your host suspends the account for sending spam or hosting malware.
- A sudden spike in CPU use or outbound email.
The conditional redirect is the one that fools people. Malware often checks the referrer or user agent and hides from logged-in admins, so "it looks fine to me" means very little.
What to do if WordPress is hacked: the first hour
- Back up the infected site. Files and database, as they are now. You need it to find the entry point, and if the cleanup goes wrong you need something to go back to. Store it off the server.
- Change your hosting control panel, SFTP/SSH and database passwords. Do this from a computer you trust; malware on your own machine stealing saved FTP passwords is a real entry point.
- Check who is an administrator and remove anyone you do not recognize.
- Put the site into maintenance mode or restrict it by IP, so you stop serving malware to visitors and Google.
- Tell your host. On shared hosting, other sites on the same account may be infected too, and they will often reinfect yours.
Do not start deleting files at random, and do not simply restore last week's backup and walk away. Without finding how they got in, the attacker usually comes back within days.
# List administrators with WP-CLI
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
# Remove an unknown admin and reassign their content to user 1
wp user delete 57 --reassign=1Verify WordPress core and plugin checksums
WordPress.org publishes checksums for every core release and every plugin in its directory, and WP-CLI can compare your files against them. This is the fastest way to find modified files among the thousands in a typical install.
wp core verify-checksums
# Warning: File doesn't verify against checksum: wp-includes/load.php
# Warning: File should not exist: wp-admin/css/colors/blue/about.php
wp plugin verify-checksums --allAny core file that fails or "should not exist" is suspect. Rather than cleaning core files one by one, I replace core entirely, which leaves wp-content and wp-config.php untouched:
wp core download --version=$(wp core version) --force --skip-contentPlugins from wordpress.org can be reinstalled the same way with wp plugin install <slug> --force. Premium plugins and themes have no public checksums, so download fresh copies from the vendor and replace them. If you find a nulled (pirated) premium plugin, that is very likely how the attacker got in. Delete it; there is no safe way to keep it.
Find the backdoors left behind
Attackers almost never leave just one way back in. Once core and plugins are clean, the backdoors are in the places checksums cannot cover: uploads, the theme, wp-config.php, must-use plugins and server config. These are the checks I run on every cleanup:
# PHP files in uploads should essentially never exist
find wp-content/uploads -type f -name "*.php"
# Must-use plugins load automatically and cannot be deactivated from the dashboard
ls -la wp-content/mu-plugins/
# Files changed recently (adjust the window to when the problem started)
find . -type f -name "*.php" -mtime -14 -printf '%TY-%Tm-%Td %p\n' | sort
# Classic obfuscation patterns
grep -rlE "eval\s*\(\s*(base64_decode|gzinflate|str_rot13)|assert\s*\(\s*\\\$_(POST|GET|REQUEST)" \
--include=*.php .A grep hit is a lead, not a verdict. Some legitimate plugins use base64_decode. What gives backdoors away is the combination: an obfuscated blob, input taken straight from $_POST or a cookie, and a file name designed to blend in, like wp-cache.php in a theme folder.
Also check:
.htaccessfiles in every directory, for redirect rules based on the referrer or user agent.wp-config.php, for an extraincludeat the top or bottom.- Cron jobs, both WordPress (
wp cron event list) and the system crontab (crontab -l), which is where reinfection scripts like to hide. - The access logs: search for POST requests to the malicious files you found. The earliest one usually shows how the attacker got in.
Finding the entry point matters more than anything else in this guide. If it was a vulnerable plugin, update or remove it. If it was a stolen password, find where it leaked. If another site on the same hosting account was the source, it has to be cleaned or removed too, because PHP running as the same user can write to every site in that account. On a VPS, I also check for unexpected SSH keys in ~/.ssh/authorized_keys, unknown system users and listening processes, and I tighten the server itself as described in my server security hardening work. A clean WordPress install on a compromised server stays clean for about as long as it takes the attacker to notice.
Clean database injections
A lot of WordPress malware lives in the database, not in files, which is why file scanners miss it. The usual places are injected scripts in post content, malicious values in wp_options, and rogue users or capabilities. Replace wp_ with your table prefix:
-- Scripts or iframes injected into posts
SELECT ID, post_title FROM wp_posts
WHERE post_content LIKE '%<script%' OR post_content LIKE '%<iframe%';
-- Site URLs changed to redirect elsewhere
SELECT option_name, option_value FROM wp_options WHERE option_name IN ('siteurl','home');
-- Options containing obfuscated code
SELECT option_name FROM wp_options WHERE option_value LIKE '%eval(%' OR option_value LIKE '%base64_decode%';
-- Users with admin capabilities, whatever their visible role
SELECT user_id FROM wp_usermeta WHERE meta_key = 'wp_capabilities' AND meta_value LIKE '%administrator%';Some legitimate posts contain scripts, such as embedded forms or analytics snippets, so review each hit before removing anything. Take a database backup before you run any UPDATE or DELETE.
Rotate every credential
Assume the attacker read wp-config.php, which means they have your database password and your salts. Rotate everything:
- Salts and keys —
wp config shuffle-salts. This logs out every session, including the attacker's. - Database password — change it in MySQL, then update
DB_PASSWORDinwp-config.php. - Every WordPress user's password, starting with administrators and editors, plus application passwords.
- API keys stored on the site: payment gateways, SMTP, cloud storage, and any
define()d secrets. - Hosting, SFTP and SSH, again, now that the site is clean.
Then update everything, delete unused plugins and themes, turn on two-factor authentication for admins, and set define('DISALLOW_FILE_EDIT', true); so a stolen admin login cannot edit PHP from the dashboard. My WordPress security checklist covers the full hardening list, and I do it as ongoing work through WordPress security and maintenance.
Google blacklist removal: requesting a review
If Google flagged the site, the warning stays until you ask Google to check again. In Search Console, open Security & Manual Actions → Security issues. It lists the problem type and often sample URLs. Make sure every listed URL is clean, and that spam pages the attacker created now return 404 or 410. Then click Request review and describe what you found and fixed.
Google says malware reviews can take several days. Do not request a review until you are confident, because repeated failed reviews can mean a longer wait. If your host or an email blocklist also flagged you, each has its own delisting process.
Cleaning a hacked site properly takes a few hours of careful work, and missing one backdoor means doing it all again next week. If you would rather hand it over, my WordPress malware removal service covers the full cleanup, the entry point, credential rotation and the Google review. Small jobs are billed at $20/hour; a complex hacked WordPress site cleanup gets a fixed price agreed in writing before I start.
Frequently asked questions
Can I just restore a backup to fix a hacked WordPress site?
Only if you know the backup predates the infection and you also close the hole that let the attacker in. Otherwise you restore a site that is either still infected or gets reinfected within days. Restoring also loses every order, post and comment made since the backup was taken.
Will a security plugin remove the malware for me?
Security plugins are good at finding known malware signatures, and they catch a lot. They routinely miss custom backdoors, malicious admin accounts, injected database content and cron jobs outside WordPress. Treat a clean scan as one input, not proof that the site is clean.
How did my WordPress site get hacked?
In my experience the common entry points are outdated plugins with published vulnerabilities, nulled premium themes or plugins that ship with backdoors, reused or leaked admin passwords, and other compromised sites on the same hosting account. Your access logs around the time of the first malicious file usually show which one.
Should I tell my customers?
If the site handled personal data or payments and there is any chance it was accessed, you may have a legal duty to notify people, depending on where you and your customers are. Get proper advice on that; it is a legal question, not a technical one.