Scanner malware WordPress : détecter les injections via les widgets

Quand on parle de “malware WordPress”, on pense souvent à des scripts cachés dans des fichiers PHP, des backdoors, ou des redirections au niveau du serveur. Dans la pratique, j’ai vu plus d’une campagne où le point d’entrée n’était ni un plugin exotique ni une modification directe du thème, mais quelque chose de plus discret: une injection passée par les widgets.

Un widget, surtout s’il est manipulable côté tableau de bord sans validation stricte, peut devenir un véhicule. Et comme les widgets sont parfois visibles dans l’interface, beaucoup d’administrateurs mettent un peu moins l’attention dessus. Résultat: le site continue “à fonctionner”, mais des contenus s’insèrent de manière irrégulière, parfois seulement pour certains navigateurs, parfois seulement sur certaines pages, parfois après une mise en cache.

Cet article se concentre sur un angle très concret: comment utiliser un scanner malware WordPress, mais aussi comment analyser l’origine via les widgets pour repérer une injection. Je vais expliquer ce qui se passe vraiment, comment on s’en rend compte, ce qu’il faut contrôler, et comment éviter les faux positifs qui font perdre du temps.

Pourquoi les widgets sont une porte d’entrée crédible

WordPress a toujours eu cette philosophie “administration facile”. Les widgets permettent de déposer du contenu dans des zones spécifiques, parfois en HTML libre, parfois avec des options plus ou moins filtrées selon le thème et la configuration.

Une injection via un widget peut ressembler à plusieurs scénarios:

    un widget “Texte” ou “HTML personnalisé” qui contient un script ou une balise iframe, un widget lié à une extension (ou à un constructeur de page) qui autorise des paramètres dynamiques, un widget qui n’a pas l’air “méchant” dans le tableau de bord, mais qui pointe vers une URL qui change ou qui dépend d’un agent utilisateur, un contenu qui ne s’affiche que sur certaines pages, ou après un intervalle de temps, grâce à du JavaScript conditionnel.

Le piège, c’est que la plupart des scans de fichiers cherchent d’abord des signatures dans le code PHP du noyau, des plugins et du thème. Les injections de widgets, elles, peuvent vivre dans la base de données, ou dans des options sérialisées, ce qui ne déclenche pas toujours les mêmes alertes.

De mon côté, j’ai déjà vu une redirection “discrète” qui ne touchait que les pages d’archives, parce que le widget injecté était ajouté dans une zone de sidebar utilisée sur ces pages, et que le code vérifiait la route dans l’URL. Un scanner “sur fichiers” n’avait rien trouvé d’anormal. C’est l’inspection de la sortie côté navigateur, puis la recherche dans les contenus de widgets, qui a tranché.

Comprendre ce que le scanner malware WordPress peut et ne peut pas voir

Quand vous lancez un scanner malware WordPress, vous cherchez généralement trois choses: des modifications de fichiers, des ajouts de fichiers inconnus, et parfois des indicateurs dans la base de données. Mais selon l’outil, la profondeur varie fortement.

Un scanner peut:

    repérer des fichiers modifiés dans wp-content/plugins et wp-content/themes, signaler des motifs typiques de webshell ou de fonctions d’évaluation de code, détecter certains patterns dans la base de données si l’outil sait où regarder, proposer une liste de “fichiers suspects” avec score.

Un scanner peut aussi rater:

    des injections qui ne touchent pas de fichiers, uniquement des options et contenus en base, des données sérialisées où le “script” est fragmenté ou encodé, des traces effacées, par exemple si l’attaquant n’a gardé que la donnée utile et a supprimé les éléments qui auraient déclenché le scan initial, des injections qui n’apparaissent qu’après conditions (cache, géolocalisation, agent utilisateur).

La bonne stratégie, c’est d’utiliser le scanner malware WordPress comme boussole, pas comme verdict. S’il ne voit rien, ce n’est pas un “tout est clean”. Cela peut simplement signifier que la compromission n’est pas dans les zones couvertes par l’analyse.

Les signaux qui doivent vous pousser à regarder les widgets

Avant même d’ouvrir la base de données, observez la réalité. Les injections via widgets laissent souvent des traces d’affichage, même si elles sont “propres” au premier coup d’œil.

Voici les indices typiques que j’ai rencontrés:

    un bloc de contenu qui apparaît uniquement sur certaines pages, souvent celles qui utilisent la même sidebar, des scripts qui se chargent depuis des domaines externes, avec un motif de tracking, d’analytics falsifié, ou de redirection, des changements “mystérieux” dans l’interface WordPress: un widget dont le contenu ne correspond pas à ce que l’équipe marketing y a mis, des performances qui se dégradent subitement, avec des requêtes réseau nouvelles et répétitives, des différences visibles entre deux navigateurs, ou entre mobile et desktop.

