Quand on découvre qu’un site WordPress est compromis, l’urgence est réelle, mais la panique coûte cher. Entre “tout casser et restaurer” et “tout analyser pendant des jours”, il existe une voie plus rationnelle: comparer ce qui est en place avec une version officielle, puis décider ce qu’on remplace, ce qu’on vérifie et ce qu’on ignore. Cette approche marche particulièrement bien quand l’infection touche le code (fichiers modifiés, fichiers ajoutés, scripts lancés au mauvais moment) plus que la simple prise de contrôle via des comptes.
Le but n’est pas de prouver que c’est “infecté” à un tribunal. Le but est de réduire l’espace de recherche, d’identifier les écarts concrets, et de reprendre la main sans laisser un morceau de porte dérobée.
Ce que “comparer avec une version officielle” veut dire, concrètement
Beaucoup de gens pensent qu’il suffit de télécharger la dernière version de WordPress, de comparer les dossiers, et de repérer les différences. En pratique, la comparaison doit tenir compte de trois réalités.
Première réalité: un site n’est jamais “un WordPress nu”. Vous avez presque toujours des plugins, des thèmes, parfois des fichiers mu-plugins, du cache, ou des modifications de configuration (php.ini, wp-config.php, htaccess, environnements de déploiement). Si vous comparez “tout”, vous obtiendrez une tempête de différences sans valeur.
Deuxième réalité: une infection peut ne pas modifier les fichiers du noyau. Elle peut par exemple vivre dans un plugin déjà existant, injecter du code via des templates de thème, modifier un fichier .php discret dans wp-content, ou ajouter une tâche planifiée si cron côté serveur est accessible.
Troisième réalité: une version officielle doit être la bonne, pas juste “la dernière”. Si votre site est en 6.3.2 et que vous comparez avec 6.5.x, vous allez confondre des écarts légitimes avec des modifications malveillantes.
Comparer avec une version officielle, c’est donc un processus de correspondance, pas un téléchargement automatique. Vous partez de la version exacte du noyau, puis vous comparez avec intelligence, en concentrant l’attention sur ce qui ne devrait pas changer, et en surveillant ce qui, sur un WordPress “normal”, reste très stable.
D’abord, vérifier le socle: quelle version exacte et quelles modifications attendues
Avant de lancer la comparaison, je commence par “figer” le contexte. Sur un WordPress compromis, le contexte peut bouger vite, surtout si le site est encore accessible publiquement.
Sur le plan technique, je vérifie au minimum:
- la version exacte du noyau (dans l’interface, via le tableau de bord, ou via les fichiers du projet), l’état de wp-config.php (présence de clés, constantes, configurations attendues), l’architecture du site (multisite ou non, sous-dossiers ou sous-domaines, présence de mu-plugins).
Je m’impose aussi une règle simple: avant toute opération de comparaison, on sauvegarde. Pas juste une copie rapide, mais une capture cohérente, idéalement avec l’arborescence complète et, si c’est possible, un dump de base de données. Même si l’infection n’est pas “dans la base”, un dump permet de revenir en arrière.
Une fois cette base posée, la comparaison devient plus utile, car vous pouvez classer les différences en catégories: celles dues au noyau, celles dues à la configuration, celles dues aux plugins et thèmes, et celles qui n’ont aucune explication raisonnable.
Ce qu’il faut comparer en priorité, sans se noyer
Quand je travaille sur un site WordPress infecté, je traite la comparaison comme un triage. J’ai besoin d’indices solides, pas de “différences” au sens large.
Le noyau WordPress (les fichiers de la racine WordPress et wp-includes) est un bon point de départ parce qu’il varie peu entre installations propres à version égale. Les thèmes et plugins, en revanche, sont un monde plus mouvant. Les écarts y sont attendus, donc la comparaison doit rester focalisée: repérer les ajouts, les modifications inattendues, et les patterns typiques d’obfuscation.
Voici les zones qui, en pratique, donnent le plus souvent des réponses:
- wp-includes et les fichiers du root WordPress, à version exacte, wp-content/plugins et wp-content/themes, mais surtout les fichiers nouvellement ajoutés ou les fichiers dont le contenu est “bizarre” (encodage, chargements conditionnels, base64, injections conditionnelles selon l’agent utilisateur), wp-content/uploads, quand l’infection passe par du webshell déguisé, wp-config.php et .htaccess, car une infection peut détourner le trafic ou activer des exécutions.
La “comparaison officielle” sert alors à repérer ce qui ne colle pas à l’original sur les zones qui devraient être stables.
Comparaison du noyau avec une version officielle: méthode terrain
Imaginons que votre site tourne sur WordPress 6.4.3 (exemple, adaptez à votre cas). Vous récupérez une copie propre du noyau correspondant exactement à 6.4.3. L’idéal est de conserver aussi la même structure d’archive telle que livrée.
Ensuite, vous comparez, fichier par fichier, sans exiger une homographie parfaite au niveau des dates. Les dates de modification ne sont pas fiables, car votre site a pu tourner pendant des mois, et certains hébergeurs ajustent les timestamps. Ce qui compte, c’est le contenu.
Dans mon processus, je procède souvent dans cet ordre: 1) comparaison sur wp-includes, 2) comparaison sur les fichiers en racine, 3) comparaison sur wp-content mais en mode “sanitaire” (détecter ajouts et anomalies plutôt que recalculer tout ce que vous avez déjà en plugins).
Je privilégie des comparateurs qui affichent clairement les différences de contenu, pas juste “liste des fichiers différents”. Les fichiers PHP sont souvent identiques à la surface, mais la charge malveillante se cache dans une petite portion de code. Une sortie de diff trop minimaliste peut rater le détail. À l’inverse, une sortie trop verbeuse peut noyer l’information. L’objectif est d’aboutir rapidement à une poignée de fichiers obtenez plus d'info suspects.
Signaux concrets d’une modification malveillante
Une infection “propre” en apparence est un piège classique. Le site répond, la page d’accueil s’affiche, mais une condition déclenche l’attaque quand le trafic correspond à certains critères.
Quelques signaux, observables dans les diffs et dans l’inspection du code, reviennent souvent. Ce sont des indices, pas des preuves seules, mais combinés ils orientent fortement.
Voici les types d’écarts que je cherche en premier, car ils sont rarement le fruit de modifications légitimes: 1) code chiffré ou obfusqué ajouté en fin de fichier, souvent avec des chaînes base64 ou gzinflate, 2) chargement dynamique de code via require, include, eval, assert, ou fonctions dont l’usage n’est pas cohérent avec le reste du fichier, 3) conditions sur l’URL, sur le référent, sur l’agent utilisateur, ou sur des segments de chemin non documentés, 4) nouvelles options dans des fichiers de configuration comme wp-config.php, ou des constantes ajoutées avec des noms non standards, 5) fichiers PHP “orphelins” dans wp-content, ou dans des sous-répertoires où ils n’ont aucune raison d’être.
Si vous ne voyez rien de tout cela dans les fichiers du noyau mais que le site est quand même compromis, l’infection est souvent dans plugins ou thèmes, ou dans la base, ou via des comptes administrateurs.
Et si le noyau correspond à l’officiel ?
C’est une situation fréquente, et elle n’est pas rassurante, elle est juste informative. Une correspondance du noyau avec une version officielle signifie que la porte dérobée n’est pas dans WordPress lui-même, au moins pas dans les fichiers que vous avez comparés.
À ce moment-là, j’oriente la comparaison sur ce qui “devrait bouger” mais qui, dans votre historique, aurait dû rester cohérent:
- plugins: vérifier les fichiers ajoutés et les fichiers modifiés qui contiennent des charges suspectes, thèmes: repérer des modifications dans des templates PHP qui injectent du contenu selon des conditions, uploads: détecter des scripts exécutables ou des fichiers déguisés, mu-plugins: souvent sous-estimés, ils s’exécutent sans passer par l’interface habituelle.
Le point important: beaucoup d’investigations ratent le fait que wp-content n’a pas besoin d’être “massivement différent” pour être dangereux. Un seul fichier suffit, et il peut être ajouté dans un dossier qui n’est pas habituellement scanné.
Une comparaison utile nécessite de maîtriser la partie non officielle: configuration et environnement
Même un WordPress propre aura des différences par rapport à l’archive officielle, parce que la configuration dépend de votre environnement.
Je garde cette idée en tête: si vous voyez des différences dans wp-config.php, ce n’est pas forcément une anomalie. Les constantes de connexion, les clés de chiffrement, la stratégie de debug, et parfois la configuration de table prefix ne seront pas identiques entre deux installations.
En revanche, je traite comme suspect tout ajout de logique PHP dans wp-config.php qui ne ressemble pas à une configuration. Sur le terrain, on voit souvent des attaques qui mettent une condition “si tel paramètre est présent, exécuter…” ou qui modifient le flux d’exécution.
De la même façon, .htaccess ou des règles server-side peuvent être modifiées. Dans ce cas, la comparaison n’est pas “avec une archive officielle de WordPress”, mais plutôt “avec l’état attendu” pour votre hébergement et votre configuration habituelle. Là où WordPress livré reste globalement stable, votre htaccess reflète des choix spécifiques. Si un changement est arrivé après un incident, il devient un indice majeur.
Cas pratique: quand le diff répond vite, et quand il vous trompe
Sur un site que j’ai eu à reprendre, le noyau était parfaitement identique à la version officielle. La page d’administration s’ouvrait, le thème semblait intact, et pourtant certaines requêtes déclenchaient une redirection étrange. Les diffs du noyau n’ont rien donné.

