Quand un site WordPress commence à “agir bizarrement”, la tentation est grande de réinstaller vite fait. Sauf qu’en pratique, une infection peut rester silencieuse pendant des semaines, le temps de trouver une entrée logique. Parmi les voies d’accès les plus tenaces, il y a les injections via les shortcodes.
Vous ne voyez pas toujours une page qui redirige vers une autre. Parfois, c’est plus discret: un bloc de contenu s’affiche à certains endroits, des scripts se chargent uniquement quand un utilisateur est connecté, ou bien l’affichage d’un article déclenche une requête vers un serveur externe. Les shortcodes sont alors le meilleur point de départ, parce qu’ils sont souvent utilisés dans les thèmes, les builders, et parfois même dans des zones “dynamiques” que personne ne relit.
Dans ce billet, je vais me concentrer sur une façon très concrète de repérer et supprimer ce qui a été injecté dans les shortcodes. Sans promesse magique, avec des angles morts, et avec des méthodes défendables, celles qu’on peut appliquer sur un site réel.
Pourquoi les injections passent par les shortcodes
Un shortcode WordPress est, en simplifiant, une macro: une balise dans le contenu déclenche l’exécution de code PHP (ou de logique) associée. Les attaquants adorent ce mécanisme pour deux raisons.
La première, c’est l’ubiquité. Les shortcodes sont partout: dans les pages, dans les posts, dans les widgets, dans certains templates, et parfois dans des champs custom gérés par des extensions. Si un contenu compromis passe par un shortcode, l’attaque n’a pas besoin de toucher au template global.
La seconde, c’est la discrétion. Un shortcode peut renvoyer une simple chaîne HTML ou au contraire exécuter une logique complète côté serveur. Un code malveillant injecté dans une fonction de shortcode peut par exemple:
- vérifier un cookie ou un rôle utilisateur chercher la langue ou la géolocalisation ne modifier que certaines pages charger un script distant au moment exact où l’utilisateur consulte la page
Résultat: en audit “classique” basé uniquement sur les fichiers les plus modifiés, vous pouvez rater le cœur du problème si la compromission est logée dans une fonction ou dans un contenu de shortcode.
Les signaux qui doivent vous faire penser à un shortcode compromis
Avant d’ouvrir des dizaines de fichiers, j’aime d’abord regarder ce qui est visible. Ce n’est pas du “théâtre”, c’est du tri. Sur un site infesté, certains patterns reviennent.
Voici les symptômes les plus parlants, ceux que j’ai déjà vus sur des infections qui, au final, se ramenaient à des injections liées à des shortcodes:
- apparition de contenu de manière conditionnelle (selon l’URL, la page, l’auteur, le device) chargement de scripts externes inconnus, souvent ajoutés au moment où le shortcode est rendu erreurs PHP sporadiques (notamment après un traitement de contenu ou après un changement de plugin) qui disparaissent parfois une fois le cache vidé redirections “bizarres” sans trace dans les menus ou dans les réglages de redirection messages qui ne s’affichent que pour certains rôles ou en version mobile
Quand ces signaux sont présents, les shortcodes deviennent un suspect raisonnable, surtout si vous retrouvez des balises inhabituelles dans des pages sensibles, des templates, ou des champs d’extensions.
Où chercher en premier: l’écosystème des shortcodes
Sur un site WordPress, un shortcode peut être défini à plusieurs endroits. Le plus fréquent, c’est une fonction PHP dans un plugin ou un thème, avec un registre du type add_shortcode().

Mais l’injection peut aussi se cacher ailleurs:
- dans le contenu lui-même, via une balise [...] placée dans un champ qui accepte les shortcodes dans une extension qui “proxy” des shortcodes, c’est-à-dire qui réécrit ou enrichit le contenu avant rendu dans des fichiers liés à un builder de pages (certains gèrent des composants sous forme de shortcodes ou de dynamiques proches) dans des templates de thème, où une zone “automatique” exécute des shortcodes contenus dans une variable
L’erreur classique, c’est de ne regarder que les shortcodes connus de votre thème, comme si l’attaque ne pouvait pas être dans un plugin tiers. En pratique, les attaquants choisissent souvent une extension populaire, et ils s’accrochent à elle.
Repérer l’injection: méthode d’enquête sans paniquer
La recherche efficace ressemble plus à du travail d’atelier qu’à du “scanning de magie”. Vous voulez réduire le volume de choses à regarder, puis confirmer votre hypothèse.
1) Identifier les pages où le shortcode est rendu
Commencez par les pages qui affichent le comportement anormal. Si l’attaque charge un script, cherchez dans le HTML final ou dans le réseau navigateur ce qui apparaît uniquement sur ces pages.

