Symptômes · 9 min · publié le 7 juillet 2024

Must-use plugin WordPress caché : l'endroit qu'on oublie

`wp-content/mu-plugins` s'exécute sans case à cocher. Après un « nettoyage » du dossier `plugins`, c'est souvent là que la porte survit. On ouvre ce répertoire à chaque incident WordPress, même s'il paraît vide dans l'admin.

Réponse directe

wp-content/mu-plugins s'exécute sans activation. Un backdoor s'y loge souvent après un « nettoyage » du dossier plugins. Ouvrez-le systématiquement.

mu-plugins malware must use plugin pirate backdoor mu-plugins

Pourquoi l'admin ne le montre pas comme les autres

Les must-use n'ont pas de bouton Désactiver. WordPress les charge tous. L'écran « Extensions installées » a parfois un onglet « Must-Use » : beaucoup d'utilisateurs ne le voient pas, et certains thèmes le masquent. Un dossier `mu-plugins` vide n'affiche rien. Un fichier `hello.php` de trois Ko non plus si personne n'ouvre l'onglet.

C'est précisément pour ça que l'attaquant aime cet endroit. Vous « désinstallez tout », vous réinstallez WordPress, vous changez de thème : le mu-plugin est encore là. Dans les dossiers que nous reprenons, c'est le premier oubli après un nettoyage amateur.

Traitez `mu-plugins` comme la racine : liste nom / taille / date, pas un coup d'œil.

Ouvrir le dossier, pas l'écran Extensions

SFTP : `wp-content/mu-plugins/`. S'il n'existe pas, ce n'est pas une garantie : on peut le créer plus tard. S'il existe, tout fichier PHP en est chargé (selon les règles WP : fichiers à la racine du dossier, pas toujours les sous-dossiers sauf loader).

