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
- Open a private window on your phone, search Google for your company name and tap the result. Do the same on your computer.
- 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.
- 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
- Go to Settings → General. Both "WordPress Address (URL)" and "Site Address (URL)" should be your own domain.
- Go to Users and look for administrators you don't recognise.
- 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. - 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.phpin the root folder is only a few lines that loadwp-blog-header.php. If it's long or full of unreadable code, it has been changed.- Look at the top of
wp-config.phpfor code that doesn't belong there, such as anincludeorrequireof a file with an unfamiliar name. - The
auto_prepend_filesetting makes PHP run a file before every page. It can be set in.user.iniorphp.iniin the root folder, or asphp_value auto_prepend_filein.htaccess. Wordfence uses it for its firewall and points it towordfence-waf.php. Any other file name needs a closer look. - Read through
functions.phpandheader.phpin 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
- Export the database before you change anything.
- Open phpMyAdmin from the hosting panel and search the whole database for the domain you were sent to, and for
<script. - Pay special attention to hits in the
wp_optionsandwp_poststables. The table names may start with something other thanwp_.
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.