La première fois que je me suis fait surprendre par un widget, c’était un site qui affichait un “module” dans la sidebar. Aucun plugin suspect, aucune modification de thème visible. Mais dans l’inspection du navigateur, on voyait un script chargé, puis un élément injecté après coup. En regardant le contenu du widget, le script était là, mais le contenu affiché semblait “inoffensif” parce que le code modifiait le DOM ensuite.

Vérifier l’affichage côté navigateur avant de fouiller partout

Le plus efficace, c’est de combiner scanner malware WordPress et analyse de la sortie HTML.

Ouvrez l’inspection du navigateur (onglets Elements et Network), rechargez la page concernée, puis cherchez:

    des scripts ajoutés après coup, des iframes, des requêtes vers des domaines inhabituels, des erreurs JavaScript liées à du code qui tente de s’exécuter, des éléments injectés dynamiquement.

Ce travail a un avantage pratique: il vous donne une cible. Si vous observez qu’un script s’exécute uniquement sur une page précise, vous savez déjà quel template et quelle zone de widgets est probablement en jeu.

Une règle simple me sert souvent: si l’injection vient d’un widget, elle suit généralement l’emplacement d’affichage du widget dans le thème. Donc l’observation côté navigateur aide à associer la page à la zone.

Où chercher les injections dans l’administration WordPress

Dans l’interface, le piège est de croire que “si je ne vois pas de fichier modifié, c’est bon”. Pour les widgets, c’est l’inverse. La base de données peut contenir des contenus injectés même si l’UI montre “quelque chose”.

Contrôlez:

    Widgets de type “Texte” ou “HTML personnalisé” dans toutes les zones disponibles, widgets liés à des zones globales, par exemple une sidebar utilisée par plusieurs modèles, widgets ajoutés par des thèmes ou des builders (certains exposent des zones qui ressemblent à des widgets standard), contenu “dans le style” du site, mais avec des scripts cachés.

Si votre site utilise des mises en cache, vérifiez le comportement avec cache vidé et hors session admin. L’attaquant peut compter sur un effet de cache pour retarder la détection. Je l’ai vécu sur un WordPress avec un cache agressif: en tant qu’admin connecté, on voyait la page “normale”, et pour les visiteurs, l’injection apparaissait.

Avant de paniquer, notez les différences entre:

    vue connectée vs déconnectée, page normale vs page via paramètre, mobile vs desktop.

Ces variations orientent vers une injection conditionnelle.

Utiliser le scanner malware WordPress sans se faire piéger par les faux positifs

Un scanner peut vous annoncer des “signatures” qui ressemblent à du malware, mais qui peuvent être issues de scripts légitimes, de publicités, ou de trackers. Le contenu d’un widget est particulièrement sujet à ce problème, car c’est justement l’endroit où l’on colle des codes externes.

Le bon réflexe, c’est de ne pas “désactiver tout”. Prenez le temps de recouper avec le navigateur.

Un workflow qui m’a évité de casser un site:

1) Lancer un scan complet et noter les éléments signalés, en particulier tout ce qui touche wp-content et la base si le scanner le propose.

2) Ouvrir la page concernée et confirmer si le code suspect s’exécute. 3) Chercher si la donnée correspond à un widget existant, ou si elle ressemble à du code embarqué dans un fichier.

Si vous voyez un domaine inconnu dans Network et que, dans l’administration, un widget texte contient exactement ce domaine, vous tenez le fil.

Si le scanner vous signale un pattern dans un widget, mais que le code ne s’exécute pas et que la page n’envoie pas de requête correspondante, c’est peut-être un faux positif. La prudence ici, c’est d’éviter la suppression “à l’aveugle” qui pourrait casser une fonctionnalité légitime.

Analyse ciblée des widgets: la méthode qui marche vraiment

Une fois que vous suspectez une injection de widget, l’objectif est de retrouver la source exacte du contenu. Selon votre environnement, vous pouvez procéder de deux manières: inspection admin, ou extraction depuis la base.

En administration, c’est souvent plus rapide. Mais si l’attaquant a modifié le rendu sans que le contenu soit clairement visible, ou si la page du widget est difficile à interpréter (contenu encodé, HTML minimal), il faut aller plus profond.

Voici ce que je fais généralement, dans l’ordre:

    d’abord, retrouver la zone et le modèle de la page où le contenu apparaît, ensuite, identifier quels widgets sont assignés à cette zone, enfin, vérifier le contenu exact de chaque widget “texte/HTML” et toute autre zone où un code peut être injecté.

Si vous avez accès au thème et aux fichiers de templates, vous pouvez aussi voir comment les sidebars sont enregistrées et quelles zones sont utilisées. Cela réduit l’espace de recherche.

