secaudit.eu
Incidents

Redirection malveillante WordPress : trouver et supprimer

Redirection malveillante WordPress : reproduisez-la avec curl et les outils de dev, repérez-la dans .htaccess, le PHP, la base ou le CDN, et évitez son retour.

Par , AngelForce OÜ 9 min de lecture

Aussi en : English Deutsch Español Italiano Polski Português Türkçe

Une redirection malveillante WordPress est conçue pour que vous, le propriétaire du site, ne la voyiez jamais. Le code piégé vérifie qui visite le site et ne redirige qu'une partie des internautes : les utilisateurs mobiles, ceux qui arrivent depuis Google ou les réseaux sociaux, et souvent chaque visiteur une seule fois. Il épargne en général, volontairement, les utilisateurs connectés et les administrateurs.

Si un client vous écrit « votre site m'a envoyé vers une fausse page de cadeau » alors que tout paraît normal sur votre ordinateur, croyez le client. Les destinations sont typiquement des pages d'arnaque, de faux jeux-concours, des régies publicitaires agressives ou des téléchargements de logiciels malveillants. Google peut signaler le site, et les visiteurs perdent confiance. La redirection n'est qu'un symptôme parmi d'autres ; les autres sont présentés dans 12 signes qu'un site WordPress a été piraté.

Pourquoi le propriétaire ne voit jamais la redirection malveillante

Les conditions sont simples et efficaces. Le code lit l'en-tête User-Agent pour repérer les téléphones et l'en-tête Referer pour repérer le trafic issu des moteurs de recherche. Il teste aussi la présence du cookie de connexion WordPress. Après la première redirection, il pose son propre cookie ou enregistre l'adresse IP pour ne pas rediriger deux fois la même personne.

Cette combinaison explique la plupart des « impossible de reproduire le problème ». Vous êtes connecté, sur un poste de bureau, vous tapez l'adresse directement, et vous avez peut-être déjà été redirigé une fois. Une seule de ces conditions suffit à désactiver la redirection.

Schéma : les couches où peut se cacher une redirection spam, du cache CDN au JavaScript injecté dans le navigateur
Une requête traverse plusieurs couches. Chacune peut porter une redirection, et le type de réponse indique où chercher dans la pile.

Reproduire la redirection sans risque

Avant de fouiller les fichiers, déterminez de quel type de redirection il s'agit. Le type de réponse vous dit quelle couche inspecter.

Commencez dans le navigateur. Ouvrez une fenêtre de navigation privée et vérifiez que vous êtes déconnecté. Ouvrez les outils de développement (F12 dans Chrome, Edge et Firefox) et activez la barre d'appareils (Ctrl+Maj+M) pour émuler un téléphone. Dans l'onglet Network (Réseau), cochez Preserve log (Conserver le journal ; dans Firefox : Persist Logs, dans le menu des paramètres Réseau) pour que les entrées survivent au changement de page. Pour obtenir un vrai référent Google, cherchez votre propre domaine sur Google et cliquez sur le résultat.

Regardez ensuite la première entrée de l'onglet Réseau :

  • **Statut 301, 302, 307 ou 308 avec un Location externe** : la redirection se produit côté serveur. Cela couvre le CDN, les règles du serveur web, PHP et WordPress lui-même.
  • Statut 200, puis une requête vers un domaine étranger : la page s'est chargée normalement, puis du JavaScript (ou une balise meta refresh) a envoyé le navigateur ailleurs. Cherchez un script injecté.

Confirmez ensuite avec curl. Curl n'exécute jamais de JavaScript et ne suit pas les redirections sauf demande explicite. La commande ci-dessous fait une requête GET normale et n'affiche que les en-têtes de réponse ; évitez curl -I, car certains codes injectés ignorent les requêtes HEAD :

curl -s -o /dev/null -D - \
  -A "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1" \
  -e https://www.google.com/ \
  https://example.com/

Une ligne Location: pointant vers un domaine inconnu confirme une redirection côté serveur. Si la ligne de statut affiche 200, récupérez le corps de la page et cherchez-y du code de redirection ou de l'obfuscation :

curl -s -A "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X)" \
  -e https://www.google.com/ https://example.com/ \
  | grep -Eio 'window\.location|location\.href|location\.replace|http-equiv=.?refresh|atob\(|eval\(|fromCharCode|script[^>]+src="[^"]+"'

Refaites le test sans -A ni -e et comparez les résultats. Testez ensuite plusieurs URL : un article de blog, une fiche produit, la page de contact. Beaucoup d'injections ne touchent qu'une partie des modèles de page.