Le vrai indice est venu d’une comparaison plus ciblée dans wp-content. Un seul fichier PHP avait été ajouté dans un sous-dossier “qui servait à stocker des images” à l’origine, sauf que l’extension et l’emplacement étaient mal choisis, et le code était obfusqué sur quelques lignes seulement. Le diff a d’abord semblé “trop simple”. C’est souvent le cas: ce n’est pas un virus qui a modifié un millier de lignes, c’est un petit mécanisme discret.
Dans un autre cas, la comparaison a trompé parce qu’on avait inclus dans la comparaison une copie d’archive qui ne correspondait pas exactement à la version installée. Les différences dans le noyau semblaient énormes, et l’équipe a perdu du temps à “nettoyer” des fichiers qui n’étaient finalement pas compromis. Leçon: la version officielle doit être la bonne, sinon vous transformez un incident en exercice d’harmonisation.
Une approche rationnelle: comparaison pour trier, puis récupération pour assainir
La comparaison avec la version officielle sert surtout à décider. J’ai rarement envie de “corriger à la main” un fichier de noyau suspect, parce qu’on introduit vite des erreurs, ou parce que le vrai problème peut être ailleurs. Le plus sain, quand le noyau est réellement en cause, reste de remplacer le noyau par la version officielle correspondant exactement.
Le même raisonnement s’applique aux thèmes et plugins: si vous avez un doute sérieux sur un fichier, surtout si un plugin a été modifié alors qu’il ne devait pas l’être, la restauration à partir d’une version propre est plus fiable que le bricolage.
Le compromis, c’est la vitesse et la complexité. Remplacer un plugin peut casser des personnalisations, mais les personnalisations doivent être maintenues dans des endroits prévus, comme un child theme ou des hooks documentés. Si votre thème est fortement modifié en dur, la comparaison devient une discussion entre le risque et le coût.
Où la comparaison ne suffit pas, même si le noyau est “clean”
Il existe des infections qui ne laissent pas grand-chose dans le code de fichiers, ou qui laissent des traces dans des endroits que la comparaison avec une archive officielle ne couvre pas directement.
Voici les zones qui, selon les incidents, doivent être vérifiées en parallèle:
- comptes administrateurs: une prise de contrôle peut être obtenue par un utilisateur ajouté ou un compte modifié, la base de données: options, cron, tables qui stockent des paramètres, parfois des scripts injectés, la file d’attente et le système de tâches: si le cron du serveur a été utilisé pour exécuter du code à intervalles réguliers, les permissions et la modification du workflow de déploiement: un plugin légitime peut avoir servi de vecteur si la chaîne d’approbation a été compromise.
C’est aussi là que la notion de “version officielle” montre ses limites. WordPress officiel ne contient pas votre base, vos utilisateurs, vos paramètres, ni votre historique de tâches. Donc la comparaison est un outil d’assainissement du code, pas un scan complet du compromis.
Comment éviter les faux positifs: garder la bonne méthode et le bon niveau d’exigence
La comparaison peut devenir anxiogène si vous voulez un match parfait. Sur beaucoup de sites, il y aura:

