Scanner malware WordPress : surveiller les fichiers .php dans uploads

Quand on administre un WordPress un peu exposé (beaucoup de trafic, hébergement mutualisé, plugins variés, mises à jour pas toujours immédiates), la zone la plus sournoise n’est pas forcément celle qu’on croit. Les attaques visent souvent l’interface d’administration, le thème ou certains plugins, mais le résultat se voit dans des endroits très concrets. Et parmi eux, il y a un piège classique: les fichiers .php déposés dans wp-content/uploads.

Le dossier uploads est censé contenir des images, des PDF, des fichiers de médias. Quand on y trouve des scripts PHP, ce n’est pas une “petite anomalie”. C’est un signal d’alarme immédiat, parfois avec une discrétion redoutable. Certains malwares ne se manifestent pas de suite. Ils s’attendent à ce que l’URL soit appelée, à ce qu’une requête déclenchée par un navigateur ou un bot passe par un chemin précis, ou à ce qu’un autre composant les invoque.

Surveiller les fichiers .php dans uploads, c’est donc à la fois de la prévention et de la détection. Mais il faut le faire proprement, sinon on se retrouve avec une liste de faux positifs, des alertes inutiles, ou pire, une configuration qui casse des fonctionnalités légitimes.

Pourquoi les fichiers .php dans uploads font peur

uploads n’est pas un dossier “technique”. Dans un WordPress standard, on y stocke des médias. C’est exactement pour ça que l’ajout de .php est un comportement atypique. Même si WordPress sait gérer et servir des fichiers, il ne devrait pas avoir besoin d’exécuter du PHP dans ce répertoire pour le fonctionnement normal des médias.

D’un point de vue attaque, le scénario est souvent simple:

    un accès est obtenu (failles de plugin, identifiants compromis, mauvaise hygiène de droits, désauthentification partielle d’un utilisateur, etc.) un payload est déposé dans un emplacement qui passe pour “banal” le malware attend une requête ciblée, un paramètre, ou une condition (par exemple un User-Agent particulier)

Dans certains cas, le fichier PHP n’est même pas accessible directement depuis le navigateur, mais il peut être inclus par un autre fichier compromis. Le simple fait qu’il existe dans uploads peut suffire à déclencher un comportement: un autre mécanisme “range” peut chercher des signatures, ou l’attaque peut réutiliser le chemin vers ce fichier.

Ce qui rend la surveillance intéressante, c’est qu’elle vous donne un levier actionnable très tôt. Au lieu d’attendre une infection détectée par un scan plus lourd, vous pouvez réagir sur un fait: “il y a un fichier exécutable dans un endroit non prévu”.

Ce que veut dire “surveiller” dans la pratique

Surveiller ne veut pas dire “scanner toute la journée avec un outil qui fatigue le serveur”. Ça veut dire instaurer une chaîne: repérer, vérifier, trier, et décider.

Il y a plusieurs niveaux possibles, et le bon choix dépend de votre environnement:

    Sur un site unique, vous pouvez vous appuyer sur des contrôles périodiques et une journalisation simple. Sur une flotte de sites, vous avez besoin d’un système central et d’indicateurs exploitables. Sur un hébergement mutualisé avec contraintes, vous devez faire attention à ce qui est réellement possible (accès SSH, droits sur la base, disponibilité des hooks, etc.).

La surveillance efficace combine souvent deux angles: la présence de fichiers (détection d’ajout) et l’intégrité (détection de modification). Un fichier .php nouvellement déposé est plus parlant qu’un fichier existant depuis longtemps. Mais un fichier “ancien” peut aussi être altéré, ou servir de leurre.

Enfin, il y a le point souvent oublié: WordPress et certains plugins peuvent créer des fichiers dans uploads via des fonctions internes. La règle doit donc être appliquée avec discernement, sans présumer qu’absolument tout PHP dans uploads est forcément malveillant au premier regard. Cela dit, dans la majorité des cas, l’apparition de .php dans uploads doit déclencher un examen rapide.

Les faux positifs possibles (et comment ne pas y tomber)

Je l’ai vu sur des projets où on pensait être “trop strict”. L’équipe avait mis une politique “zéro PHP dans uploads” et chaque alerte créait une friction. Au final, une partie du bruit venait de:

    des imports automatiques d’utilisateurs qui chargent “n’importe quoi” (certains CMS ou outils d’export finissent parfois par mettre des scripts dans des archives ou des fichiers mal filtrés) des fichiers temporaires créés pendant des traitements (rare, mais possible selon des plugins qui décompressent des archives) des environnements de débogage où on a laissé une pratique permissive