Si vous n’êtes pas sûr, prenez une page où l’injection est visible, désactivez le widget candidat, puis rechargez en navigation privée. Si l’élément disparaît, vous avez identifié la source.

Un mini plan de validation rapide

Voici un petit protocole, simple, qui évite beaucoup d’erreurs:

Choisir une page où l’injection s’affiche clairement. Ouvrir les outils développeur, vérifier les requêtes réseau liées au code suspect. Dans WordPress, désactiver temporairement le widget candidat (ou le retirer de la zone). Recharger en navigation privée pour observer la différence. Si disparition, remplacer par un contenu propre, puis surveiller 24 à 48 heures.

Ce test direct est souvent plus fiable que de “deviner” sur la base du code visible.

Chercher dans la base de données quand l’interface ne suffit pas

Quand l’interface ne donne pas une lecture évidente, ou que le widget est présent mais pas sous la forme attendue, la base de données devient le terrain de vérité.

Sans entrer dans des recettes risquées, le principe reste simple: WordPress stocke les widgets et leurs paramètres en base. Selon les versions et les configurations, les contenus peuvent être sérialisés et stockés dans des champs d’options.

image

Ce que je recommande, avant toute modification:

    faire une sauvegarde complète (fichiers et base), travailler sur une copie si vous êtes en environnement de préproduction, limiter les suppressions au strict nécessaire.

Ce n’est pas “dangereux” parce que c’est une base, c’est dangereux parce qu’on peut casser une sérialisation et perdre la configuration des widgets, parfois sans possibilité simple de récupération.

Sur les incidents que j’ai traités, les cas où la base était nécessaire arrivaient quand:

    plusieurs widgets semblaient “propres” à l’œil, mais le navigateur montrait une exécution qui ne correspondait à aucun contenu visible, le contenu était encodé, compressé, ou chargé depuis un endpoint qui n’apparaissait pas tel quel dans le texte affiché, le thème rendait les widgets de manière spéciale, transformant des paramètres au moment de l’affichage.

Dans ces situations, l’extraction des champs pertinents, puis la recherche de fragments de chaînes identifiées côté navigateur, fait gagner un temps énorme. Par https://gardewp.fr/nettoyage-malware-wordpress/ exemple, si dans Network vous voyez une URL, cherchez des fragments de cette URL dans les données de widgets.

Comment distinguer une injection via widget d’une compromission plus large

Un autre piège, c’est de traiter uniquement le symptôme. Si l’attaquant a accès à l’administration pour ajouter ou modifier des widgets, il peut aussi avoir pris un contrôle plus large: compte admin compromis, fichier modifié, ou accès persistant.

C’est pour ça que je garde toujours en tête la question suivante: “Est-ce que le widget a été modifié parce qu’un compte a été compromis, ou parce qu’un plugin/une mise à jour a introduit une ouverture?”

Les check points qui orientent:

    comptes: présence de nouveaux utilisateurs, notamment avec rôles élevés, modifications: changements sur wp_options et wp_users autour du moment de l’incident, plugins: nouveaux plugins installés ou versions inattendues, thèmes: fichiers modifiés, même légèrement, sur les dates proches.

Ici, le scanner malware WordPress sert aussi à regarder au delà des widgets. Si le scan signale des fichiers modifiés dans wp-content, on ne peut pas se limiter au widget. Si au contraire tout est clean côté fichiers mais qu’un seul widget contient le code, la compromission peut être plus “localisée”, même si elle reste un signe d’accès.

Ce que je fais après avoir neutralisé le widget

Il y a une différence entre “enlever le contenu” et “éradiquer la cause”. Après correction, je vérifie au minimum:

    que le compte admin responsable n’a pas été modifié (mots de passe, rôles, sessions), que le formulaire d’ajout de contenu n’accepte pas de code dangereux si votre politique de sécurité le refuse, que le site ne réinsère pas le contenu au prochain chargement.

Ce dernier point arrive plus souvent qu’on ne croit: on retire un script du widget, puis il réapparaît parce qu’un mécanisme ailleurs l’alimente. Là, l’analyse devient plus large.

Durcir la configuration pour limiter les injections via widgets

Neutraliser une injection est nécessaire, mais sans durcissement, vous êtes exposé à la répétition.

Le durcissement dépend de votre profil d’usage. Un site vit souvent grâce à des widgets, mais on peut réduire la surface d’attaque.

Sans faire de promesses, voici les mesures qui réduisent le risque dans la pratique:

    limiter qui peut modifier les widgets, en particulier le rôle “admin”, renforcer la politique de gestion des rôles (moins d’utilisateurs avec trop de permissions), surveiller les modifications de contenu et les changements d’options, contrôler le contenu autorisé dans les widgets qui acceptent du HTML.

