How to check whether your WordPress site has been hacked
Check from outside first, with Google's Security issues report, its Safe Browsing page, a site search and the page as Google is served it. Then check inside, from administrators and checksums to uploads and the access log. Clean results lower the odds and do not prove the site is clean.
- By
- WP Ministry
- Published
In short
- Start with the checks that need no login. See what Google has flagged, what it has indexed, and what the site serves a stranger.
- Failed logins in a log, a blank page after an update and an emailed demand for money are not a break-in by themselves.
- Checksums cover WordPress itself and plugins from WordPress.org. They say nothing about themes, paid plugins, uploads or the database.
- An administrator nobody created, or a PHP file in uploads that no plugin accounts for, is enough to act on.
- Clean results lower the odds. They do not prove the site is clean.
- When a check comes back positive, stop, write it down and follow the first-hour runbook. Do not delete what you found.
You check for a break-in in two passes. From outside, look at what Google has flagged, what it has indexed under your domain, and what the site serves to someone who is not you. From inside, compare the site with what should be there: the administrators, WordPress's own files, the plugins, the uploads folder, the scheduled events, .htaccess and the access log.
One positive result is enough to act on. A run of clean results lowers the odds and does not prove the site is clean, because each check covers only part of it. None of the checks on this page changes the site. If one comes back positive, write down what you found, leave it where it is, and follow the runbook for the first hour.
What counts as a sign
WordPress's documentation asks you to name the specific symptom, because "hacked" on its own says little. It lists these as clear indicators. Each one has a place where you can confirm it.
| The sign | Where to confirm it |
|---|---|
| A search engine has blacklisted the site, or it is flagged for distributing malware | The Security issues report and the Safe Browsing page, below |
| Visitors say their antivirus flags your pages | The checks from outside, below |
| Your host has disabled the site, or says it is being used to attack other sites | The host's own message. Ask which files or requests it is about. |
| Something happened that nobody authorized, such as a new user appearing | The administrators check, below |
| You can see it when you open the site | Fetch the page without a browser, as shown below, and keep a copy of what came back |
A hack can also show you nothing. Google's guidance for hacked sites describes cloaking: the site gives one page to its owner and another to a search engine, or to a visitor who arrives from one. That is why the outside checks do not rely on what you see when you open your own home page.
What is not a hack
- Failed logins in a log. Password guessing is automated and often comes from many addresses at once. An attempt that failed opened nothing. How to protect WordPress from brute force attacks covers what to do about it.
- A blank page straight after an update. WordPress's documentation gives a plugin or a theme with a compatibility problem as a cause of the white screen. That is a fault, and how to fix the WordPress white screen of death has the steps.
- A site that is down and nothing else. WordPress's documentation notes that your host may be able to confirm whether you are looking at a hack or a loss of service. For the second, use the runbook for a site that is down.
- An email that says the site was hacked and demands money. A message is not one of the signs above. Run the checks on this page. If they find nothing, you have an email and nothing more. If they find something, the runbook says what to do with the demand.
Check from outside
These need no access to the server, so do them first.
Step 1: Open the Security issues report in Google Search Console
The report says whether Google has found hacked content, malware and unwanted software, or social engineering on the site. With no issues, it shows a green check mark and a message. With an issue, it lists example addresses, and Google says that list is a sample, not every affected page. If the site is not in Search Console yet, add it first.
Step 2: Check the Safe Browsing site status
Safe Browsing is the service Chrome and other browsers use to warn a visitor before a dangerous site opens. Enter your address on Google's site status page. It says whether the site currently contains content that Safe Browsing has determined to be dangerous.
Step 3: Search Google for pages you did not write
Type the line below into Google Search, with your own domain. The
site:operator limits the results to one domain, and Google's guidance for hacked sites uses it to uncover pages a hacker added. Look for titles in a language you do not publish in, products you do not sell, and addresses in folders you never made. Add a word your site would never use after the domain to narrow the search. Google notes that the operator does not necessarily return every indexed address, so an ordinary set of results is not the full picture.textsite:example.comStep 4: See a page the way Google is served it
In Search Console, type a page's full address into the inspection bar at the top. Select "Test live URL", then "View tested page". You get the page's code as Google's own crawler received it just now, and a screenshot. Spam words and links that are in Google's copy and not in the page you see are cloaking. Do this for the home page and for any address that looked wrong in the search above.
Step 5: Fetch a page as a visitor arriving from Google
Google's guidance advises against opening a page you suspect in a browser, because malware often spreads through browser vulnerabilities. It recommends fetching the page with and without a Google referrer, since some malware acts only on visitors who come from search results. Run this in a terminal on your own computer. If
diffprints nothing, the two copies are the same. If it prints lines, read them. A block of links, a script from a domain you do not know, or a different page altogether is a positive result.bashcurl -s -o plain.html https://example.com/ curl -s -o from-google.html --referer "https://www.google.com/" https://example.com/ diff plain.html from-google.html
curl does not follow a redirect unless told to, so a page that sends visitors elsewhere saves as a short file or an empty one. The redirect checker shows where an address leads, hop by hop, without your browser opening anything.
The hacked-site check makes the same two requests from our server, compares where each one ends, and reads the page for links hidden from readers and code written to hide what it does. It reports signs, not a verdict.
Check from inside
The first check needs only the dashboard. The rest need SSH access and WP-CLI. Ask your host whether your plan has them.
Step 1: Look for administrators you did not create
In the dashboard, open the Users screen and select the link for the Administrator role above the table. Then list the same accounts from the command line, with the plugins and the theme left out. Every name on both lists should be a person you can account for. Check the email address on each real account too, because a password reset is sent to that address. An administrator nobody created is a positive result.
bashwp user list --role=administrator --fields=ID,user_login,user_email,user_registered --skip-plugins --skip-themesStep 2: Compare WordPress with its checksums
This downloads the checksums WordPress.org holds for your version and compares every WordPress file with them. A clean run prints "Success: WordPress installation verifies against checksums." Otherwise it warns about each file that does not match, and about each file that should not exist. With
--include-rootit also warns about anything in the site's main folder that is not part of WordPress. Some of those files will be yours. It does not look insidewp-content, and it skipswp-config.phpand.htaccess.bashwp core verify-checksums --include-rootStep 3: Compare the plugins with their checksums
This compares each plugin's files with the checksums WordPress.org holds for that plugin and version. A clean run ends with "Success: Verified" and a count. For a failure it lists the plugin, the file, and a message such as "File was added" or "Checksum does not match". Changes to
readme.txtare ignored unless you add--strict. A plugin that did not come from WordPress.org cannot be checked this way: the command warns that it could not retrieve the checksums and skips it. WP-CLI has no checksum command for themes.bashwp plugin verify-checksums --all --skip-plugins --skip-themesStep 4: List the PHP files that changed recently
-mtime -14matches files whose contents changed less than 14 days ago. Set the number to reach back to when you last knew the site was fine. Updates change files too, so compare the list with what you updated and when, and open any file that changed on a day when nobody updated anything. An old date clears nothing, because thetouchcommand lets a file's owner set its modification time to any value.bashfind . -type f -name "*.php" -mtime -14Step 5: Look for PHP files in the uploads folder
WordPress's hardening guide describes
wp-contentas the place for user-supplied content, writable by the web server. The uploads folder inside it is for media, so a PHP file there needs explaining. Open each one this lists. A file that no plugin of yours accounts for, or one filled with long unreadable strings, is a positive result. Leave it where it is.bashfind wp-content/uploads -type f -name "*.php"Step 6: List the scheduled events
WordPress runs timed jobs through its own scheduler, which it checks on every page load. WordPress uses it for update checks and scheduled posts, and plugins add events of their own. The table shows each event's hook and when it runs next.
wp_version_check,wp_update_pluginsandwp_update_themesare WordPress's update checks. For a hook you do not recognize, find the file that names it withgrep -rl "hook_name" wp-content, using the hook's name. A hook that no plugin or theme of yours accounts for goes in your notes.bashwp cron event list --skip-plugins --skip-themesStep 7: Read every .htaccess file
.htaccessis a file Apache reads, one folder at a time. If your site runs on another web server, skip this check. WordPress's documentation calls it one of the files most often changed in a break-in, and notes that copies can sit in other folders as well as the main one. List them all, then compare the one in the main folder with the standard block WordPress writes, shown in how to fix the 403 Forbidden error. Look for a rule that neither you nor a plugin added, above all one that sends visitors to another domain or applies only to visitors arriving from a search engine.bashfind . -name ".htaccess"Step 8: Search the access log
Ask your host for the access log, or download it from the control panel if yours offers one. In Apache's format, each line holds the visitor's address, the time, the request and the status code the server answered with. Search it for requests to PHP files in uploads. A line with status 200 means the file was there and the server answered for it. Look also at requests for dashboard pages such as
/wp-admin/plugins.php. WordPress sends anyone who is not logged in to the login page, so a 200 for one of those, from an address none of your people use, is someone logged in.bashgrep -E "/wp-content/uploads/[^ ]*\.php" access.log
What a scanner adds, and its limits
WordPress's documentation describes two kinds of scanner: remote ones that read the site from outside, and plugins that run on the site. It says each looks for and reports on different things, that no one solution is the best approach, and that using them together improves your odds.
- A scanner that reads from outside sees only what the site serves it. Google's guidance notes that malicious content may be served only to certain user agents or referrers, to avoid detection by site owners and by malware scanners.
- A scanner plugin reads the files on the server, so it can report on code that is never shown to a visitor. It reports what it was built to recognize.
- Free versions differ in what they scan. WordPress security plugins compared sets out what each plugin scans and where it does the work.
Run one as a further check. Its clean result is the same kind of evidence as the others: that scanner found nothing it looks for.
What these checks cannot tell you
- The database. Apart from the users and the scheduled events, nothing here reads it. Google's guidance describes code injected into the database through SQL injection, which no file check sees.
- Themes and paid plugins. The checksum commands do not cover them.
- When something happened. Modification times can be set by hand, and a log reaches back only as far as your host keeps it.
- Anything beyond this one WordPress. WordPress's documentation warns that a hack may reach more than one site, above all on shared hosting, and that many break-ins begin on the owner's own computer.
If everything comes back clean and the doubt remains, run the checks again in a week. WordPress's hardening guide recommends monitoring the site's files for changed and added files, and some of the security plugins in the comparison above do that from then on.
When a check comes back positive
Stop looking. Do not delete the file, the user or the rule you found: the site as it stands is the record of what was done to it. Write down what you found, where, and the time. Then follow the hacked site runbook, which covers the first hour in order. Cleaning comes after that and has its own guide, how to remove malware from a hacked WordPress site.
Get help when:
- a check found code you cannot read, and you cannot tell whether it belongs;
- you cannot run the inside checks and the outside ones leave you unsure;
- the site holds customer accounts, orders or payment details.
Our malware removal service is a one-time clean-up with hardening, a blacklist removal request and a written report.
Common questions
Can a site be hacked with no visible sign?
Yes. Google's guidance describes cloaking, which exists to keep a hack out of the owner's sight: you see your page, and a search engine or a visitor from one sees something else. That is the reason to check what Google has indexed and what the site serves to a request that is not yours.
Google shows no problem. Is the site clean?
It means Google has detected nothing. The Security issues report and the Safe Browsing page tell you what Google found, and neither reads the files on your server. Treat both as one check among the others.
A file fails its checksum. Is that proof of a hack?
It is proof that the file differs from the original. It does not say who changed it. Someone may have edited a plugin by hand. Download the same version of the plugin from WordPress.org and compare the two files. Code that nobody on your side can explain is a positive result.
What can I check without SSH or WP-CLI?
All of the outside checks, the Users screen, and the uploads folder and .htaccess through your host's file manager. For the rest, send your host the commands on this page and ask them to run them.