Le piège, c’est de décider trop vite. Par expérience, je préfère une approche en deux temps: d’abord, classifier et vérifier, ensuite seulement bloquer ou supprimer.

Le bon réflexe est de coupler la détection de présence (y a-t-il du .php?) Avec des informations supplémentaires:

    date de création et date de modification taille du fichier (un script malicieux est souvent petit, mais pas toujours) nom du fichier (certains payloads utilisent des schémas typés, d’autres essaient de ressembler à des noms “normaux”) contenu: fonctions typiques, obfuscation, appels à base64_decode, eval, gzinflate, str_rot13, shell_exec si vous en voyez, ou des patterns de requêtes réseau

On évite ainsi de transformer la surveillance en guillotine immédiate.

Construire un signal fiable: présence, modification, et contexte

Une surveillance utile a besoin de critères cohérents. Si vous faites juste “rechercher uploads/*.php”, vous aurez un signal brut. Il vous faut un minimum de contexte.

Dans les journaux ou métadonnées disponibles, cherchez:

    l’heure de création (et comparez-la à des événements: mise à jour plugin, changement de mot de passe, déploiement, période de charge inhabituelle) la cohérence avec les habitudes du site (un pic d’activité à 3 h du matin sur un site qui normalement dort, ça compte) l’accessibilité réelle: le fichier est-il réellement consultable via URL? l’existence d’autres anomalies en parallèle: nouveaux fichiers dans wp-content/plugins, wp-content/themes, ou modifications sur des fichiers de WordPress

C’est là que la notion de “scanner malware WordPress” prend son sens. Un scan, même bon, n’est pas uniquement une chasse au fichier. C’est un outil qui met en perspective et qui réduit votre temps de triage. Mais il n’a pas forcément la finesse de “détecter immédiatement le dépôt dans uploads”. D’où l’intérêt d’une surveillance ciblée.

L’idéal n’est pas de choisir “scanneur ou surveillance”, mais d’orchestrer les deux: surveillance ciblée pour déclencher, scanner plus complet pour confirmer et nettoyer.

Exemples de scénarios concrets

Cas 1: un fichier .php apparaît après une semaine sans incident

Le site tourne, rien d’anormal côté base de données. Puis, vous recevez une alerte, ou vous constatez manuellement un nouveau fichier dans uploads. Taille faible, nom peu naturel, date récente. Vous ouvrez le fichier: vous voyez des couches d’obfuscation et une fonction qui lit des données depuis une source externe.

À ce stade, je ne me contente pas d’effacer. Je coupe d’abord l’exécution et j’enquête sur l’origine du dépôt. Une suppression seule peut laisser derrière elle un autre mécanisme, et si l’attaquant a conservé l’accès, il reverra le fichier.

Sur le plan opérationnel, vous voulez confirmer si d’autres fichiers ont été ajoutés dans la même fenêtre temporelle. Vous vérifiez aussi les comptes utilisateurs: changements d’email, nouveaux rôles, clés d’API, tokens.

Cas 2: un fichier .php “ressemble” à un template

On voit parfois des https://gardewp.fr/ scripts qui adoptent des noms plus banals, ou qui font semblant d’être liés à un plugin. C’est là que la classification de contenu compte. Si le script n’essaie pas de se faire passer pour autre chose, si vous voyez des patterns de chargement dynamique ou d’exécution, c’est déjà suspect.

Mais si vous ne savez pas, mieux vaut isoler et comparer. Par exemple, si vous aviez une sauvegarde juste avant, vous pouvez chercher si le fichier existait déjà. Si c’est un nouveau fichier, il n’y a pas de débat. S’il existait déjà mais était “inactif”, une modification récente peut être la vraie alerte.

Cas 3: une alerte se déclenche sur un site en production très dynamique

Parfois, un plugin d’import ou un service d’upload “technique” peut créer un fichier en uploads pour un traitement. Dans ce cas, la date de création et la logique de workflow sont déterminantes. Si l’import se fait à la demande, pendant une fenêtre connue, et que le fichier n’a pas de comportement exécutable évident, vous pouvez ajuster la règle.

Le problème n’est pas d’avoir un fichier .php dans uploads, c’est de traiter toutes les occurrences comme https://gardewp.fr/nettoyage-malware-wordpress/ identiques. En pratique, ce qui tue, c’est le manque de tri.

La méthode de surveillance la plus utile, sans surcharger le serveur

Vous voulez un système qui repère les nouveaux .php dans wp-content/uploads et qui vous prévient sans délai. L’approche dépend de votre accès. Si vous avez SSH et que le site est sur un environnement contrôlé, vous pouvez utiliser une tâche planifiée. Si vous n’avez pas, vous devez vous tourner vers des outils applicatifs, des hooks, ou une surveillance au niveau du fichier via l’hébergement.

Dans la plupart des organisations, j’ai vu fonctionner une logique en trois étapes: collecte, comparaison, et décision.

Voici un mini plan, que vous pouvez adapter.

    Identifier toutes les occurrences de fichiers *.php sous wp-content/uploads (y compris sous-dossiers). Enregistrer un instantané de liste (ou au minimum dates et tailles) et comparer avec la dernière version. Mettre une règle d’alerte: nouveau fichier ou modification récente, surtout si la date ne colle à aucun événement. En parallèle, vérifier rapidement dans WordPress si des fichiers ont été ajoutés ailleurs et si des comptes ont changé. Lancer ensuite un scan plus complet (scanner malware WordPress) pour valider l’étendue, puis nettoyer.

Ce que j’aime dans ce flux, c’est qu’il ne dépend pas d’un seul outil. Un outil de scan peut rater quelque chose, ou produire des faux positifs. Une surveillance sur les chemins typiques de dépôt, comme uploads, réduit l’incertitude au départ.

Et si vous ne pouvez pas accéder aux fichiers comme vous voulez ?

Sur certains hébergements, l’accès SSH n’est pas disponible ou limité. Dans ce cas, la surveillance ciblée devient plus “observatoire” que “détecteur direct”.

Vous pouvez par exemple:

    vous appuyer sur des outils fournis par l’hébergeur, s’ils existent (audit de fichiers, logs d’accès, fichiers modifiés) utiliser un plugin de sécurité qui liste les fichiers et peut signaler des changements, avec la prudence habituelle (un plugin de sécurité ne remplace pas une vérification de contenu si une alerte tombe) renforcer la configuration pour limiter l’exécution PHP dans uploads (ce point dépend fortement de votre stack serveur et doit être testé)

Le piège ici, c’est de croire que l’absence d’alerte signifie “rien”. Si votre méthode de vérification est lente, vous perdez la fenêtre de réaction.

Si vous avez un doute et que votre accès est limité, faites au minimum une vérification manuelle rapide: liste des fichiers .php dans uploads, regard sur les dates, puis inspection du contenu des quelques fichiers trouvés. La plupart du temps, il y en a peu.

Bloquer l’exécution: utile, mais à ne pas faire au hasard

Beaucoup d’équipes veulent “rendre impossible” l’exécution de PHP dans uploads. Sur Apache et Nginx, on peut configurer selon les cas. Sur certaines configurations, on peut empêcher l’exécution en ajoutant des règles qui renvoient un statut 403 ou qui traitent les .php comme du texte. Sur d’autres, c’est plus délicat.

Je reste prudent. Tout blocage mal appliqué peut casser un plugin, un module, ou un mécanisme de rendu. Et comme vous surveillez déjà, vous pouvez gagner du temps sans casser la prod. Une stratégie raisonnable consiste à:

    confirmer d’abord si un .php exécuté pourrait être appelé publiquement puis seulement durcir l’exécution, en testant sur un environnement miroir ou sur une fenêtre de maintenance

Cette partie est très dépendante de votre serveur. L’idée générale est simple: si quelqu’un dépose du .php dans uploads, l’impact doit être réduit autant que possible.

Ce que je vérifie après une alerte sur uploads/*.php

Quand vous avez un ou plusieurs fichiers .php trouvés, votre priorité est de savoir si c’est isolé ou si l’attaque a étendu son rayon.

Voici ma routine, courte mais structurée.

    Vérifier si d’autres fichiers suspects existent dans la même zone et autour (plugins, thèmes, fichiers racine du WordPress). Rechercher les modifications récentes sur des fichiers sensibles, surtout si les dates ne correspondent à aucun déploiement. Contrôler les utilisateurs WordPress: nouveaux comptes, rôles, modifications d’email, accès récents. Examiner les fichiers PHP concernés: obfuscation, appels à exécution, chargement de contenu externe, comportement conditionnel. Mettre le site en mode d’assainissement contrôlé (au moins temporairement) si vous suspectez un webshell actif.

Cette séquence évite le piège du “on supprime le fichier et on prie”. Si l’attaquant a laissé un chemin de persistance, l’incident revient.

Ajuster la détection pour éviter l’usure opérationnelle

Un problème courant: vous recevez trop d’alertes, ou vous ne savez plus lesquelles traiter en premier. Pour garder un système viable, vous devez choisir des critères qui réduisent le bruit.

En pratique, je préfère un classement “nouveau” vs “ancien” et une pondération par risque. Un fichier nouveau, petit et obfusqué pèse plus qu’un fichier .php ancien avec un contenu clairement inoffensif (ce cas reste rare, mais il existe).

Si votre surveillance prend la forme d’une comparaison d’inventaire, vous pouvez aussi limiter les alertes à une fenêtre de temps. Par exemple, vous déclenchez l’alerte immédiate sur la nouveauté sur 24 à 48 heures, et vous programmez un audit “plus lent” sur le reste.

Ce choix ne doit pas masquer les modifications. Un fichier ancien modifié récemment mérite le même niveau d’attention qu’un nouveau fichier.

Scanner malware WordPress: comment l’utiliser sans se faire piéger par ses limites

Les scanners sont utiles, mais ils ont des limites. Certains cherchent des signatures connues, donc ils ratent les variantes. D’autres font de l’analyse heuristique, mais peuvent être trop prudents. Dans tous les cas, un scan ne remplace pas la lecture contextuelle, surtout quand l’alerte pointe vers uploads.

Ma recommandation opérationnelle est d’utiliser le scanner malware WordPress comme un outil d’extension, pas comme un verdict final. Concrètement:

    vous déclenchez un scan après une alerte ciblée (présence d’un .php dans uploads) vous regardez la liste des fichiers signalés, mais vous triez par dates et proximité avec les anomalies vous comparez avec vos sauvegardes si vous en avez une, au moins pour les chemins sensibles

Un scanner peut vous dire “suspect”. Mais c’est votre contrôle qui vous dira “actif”, “isolé” ou “trace de persistance”.

Une anecdote de terrain sur la “bonne règle” qui devient trop stricte

Sur un site, on avait intégré une règle simple: alerter dès qu’un .php apparaît dans uploads. Ça a marché trop bien. En fait, un plugin de génération de PDF ajoutait un fichier temporaire avec une extension inattendue dans un sous-dossier. Le contenu n’était pas un webshell, et il était supprimé rapidement, mais l’alerte s’empilait.

Au lieu de désactiver la surveillance (mauvaise décision), on a affiné. On a conservé l’alerte immédiate uniquement sur les nouveaux fichiers non attendus, et on a ajouté un contrôle de contenu minimal sur les fichiers déclenchants. Résultat, moins d’interruptions, plus d’efficacité.

image

Le point important: une bonne règle n’est pas forcément “la plus stricte”. C’est celle qui reste stable dans votre réalité d’exploitation.

En cas d’incident: nettoyer et revenir à un état sûr

Si vous confirmez qu’un .php dans uploads est malveillant, la suppression est nécessaire mais rarement suffisante. À minima, vous voulez:

    retirer le fichier et tout ce qui ressemble à une dépendance (fichiers de chargement, scripts auxiliaires) vérifier le reste de l’arborescence WordPress, surtout les chemins où une persistance peut être installée invalider les sessions et forcer un renouvellement de secrets (mots de passe, clés, tokens) remettre les plugins et thèmes à un état connu si vous suspectez une compromission plus large

Si le serveur a été compromis, le nettoyage côté application ne suffit pas. C’est pour ça que la surveillance de uploads est un excellent signal, mais pas un diagnostic complet.

Mettre en place la surveillance dès maintenant, sans attendre “le prochain incident”

Si vous n’avez pas de processus aujourd’hui, commencer par une surveillance ciblée sur wp-content/uploads est un bon point d’entrée. C’est un endroit logique, et c’est souvent là que les actions malveillantes laissent un empreinte visible.

image

La clé est d’associer trois choses: une détection fiable des changements, une vérification contextuelle, et un déclenchement vers un scan plus large quand c’est nécessaire. Dans ce schéma, le scanner malware WordPress devient l’étape de confirmation, pas le point de départ.

Si vous voulez une mesure de succès simple: après quelques semaines, vous devriez être capable de répondre rapidement à deux questions. Qu’est-ce qui est arrivé, et est-ce que c’était déjà connu ou inattendu. Quand ces réponses deviennent naturelles, votre sécurité gagne en précision, et votre exploitation reste supportable.

La surveillance de uploads/*.php ne garantit pas à elle seule que votre WordPress est sain. Mais elle réduit une zone de non visibilité et elle vous donne un levier concret, rapide, et souvent décisif.