Même si vous n’avez pas d’accès direct au code final, vous pouvez souvent repérer des indices dans le source rendu: une balise
Le but est de lier le symptôme à une section du contenu. Si vous utilisez un builder, la zone “propre” du contenu peut être trompeuse: l’infection peut venir d’un shortcode dans un champ global.
2) Rechercher les shortcodes présents dans le contenu
Une fois que vous savez quelles pages sont touchées, vérifiez les shortcodes utilisés dans ces pages. Selon la façon dont votre site est configuré, cela se fait dans l’interface WordPress ou directement dans la base de données.
Là, une nuance importante: WordPress stocke le contenu des articles et pages, mais certains plugins transforment ou injectent ensuite. Donc si vous ne voyez pas une balise étrange dans l’éditeur, ça ne veut pas dire qu’elle n’a pas été introduite. Elle peut avoir été ajoutée via des modèles de template, via un champ global, ou via une conversion.
Ce que vous cherchez, ce sont des balises qui n’ont aucune raison d’être là. Par exemple, un shortcode nommé “gallery” ou “button” dans un site qui n’en utilise pas, ou un shortcode “helper” qui n’existe dans aucun plugin que vous avez installé.
3) Chercher l’enregistrement PHP des shortcodes
Quand vous suspectez un shortcode, l’étape suivante consiste à trouver sa définition PHP. Concrètement, cherchez dans le dossier wp-content des occurrences de:
- add_shortcode( shortcode_atts do_shortcode des fonctions qui manipulent content avant rendu
Sur une base saine, add_shortcode ne devrait pas être disséminé dans des fichiers que personne n’a touchés récemment. Sur un site compromis, j’ai souvent vu des définitions ajoutées dans des fichiers dont la taille et la date ne “collent” pas avec l’historique normal du projet.
4) Contrôler le contenu exécutable dans les fonctions
L’injection ne se limite pas à un add_shortcode. Souvent, la vraie charge est cachée à l’intérieur de la fonction associée. Les attaquants aiment masquer l’exécution, par exemple avec:
- concatenation de chaînes encodage base64 appel à eval, assert, preg_replace avec le bon drapeau, ou création de fonctions dynamiques inclusion de fichiers distants ou locaux via include, require, file_get_contents, curl_exec ou fsockopen
Je dis “aiment”, parce que dans le monde réel, certains codes ne sont pas très élégants. Ils sont juste suffisants. Et c’est justement pour ça que la recherche par motifs est utile.
Signes techniques dans les shortcodes qui trahissent une infection
Une fonction de shortcode “normale” renvoie du HTML, éventuellement en utilisant des attributs. Une fonction malveillante ajoute presque toujours une logique qui n’a rien à faire là.
Je pense en particulier à quatre catégories d’indices.
D’abord, les comportements sur URL ou sur variables de contexte. Par exemple, un shortcode qui ne s’exécute que sur une page précise, ou seulement quand un paramètre est présent dans l’URL.
Ensuite, les appels réseau. Si une fonction de shortcode fait un file_get_contents vers une URL, ou un curl, c’est très probablement un problème, sauf si vous avez un plugin explicitement conçu pour ça. Même dans ce cas, le pattern doit correspondre à un besoin clair.
Troisièmement, la modification du contenu retourné. Une fonction peut générer du HTML propre, mais si elle ajoute une balise qui n’a rien à voir avec l’UI attendue, comme un script tiers chargé à chaque rendu, vous êtes en droit de creuser.
Enfin, la manière dont le code “s’habille”. Les attaquants n’en mettent pas forcément beaucoup, mais ils utilisent des techniques pour éviter l’œil humain: variables sans sens, chaînes concaténées, conditions inutiles, et parfois une structure qui ressemble à un morceau de code “copié collé” depuis un autre site.
La recherche par motifs: les indices à vérifier dans vos fichiers
Une fois que vous avez localisé le ou les fichiers qui définissent des shortcodes suspects, passez à une vérification ciblée. L’idée n’est pas de tout lire à la main, c’est de faire ressortir ce qui est anormal, puis de confirmer.
Voici une petite liste de motifs utiles à repérer en priorité dans les fonctions de shortcode, surtout dans les fichiers de plugins et de thème:
- présence de eval(, assert(, base64_decode( ou concaténation systématique de fragments de chaînes appels à des fonctions réseau ou systèmes comme file_get_contents(, curl_exec(, fsockopen(, exec(, system(, shell_exec( preg_replace avec une forme qui permet d’exécuter (selon la version PHP et le pattern exact) inclusion conditionnelle via include ou require avec un chemin construit dynamiquement logique conditionnelle basée sur $_GET, $_POST, $_COOKIE, $_SERVER['REQUEST_URI'] ou sur des rôles utilisateurs
Si vous trouvez plusieurs de ces éléments dans un shortcode, vous n’avez pas besoin d’attendre le “diagnostic” complet. La probabilité devient élevée, et la priorité passe au containment, puis à la suppression contrôlée.
Exemple typique de structure d’injection dans un shortcode
Je peux vous décrire la forme que j’ai le plus souvent observée, sans coller à un code spécifique. Une fonction de shortcode ressemble au début à quelque chose d’inoffensif, elle récupère des attributs puis assemble une sortie HTML.
Et ensuite, au milieu, vous voyez une branche qui ne s’exécute que dans https://gardewp.fr/ certains cas. Elle peut ressembler à une condition du genre “si tel paramètre existe, alors construire une URL à partir de fragments, puis la récupérer ou injecter le résultat”.
Parfois, l’objectif n’est même pas d’exécuter directement une commande. Il peut être simplement d’ajouter un
Le piège, c’est que la sortie principale du shortcode peut rester correcte visuellement. L’utilisateur voit encore une bouton ou une section. Mais sous le capot, le shortcode a une seconde mission.
Contenir avant de “supprimer”: éviter d’empirer
Avant de toucher au code, j’ai appris à faire une étape courte de containment. Sur un site compromis, vous pouvez casser davantage si vous supprimez au hasard.
Deux décisions pratiques reviennent souvent:
1) Couper l’exécution suspecte sans casser le rendu global. 2) Garder une trace de ce que vous avez trouvé, au moins via une copie des fichiers concernés.
Selon votre situation, vous pouvez mettre le site en mode maintenance, ou désactiver temporairement le plugin qui contient le shortcode. Si le site doit rester accessible, vous pouvez aussi désactiver le shortcode en supprimant l’enregistrement ou en neutralisant la fonction, mais uniquement après avoir validé qu’on parle bien du bon shortcode.
Le bon geste, c’est de travailler par test. Vous neutralisez une chose, vous observez, puis vous avancez.
Stratégies de suppression: neutraliser, retirer, puis nettoyer
Supprimer malware WordPress ne veut pas dire juste “effacer un bout de code”. Vous voulez aussi éviter que l’attaque réapparaisse. Souvent, l’injection est couplée à une persistance ailleurs: un fichier modifié, un plugin réinstallé, un utilisateur admin caché, une tâche cron ajoutée, ou un fichier PHP supplémentaire dans un dossier moins visible.

Concernant les shortcodes, les stratégies que j’utilise se déclinent en trois niveaux.
Niveau 1: neutralisation du shortcode suspect
Si vous identifiez clairement le shortcode qui injecte du contenu, vous pouvez temporairement le neutraliser en forçant sa fonction à renvoyer une sortie neutre, ou en supprimant l’enregistrement du shortcode (remove_shortcode si applicable).
Ça permet d’arrêter l’effet immédiat sans casser le reste.
Niveau 2: suppression et restauration contrôlée
Ensuite, vous remplacez le fichier contaminé par une version saine. Si le shortcode est dans un plugin, l’idéal est de réinstaller ce plugin depuis une source fiable, en prenant soin de vérifier que la version réinstallée est bien identique à ce que vous aviez avant l’incident.
Si le shortcode est dans votre thème, vous pouvez restaurer votre thème depuis un tag connu, ou mieux, depuis une version stockée dans un système de versioning. Là encore, l’objectif est de ne pas “patcher” au hasard.
Niveau 3: élimination de la persistance
Une infection via shortcodes peut être la conséquence, pas la cause. La cause peut être un fichier différent, un script qui modifie le plugin à chaque chargement, ou un accès compromise à votre compte.
Donc après la neutralisation et la restauration, vérifiez les autres points de persistance: utilisateurs, cron jobs, fichiers nouvellement créés, tâches planifiées, et variations inhabituelles dans wp-content/uploads ou dans des dossiers temporaires.
Je sais que ce n’est pas exactement ce que vous avez demandé, mais sur le terrain, c’est ce qui évite le “ça a l’air nettoyé, jusqu’à demain”.
Vérifier dans le rendu: confirmer que l’injection ne revient plus
Une fois la suppression opérée, la confirmation doit être factuelle.
Le plus concret est de recharger les pages concernées et de comparer le HTML final. Si vous aviez un script ajouté par le shortcode, il doit disparaître. Si vous aviez un comportement conditionnel, il doit aussi cesser sur les mêmes conditions.
J’ajoute toujours un passage par la logique de cache. Souvent, la version “corrigée” semble ne rien changer parce qu’un cache au niveau serveur ou CDN sert encore l’ancien rendu. Dans ce cas, vous pouvez croire que l’injection est toujours active. Sur un incident réel, j’ai déjà perdu une heure sur ce point.
Alors oui, quand on parle de supprimer malware WordPress, la vérification doit inclure les couches de cache et pas seulement le code.
Cas limites: shortcode existant, mais compromis ailleurs
Le cas le plus frustrant, c’est quand le shortcode “normal” existe déjà dans votre site, mais le malware s’y greffe via une autre couche. Par exemple:
- un hook modifie la sortie juste avant le rendu un filtre WordPress altère le contenu généré une extension de sécurité ou de builder ajoute une logique supplémentaire
Dans ce scénario, vous pouvez trouver la balise dans le contenu, vous pouvez voir le code du shortcode, mais rien ne semble malveillant directement dans la fonction. Pourtant, l’injection se produit.
La solution, c’est de suivre le flux de rendu: cherchez les filtres utilisés sur the_content, ou les actions qui modifient le contenu des pages. Si une extension a été modifiée, elle peut réécrire la logique de rendu autour des shortcodes.
C’est là que l’approche “par motifs” reste utile, mais sur davantage de fichiers que vous ne le pensez au départ.
Réduire le risque après nettoyage
Une fois que le shortcode compromis est neutralisé, la partie qui protège vraiment votre futur ne dépend plus du code malveillant, elle dépend de l’accès.
Sur des sites que j’ai aidés à remonter après suppression malware WordPress, le facteur commun a souvent été un point d’entrée faible: mot de passe réutilisé, plugin obsolète, permissions trop larges, ou clé API exposée.
Je vous propose donc trois actions simples, sans les transformer en usine à gaz:
Réinitialiser tous les mots de passe liés aux comptes WordPress et aux accès FTP ou SFTP. Vérifier les utilisateurs et rôles, et supprimer ceux qui n’ont aucune raison d’être là. Mettre à jour les plugins et thèmes, puis couper l’accès aux plugins non utilisés.Si vous avez besoin de conserver certaines extensions pour des raisons opérationnelles, au moins surveillez leurs fichiers, et assurez-vous qu’elles ne sont pas modifiées hors des mises à jour.
Procédure pratique de diagnostic quand vous êtes coincé
Parfois, vous avez un soupçon, mais pas assez pour agir. Vous voyez un shortcode sur les pages affectées, vous trouvez add_shortcode, mais vous ne savez pas lequel est réellement responsable.
Dans ce cas, je fais un diagnostic en “bascule contrôlée”, étape par étape, sans toucher à tout en même temps. L’objectif, c’est de lier le symptôme à la fonction précise, puis de supprimer seulement ce qui cause le problème.
Voici la logique que je suis le plus souvent, en restant dans un temps raisonnable:
D’abord, j’active temporairement un mode d’observation. J’ouvre la page touchée, je regarde le réseau et le HTML rendu, et je note exactement ce qui apparaît. Ensuite, je neutralise uniquement la définition du shortcode suspect (ou je désactive l’extension qui le porte), et je refais le test sur la même page avec les mêmes conditions. Si le symptôme disparaît, vous avez votre point d’ancrage.
Si le symptôme ne bouge pas, ce n’est pas le bon shortcode, ou alors l’injection est ailleurs. Dans ce cas, je reviens à la liste des shortcodes présents et je répète le raisonnement. Ça paraît répétitif, mais en réalité c’est plus rapide que de “lire tout WordPress” en espérant tomber sur un eval au hasard.
Conclusion de terrain sans slogans: le shortcode comme piste sérieuse
Les injections dans les shortcodes ne sont pas un mythe, et elles ne demandent pas forcément un code spectaculaire pour être efficaces. Souvent, la compromission est suffisamment ciblée pour que les pages “semblent normales” et que l’impact se manifeste seulement dans des détails: un script discret, un chargement conditionnel, une modification d’un fragment de contenu.
Si vous cherchez à supprimer malware WordPress, traitez les shortcodes comme une piste centrale quand vous observez un comportement conditionnel ou une modification qui ne correspond pas à votre logique applicative. Repérez la balise dans le contenu, cherchez l’enregistrement PHP, scannez les motifs typiques, neutralisez, restaurez proprement, puis validez sur le rendu réel en tenant compte du cache.
Si vous voulez, vous pouvez me donner trois éléments et je vous dirai comment structurer l’enquête: le type de shortcode suspect (nom), où il est utilisé (pages, widgets, builder), et le symptôme exact (script externe, redirection, contenu injecté). Avec ces infos, on peut remonter très vite au bon fichier et éviter les fausses pistes.