Un résultat propre ne prouve pas que le site est sain. Si le code ne redirige chaque IP qu'une fois, ou ne cible que certains pays, votre test peut passer à côté. Refaites-le depuis un autre réseau, par exemple un téléphone en données mobiles.

Redirections côté serveur : .htaccess, configuration du serveur et PHP exécuté en premier

Si curl montre un 3xx vers un domaine étranger, inspectez le serveur et le code qui s'exécute avant que WordPress n'affiche quoi que ce soit.

Sous Apache, vérifiez tous les fichiers .htaccess, pas seulement celui de la racine web. Cherchez des conditions de réécriture sur le user-agent ou le référent, ainsi que auto_prepend_file. Cette directive force PHP à charger un fichier de l'attaquant avant chaque requête :

grep -rn --include=.htaccess -E "HTTP_(USER_AGENT|REFERER)|auto_prepend_file" .
grep -rn --include=.user.ini --include=php.ini "auto_prepend_file" .

Des lignes RewriteCond %{HTTP_USER_AGENT} légitimes existent, par exemple dans certains plugins de cache. Une règle qui envoie le trafic mobile ou issu de Google vers un domaine que vous ne reconnaissez pas n'est pas légitime.

Listez ensuite les fichiers PHP et de configuration modifiés récemment. Les attaquants peuvent réinitialiser les horodatages : considérez cette liste comme un point de départ, pas comme une preuve. Lancez la commande depuis la racine de WordPress :

find . -type f \( -name "*.php" -o -name ".htaccess" -o -name ".user.ini" \) -mtime -14 -print

Examinez de près tout ce qui a été ajouté en haut ou en bas de wp-config.php et chaque fichier de wp-content/mu-plugins. Les plugins à chargement obligatoire (must-use) se chargent automatiquement et n'apparaissent pas dans la liste normale des extensions. Contrôlez aussi le functions.php du thème actif. Lancez ensuite wp core verify-checksums pour repérer les fichiers du cœur modifiés. Pour savoir lire son résultat et réinstaller le cœur en sécurité, consultez notre guide sur la vérification des checksums WordPress.

Sous nginx, les règles se trouvent dans la configuration du serveur, pas dans .htaccess. Sur un hébergement managé, vous ne pouvez parfois pas les voir. Dans les deux cas, demandez à votre hébergeur de vérifier les règles de redirection et les paramètres de préchargement au niveau du serveur.

Les options siteurl et home

Une variante plus grossière modifie les options siteurl et home. WordPress redirige alors tous les visiteurs vers le domaine de l'attaquant, vous compris. Vérifiez les deux valeurs :

wp option get siteurl
wp option get home

Sans WP-CLI, ouvrez phpMyAdmin et consultez la table wp_options. Le préfixe de vos tables peut différer de wp_ : vérifiez $table_prefix dans wp-config.php. Pour corriger les valeurs :

wp option update siteurl 'https://example.com'
wp option update home 'https://example.com'

Lancez aussi grep -n "WP_HOME\|WP_SITEURL" wp-config.php. Si ces constantes sont définies, elles écrasent les valeurs de la base. Un attaquant peut les y avoir placées, et votre correction dans la base semblera alors sans effet.

Redirections JavaScript dans les articles, widgets, fichiers du thème et scripts d'en-tête

Une réponse 200 suivie d'un saut vers un autre domaine signifie qu'un script s'exécute dans la page. Il peut provenir de plusieurs endroits :

  • Contenu des articles : balises script injectées dans post_content, souvent dans des dizaines d'articles à la fois.
  • Options : lignes de widgets (widget_*), options du thème et réglages des constructeurs de pages dans wp_options.
  • Réglages « Insert headers and footers » : les plugins d'extraits de code et les constructeurs de pages y stockent des scripts valables sur tout le site. Un attaquant disposant d'un accès administrateur n'a qu'une ligne à coller.
  • Fichiers du thème et des plugins : header.php, footer.php et les fichiers JavaScript mis en file d'attente.

Une recherche rapide dans la base (adaptez wp_posts si votre préfixe de tables est différent) :

wp db query "SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%script%src=%';"
wp db search 'fromCharCode' --all-tables
wp option list --search='widget_*' --fields=option_name