Un sous-dossier `something/` plus un `something.php` chargeur est le schéma légitime (Acorn, un mu-plugin d'agence). Un sous-dossier sans chargeur visible plus un `index.php` à la racine du mu-plugins est plus suspect.

Copiez tout le dossier hors serveur avant de juger. Un delete trop vite casse un must-use de licence ou de multisite que l'agence avait posé pour de vraies raisons.

  • Listing SFTP horodaté.
  • Onglet Must-Use de l'admin s'il existe.
  • Copie complète du dossier.
  • Sous-dossiers + chargeurs.

Ce à quoi ressemble un mu-plugin légitime

Un header de plugin WordPress (`Plugin Name:`), un auteur que vous connaissez (agence, hébergeur, Bedrock, un outil de staging). o2switch et d'autres posent parfois un mu-plugin de cache ou de sécurité. Demandez-leur avant d'effacer un fichier signé de leur nom.

Un fichier de 400 octets qui désactive les mises à jour ou force une option peut être un bricolage d'agence — discutable, pas forcément pirate. Un fichier de 80 Ko minifié, sans header, avec `eval` : l'inverse.

En cas de doute, isolez (renommez en `.off`) et testez le site. Si le métier casse (tunnel, intranet), c'était peut-être légitime. Si rien ne casse et que le footer spam disparaît, vous tenez une porte.

Chargeur, dossier caché, et `index.php`

Les kits posent `index.php` dans `mu-plugins` pour charger un voisin aux nom de cache (`wp-cache-core`, `.hidden`). Le listing FTP « cache » rassure à tort. Ouvrez le PHP : s'il `require` un chemin bizarre, suivez-le.

Un fichier qui commence par une image JPEG puis du PHP : double regard, même hors `uploads`. Rare en mu-plugins, pas impossible.

Les permissions : un `mu-plugins` en 777 plus un FTP ouvert, la réécriture est triviale. 755/644 après tri.

Après un cleaner : le scénario le plus fréquent

Wordfence « réparer tout », un plugin cleaner, une restauration de `plugins/` : le payload visible part, le mu-plugin reste. Le lendemain, `plugins/` est à nouveau infecté. On accuse WordPress ; c'est le must-use qui réécrit.

C'est pour ça que « on a déjà nettoyé » n'est pas une information utile sans « on a ouvert mu-plugins ». Posez la question à l'agence précédente.

Un cleaner peut aussi poser son propre mu-plugin. Lisez-le. S'il est officiel (Wordfence, un hébergeur), gardez. S'il date de la même minute qu'un `radio.php`, copiez et sortez.

Drop-ins : l'autre oubli (`advanced-cache.php`)

À la racine de `wp-content` : `advanced-cache.php`, `object-cache.php`, `db.php`, `maintenance.php`, `php-error.php`, `install.php`. WordPress les charge s'ils sont là. Un `object-cache.php` pirate survit à tous les plugins. Lisez les dates.

LiteSpeed, Redis, Memcached posent des drop-ins légitimes. Comparez au zip du plugin de cache. Un drop-in de 200 Ko alors que l'officiel en fait 8, c'est le même signal que index.php trop lourd.

Vider le cache après retrait : le drop-in sale a pu remplir Redis. Voir object cache.

Couper sans casser un must-use métier

Isolez fichier par fichier, testez. Sur un multisite, les mu-plugins tiennent parfois le réseau. Un delete global le vendredi soir est un second incident.

Documentez ce que vous retirez (nom, date, hash). Le constat. Si l'hébergeur avait posé le fichier, ils apprécient de le savoir avant de rouvrir un compte.

Changez le panel : un mu-plugin se recree en une requête FTP. L'ordre mots de passe reste le même que partout.

Vérifier qu'il ne se recrée pas

J+1 et J+7 : le dossier est-il encore dans l'état que vous avez laissé ? Une nouvelle ligne `sitemaps.php` à 3 h, voyez cron.

L'onglet Must-Use : prenez une capture « après » pour l'équipe. La prochaine personne ne devra pas chercher.

Si le cloaking ou le footer revient sans nouveau mu-plugin, l'écrivain est en base ou dans le thème. Cet endroit n'est pas le seul ; il est celui qu'on saute.

Lien avec cron, footer et cloaking

Un mu-plugin de 20 lignes peut : reconnaître Googlebot, servir un autre HTML, poser un lien en footer, `file_put_contents` sur `.htaccess`, `wp_insert_post`. Un seul fichier, plusieurs symptômes. C'est pour ça qu'on l'ouvre tôt, pas à la fin.

Inspection d'URL Search Console : si le HTML diffère, et qu'un mu-plugin teste `HTTP_USER_AGENT`, vous avez le couple. Voir cloaking.

Vous pouvez déclarer le site. Une archive du seul dossier `mu-plugins` plus les drop-ins, c'est déjà un dossier exploitable.

  • Liste + copie + isolation fichier à fichier.
  • Drop-ins `wp-content` dans la même passe.
  • Panel changé.
  • Contrôle réapparition une semaine.
Safe Browsing ne se lève pas parce que le mu-plugin est parti. Il se lève quand plus aucune URL dangereuse ne répond 200, souvent 24 à 72 h après réexamen.

Questions fréquentes

Je n'ai pas de dossier mu-plugins. Je dois en créer un « pour surveiller » ?

+
Non. L'absence est saine. Surveillez sa création (date du dossier) après incident, ne posez pas un dossier vide inutile.

L'hébergeur dit que son mu-plugin est obligatoire.

+
Lisez-le, comparez à ce qu'ils décrivent. S'il a gonflé ou changé de date hors MAD hébergeur, copiez et ouvrez un ticket. Ne l'effacez pas à l'aveugle : vous pouvez casser le cache du mutualisé.

Un plugin « must use » dans l'onglet Extensions, c'est pareil ?

+
L'onglet liste les fichiers de `mu-plugins`. Un plugin normal coché « must use » par un outil tiers est parfois déplacé ici. Vérifiez le chemin réel.

Wordfence scanne-t-il mu-plugins ?

+
Oui en principe, s'il a accès au disque. Un one-liner écrit pour vous passe quand même. La lecture humaine des dates reste.

Puis-je désactiver les must-use dans wp-config ?

+
Ce n'est pas un réglage de core prévu. Isoler les fichiers est le geste. Des bricolages `ignore` cassent plus qu'ils n'aident.
À lire ensuite
Fichiers du thème modifiés Tâches cron inconnues Cloaking Googlebot Backdoor PHP WordPress piraté Déclarer mon site