- des fichiers générés automatiquement, des index et des caches, des modifications légitimes dues à l’hébergement ou à des outils de performance.
Sur un projet réel, il faut accepter qu’une “différence” n’implique pas automatiquement une infection. Le bon réflexe est de combiner trois choses: emplacement, contenu, et chronologie.
Si une modification d’un fichier du noyau correspond à un moment précis après un incident, et si le contenu ajouté ressemble à une charge, alors la décision est simple. Si, au contraire, vous voyez des différences dans un endroit attendu, et que le contenu correspond à ce que votre workflow générerait, vous gagnez du temps en écartant.
Le piège, c’est de chercher une preuve unique. Les compromis WordPress sont souvent multi-couches, et une partie peut être “silencieuse” dans les fichiers. C’est pour cela que je préfère une démarche pragmatique: d’abord éliminer le noyau et les scripts évidents, puis contrôler la base et les comptes.
Procédure pratique de comparaison, sans s’éparpiller
Je vous propose une séquence qui fonctionne bien en intervention. Elle évite de passer des heures à comparer des centaines de fichiers inutiles.
1) Identifiez la version exacte du noyau et obtenez la version officielle correspondante. 2) Comparez en priorité wp-includes et la racine WordPress, en ignorant les timestamps et en focusant sur le contenu. 3) Si le noyau diverge sur des fichiers sensibles, planifiez le remplacement complet du noyau par une copie propre. 4) Si le noyau est identique, déplacez la comparaison vers wp-content, en recherchant les ajouts, les modifications obfusquées, et les fichiers exécutables dans des emplacements inhabituels. 5) Après nettoyage du code, vérifiez l’accès et la base, car un compromis peut persister via comptes, options et tâches.
Je sais, ça ressemble à une liste, mais l’idée est simple: l’ordre évite de perdre du temps et réduit la probabilité de rater une pièce maîtresse.
Quand il vaut mieux restaurer plutôt que comparer
Il y a un moment où la comparaison devient un outil de retardement. Si le site a été en ligne pendant plusieurs heures avec une charge active, si vous observez des comportements difficiles à tracer, ou si plusieurs plugins ont été touchés, la restauration à partir d’une sauvegarde saine peut être plus efficace.
Le critère que j’utilise: la qualité et la date de vos sauvegardes. Une sauvegarde du code datant d’une période “avant incident” est souvent plus précieuse qu’un travail d’analyse sans fin. Même si vous ne savez pas exactement comment l’infection a démarré, restaurer un état cohérent réduit la surface d’attaque.
Le compromis est évidemment la restauration de la base. Si la sauvegarde de base est trop ancienne, vous perdez des données ou des contenus. Mais si la base a été contaminée, rester sur une base suspecte peut coûter plus cher à moyen terme. Dans plusieurs interventions, j’ai vu le choix se faire avec une règle empirique: mieux vaut restaurer tout ce qui a un doute, puis réinjecter les changements légitimes après coup, plutôt que garder une partie potentiellement compromise en espérant “que ça va”.
Les erreurs fréquentes que je vois dans les comparaisons
Pour éviter de transformer l’analyse en boucle, je surveille quelques erreurs typiques.
- comparer avec la mauvaise version du noyau, et donc “normaliser” des différences légitimes comme si elles étaient des signes, ne pas sauvegarder avant, ce qui rend ensuite impossible de prouver ou de comparer à nouveau, ignorer wp-content et se focaliser uniquement sur le noyau, remplacer un plugin compromis sans vérifier si la configuration ou la base a conservé une entrée malveillante, croire que “le site s’affiche” signifie “tout est sain”.
Une comparaison utile n’est pas celle qui montre le plus de différences, mais celle qui aboutit à une décision.
Une mini check-list de décision (courte, mais efficace)
Quand vous hésitez entre investigation et restauration, voici les signaux qui poussent souvent à restaurer ou à remplacer rapidement plutôt que “continuer à chercher”.
- le noyau diverge sur des fichiers qui ne devraient pas changer, vous trouvez des ajouts de fichiers PHP dans wp-content avec code obfusqué ou logique conditionnelle, plusieurs plugins ou thèmes montrent des modifications sans explication claire, des comptes administrateurs ou des paramètres suspects apparaissent dans la base, le comportement malveillant persiste malgré des changements de code.
Si vous cochez plusieurs points, la restauration gagne généralement en rapport effort-risque.
Après l’assainissement: prévenir la prochaine infection (sans promesses miracles)
Une fois le site rétabli, le sujet devient la prévention. Comparer avec une version officielle vous aide à nettoyer, mais ce qui compte vraiment, c’est la réduction des vecteurs d’entrée.
Les axes concrets sont souvent:
- limiter les droits, surtout côté fichiers et répertoires sensibles, mettre en place une hygiène d’installations (plugins de sources fiables, mises à jour régulières), supprimer les thèmes et plugins inutiles, renforcer la rotation des identifiants et surveiller les connexions, contrôler le processus de déploiement si vous utilisez une pipeline CI/CD.
Je garde aussi un réflexe de suivi: surveiller les changements de fichiers (intégrité) et regarder les journaux d’erreurs, pas uniquement la page web. Une infection sait souvent où regarder, et les logs donnent une longueur d’avance.
Réponse directe à la question “comparer, oui, mais comparer quoi”
Si je devais résumer avec précision l’idée centrale, sans en faire une recette figée: comparez avec une version officielle pour le noyau et pour ce qui est supposé stable, puis élargissez vers wp-content quand le noyau est clean. La comparaison sert d’aiguillage. Ensuite, l’assainissement se fait par remplacement des composants réellement suspects, plus vérification des comptes et de la base.
Ce type de démarche est utile quand vous suspectez un site WordPress infecté parce qu’il vous donne une méthode de travail stable, une logique de réduction du bruit, et une façon de justifier vos décisions. Et sur le terrain, c’est souvent le plus dur, avant même la technique: passer de “on ne sait pas” à “voilà ce qu’on a vu, voilà ce qu’on remplace, voilà ce qu’on vérifie pour que ça ne revienne pas”.
