Skip to content
The site is hacked

The site sends visitors to spam

The code may only fire for visitors who come from Google or use a phone, so you never see it yourself. How to find the code behind it.

You need
FTP
Updated

When visitors are sent on to a spam site, there is malicious code on your site. The code is built to hide. It reads the Referer and User-Agent of each request and only redirects visitors who come from Google or use a phone. If you're logged in or type the address yourself, you get the normal page. That is why the site looks fine when you check it.

The redirect can be in .htaccess, in a PHP file or in a script stored in the database. Work through the places below in order.

See what visitors see

  1. Open a private window on your phone, search Google for your company name and tap the result. Do the same on your computer.
  2. If you have Search Console, paste the address into URL Inspection and run a live test. The screenshot shows the page as Google sees it. If it isn't your page, the redirect is confirmed.
  3. Note the domain you're sent to. You'll need it when you search the files and the database.

With curl you can imitate a mobile visitor arriving from Google:

curl -sI -A "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)" -e "https://www.google.com/" https://example.com/

If the response shows status 301 or 302 and a Location header pointing to another domain, the redirect happens on the server. A JavaScript redirect doesn't show in the headers, only in the HTML.

Also scan the site with Sucuri SiteCheck. It looks for known malware and checks whether the domain is on any blocklists. If Google has flagged the site as dangerous, Google Safe Browsing shows it.

Check wp-admin

  1. Go to Settings → General. Both "WordPress Address (URL)" and "Site Address (URL)" should be your own domain.
  2. Go to Users and look for administrators you don't recognise.
  3. Go to Plugins and look for plugins you didn't install. If there is a "Must-Use" tab, it lists files in wp-content/mu-plugins, which run without being activated.
  4. If you use a plugin that inserts code into <head> or before </body>, such as WPCode, go through its snippets and look for scripts from domains you don't know.

Check .htaccess

Connect with FTP or the file manager in your hosting panel and show hidden files. In the .htaccess file in the root folder, the WordPress block looks like this, plus a few comment lines:

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

Cache and security plugins can add their own blocks, marked with their name. Be suspicious of lines containing HTTP_REFERER or HTTP_USER_AGENT, and of rules that send visitors to another domain. Also check .htaccess in subfolders such as wp-content and wp-content/uploads.

Check the PHP files

  • index.php in the root folder is only a few lines that load wp-blog-header.php. If it's long or full of unreadable code, it has been changed.
  • Look at the top of wp-config.php for code that doesn't belong there, such as an include or require of a file with an unfamiliar name.
  • The auto_prepend_file setting makes PHP run a file before every page. It can be set in .user.ini or php.ini in the root folder, or as php_value auto_prepend_file in .htaccess. Wordfence uses it for its firewall and points it to wordfence-waf.php. Any other file name needs a closer look.
  • Read through functions.php and header.php in the active theme.

In all of these files, look for eval, base64_decode, gzinflate and str_rot13, especially next to long strings of random characters.

With SSH and WP-CLI, wp core verify-checksums compares the WordPress files with the originals from wordpress.org, and wp plugin verify-checksums --all does the same for plugins from wordpress.org. Both list files that have been changed or added.

Search the database

  1. Export the database before you change anything.
  2. Open phpMyAdmin from the hosting panel and search the whole database for the domain you were sent to, and for <script.
  3. Pay special attention to hits in the wp_options and wp_posts tables. The table names may start with something other than wp_.

Don't delete rows you don't understand. Remove only the code the attacker added.

Be extra careful with values in wp_options that start with a: and have a number such as s:12: before each piece of text. The number is the length of the text in bytes, and letters such as é, ü and ø count as two. If you change the text without fixing the number, the setting stops working. Where you can, change such values in wp-admin instead.

When you're stuck

If the redirect comes back after you removed the code, either a backdoor is left somewhere else, or the security hole the attacker used is still open. It can also be both. Then someone has to clean the whole site and go through the server logs, which takes access to the hosting and experience with WordPress security. If you find nothing in WordPress, the redirect may be in the server configuration, and then your hosting provider has to track it down.