Selon la stack, on peut aussi mettre en place des politiques de nettoyage du contenu, en gardant à l’esprit que les faux positifs peuvent casser des intégrations légitimes, notamment des embeds et scripts marketing.

La règle que j’applique: durcir sans casser. Je préfère une approche progressive, un test sur un sous ensemble de pages, puis une règle plus stricte une fois que l’équipe comprend ce qui est autorisé.

Cas particuliers: thèmes builder, iframes et contenus “marketing” qui ressemblent à du malware

Un widget injecté, ce n’est pas toujours un script obstrué. Parfois, c’est un iframe, ou un embed qui semble marketing. La nuance, je la vois souvent dans les destinations et le comportement au chargement.

Si vous utilisez des services légitimes (tag manager, pixels, chat), l’architecture ressemble. La différence se joue sur:

    les domaines réellement utilisés, l’activation conditionnelle (qui reçoit quoi), la présence de redirections ou de scripts qui modifient le HTML sans logique métier.

Pour trier rapidement, je m’appuie sur deux observations:

1) Est-ce que le widget charge des ressources qui ne figurent nulle part dans votre documentation interne ou dans vos intégrations connues ?

2) Est-ce que le comportement affiché correspond à ce que vous attendez, ou bien est-ce que le code “fait quelque chose de plus” (injection de nouveaux liens, tracking douteux, redirection) ?

C’est là que l’inspection réseau et l’affichage en navigation privée valent plus que dix captures d’écran.

Une stratégie de réponse cohérente quand l’injection est confirmée

Quand vous confirmez une injection via widget, votre réponse doit être à la fois technique et opérationnelle. Le technique, c’est retirer le code et vérifier la persistance. L opérationnel, c’est comprendre comment l’accès a été obtenu.

J’ai vu des équipes se concentrer uniquement sur le widget. Le contenu disparaît, tout semble aller mieux, puis une semaine plus tard un autre module apparaît, parce que le compte compromis n’avait pas été traité ou parce qu’un token restait valide.

La réponse complète doit inclure:

image

    changement de mots de passe des comptes ayant des rôles sensibles, révocation des sessions actives si c’est possible, audit des utilisateurs et des rôles, vérification des plugins et thèmes, scan malware WordPress à nouveau après suppression, pour vérifier qu’il n’y a pas de résidus.

Et surtout, garder une trace: date de l’incident, page touchée, widget exact, fragments de code observés. Cela facilite le diagnostic si un autre site du même réseau est affecté.

Pièges fréquents pendant le diagnostic

Je termine avec une poignée de pièges que j’ai rencontrés, parce qu’ils font dérailler même une analyse sérieuse.

    Se fier uniquement au scanner, sans vérifier la sortie réelle dans le navigateur. Supprimer le widget, puis ne pas vérifier les comptes et l’accès, ce qui laisse un mécanisme de réinjection. Confondre un embed légitime avec un script d’injection, surtout si les domaines externes sont connus mais si le comportement est anormal. Interpréter trop rapidement des alertes de “base de données” sans recouper avec le rendu visible, ce qui peut conduire à des suppressions non nécessaires.

Le bon diagnostic tient souvent dans un recoupement: une observation côté navigateur, une corrélation avec le widget, puis une validation en désactivant ce widget et en surveillant.

image

Ce que j’attends d’un bon outil de détection pour les widgets

Dans un incident “injection via widgets”, un scanner malware WordPress utile ne se contente pas de dire “suspect”. Il doit aussi faciliter la corrélation.

Concrètement, j’attends au minimum:

    un signal sur les contenus stockés en base quand c’est couvert, une capacité à revenir rapidement sur les zones possibles (widgets, options, thèmes), des indications qui permettent de retrouver la donnée exacte, pas seulement une alerte générique.

Même avec un excellent outil, je garde l’inspection réseau comme arme de vérité. Les meilleurs scans gagnent en pertinence quand ils sont combinés à ce que le visiteur reçoit vraiment.

Pour aller plus loin sans se disperser

Si vous gérez plusieurs sites WordPress, je conseille d’adopter une routine d’observation, pas seulement une routine de scan. Un scanner, vous le lancez quand ça sent mauvais. L’observation, vous la faites aussi quand tout semble normal, par exemple en surveillant les variations de contenu sur des pages clés, ou en gardant une trace des modifications récentes de widgets.

C’est souvent ce qui vous permet de répondre vite quand “quelque chose a changé” sans vous obliger à diagnostiquer en urgence à chaque alerte.

Si vous voulez, dites-moi votre contexte (hébergement, cache utilisé, thème builder ou thème classique, et ce que vous avez vu dans les outils développeur, par exemple une redirection ou une iframe). Avec ces détails, je peux vous proposer un chemin de vérification plus précis, orienté vers l’origine exacte dans les widgets, et une façon de confirmer sans casser la mise en page.