Attendez-vous à de l'obfuscation. Le code injecté contient rarement l'URL de destination en clair. Cherchez atob(, de longues chaînes en base64, String.fromCharCode, et des sources de script qui imitent des domaines connus de CDN ou d'analytique avec une orthographe légèrement différente. La technique de recherche dans la base et le nettoyage sont détaillés dans le spam SEO sur WordPress.

Copies en cache : plugin de cache, cache serveur et CDN

Vous pouvez nettoyer entièrement l'origine et voir vos visiteurs redirigés quand même, parce que la page infectée est toujours stockée quelque part. Des copies peuvent subsister dans les fichiers du cache de pages (wp-content/cache), dans un cache d'objets comme Redis ou Memcached, dans le cache serveur de votre hébergeur et sur les serveurs périphériques du CDN.

Purgez dans l'ordre de la requête, de l'origine vers l'extérieur :

  1. Terminez le nettoyage des fichiers et de la base à l'origine.
  2. Videz le cache de pages du plugin de cache.
  3. Videz le cache d'objets avec wp cache flush.
  4. Purgez le cache serveur de l'hébergeur depuis le panneau d'hébergement.
  5. Purgez tout au niveau du CDN.
  6. Refaites les tests avec les commandes curl ci-dessus, avec et sans user-agent mobile et référent Google.

Envisagez aussi le cas inverse : la redirection a été posée au niveau du CDN ou du DNS. Toute personne ayant accès à votre compte CDN peut créer une règle de redirection sans toucher à WordPress. Vérifiez les règles de redirection et de page dans le tableau de bord de votre CDN ainsi que vos enregistrements DNS. Passez en revue qui dispose d'identifiants sur ces comptes, et supprimez les accès devenus inutiles.

Trouver le point d'entrée, sinon la redirection revient

La redirection est la charge utile, pas la brèche. Si vous ne supprimez que la charge utile, elle revient généralement en quelques jours, car l'accès reste ouvert. Les points d'entrée courants sont des plugins vulnérables ou piratés (« nulled »), des identifiants d'administration ou d'hébergement volés, des web shells dans wp-content/uploads et des portes dérobées résiduelles qui réinjectent le code via une tâche cron ou une option de la base.

Un premier contrôle rapide :

  • Administrateurs inconnus : wp user list --role=administrator
  • Mots de passe d'application que vous n'avez pas créés (Utilisateurs > Profil)
  • Événements planifiés inconnus : wp cron event list
  • Fichiers PHP dans uploads : find wp-content/uploads -name "*.php"
  • Plugins et thèmes obsolètes ou piratés (« nulled »)

Une fois la brèche fermée, changez les mots de passe d'administration, d'hébergement, de base de données, SFTP et CDN. Renouvelez ensuite les clés de sécurité (salts) avec wp config shuffle-salts. Cela déconnecte tout le monde. Suivez le plan complet de suppression de malware WordPress pour la préservation des preuves et le choix entre nettoyer et restaurer.

L'attaquant a peut-être aussi pu lire des données de clients, des entrées de formulaires de contact ou des commandes. Dans ce cas, évaluez l'incident comme une possible violation de données à caractère personnel. Voir la notification de violation de données sous 72 heures prévue par le RGPD.

FAQ

Pourquoi seuls les utilisateurs mobiles sont-ils redirigés ?

Les visiteurs sur téléphone remarquent moins facilement une barre d'adresse suspecte et cliquent plus volontiers sur des pages d'arnaque. Les propriétaires, eux, vérifient généralement leur site depuis un poste de bureau, connectés. La condition « mobile uniquement » sert à vous cacher la redirection.

Google affiche « Ce site peut être piraté ». Que faire ?

Nettoyez d'abord le site, fermez le point d'entrée et purgez tous les caches. Demandez ensuite un réexamen dans la Search Console de Google. La procédure est décrite dans le spam SEO sur WordPress. Si vous demandez un réexamen avant que la redirection ait vraiment disparu, il a tendance à échouer.

Un plugin de sécurité peut-il supprimer la redirection à ma place ?

Les scanners aident à la trouver. Ils ne remplacent ni le nettoyage manuel ni la recherche du point d'entrée. Le plugin d'audit de secaudit.eu contrôle l'intégrité des fichiers par rapport à une référence et signale des indicateurs de compromission comme les administrateurs cachés, les événements cron suspects et le spam dans la base. Il recherche aussi le spam SEO caché. Il détecte et signale. Supprimer le code et fermer la brèche reste à votre charge, ou à celle d'un professionnel que vous mandatez.

Vérifiez votre propre site

Security Audit & Compliance est l’extension WordPress de secaudit.eu : elle recherche les logiciels malveillants, le spam caché, les fichiers du cœur modifiés et le code vulnérable, et rattache ses constats à l’article 32 du RGPD, à l’article 21 de NIS2 et à l’OWASP Top 10.

Voir ce que vérifie l’extension
Melike Görel

Melike Görel rédige les guides de secaudit.eu sur la sécurité WordPress et la conformité européenne pour AngelForce OÜ, l’éditeur de logiciels basé à Tallinn qui développe secaudit.eu.

Rédigé avec l’aide de l’IA et vérifié avant publication. Cet article est une information générale et non un conseil juridique.