Un abonné devenu administrateur : comment ça arrive
Un compte « Abonné » ou « Client » qui apparaît administrateur n'est pas un bug d'affichage. Faille de plugin, API REST trop ouverte, ou écriture directe en base. Retirez le privilège, cherchez l'entrée, forcez la déconnexion de tous — puis relisez les rôles une semaine plus tard.
Faille de plugin, REST API, ou accès base. Retirez le privilège, cherchez l'entrée, forcez la déconnexion de tous. Relire les roles une semaine plus tard.
Ce que « devenu admin » veut dire en table
WordPress stocke le rôle dans `wp_usermeta`, clé `wp_capabilities` (préfixe à adapter). Un abonné a `subscriber` ; un administrateur a `administrator`. L'élévation, c'est cette valeur qui change, parfois sans que `user_login` ni l'email ne bougent. L'écran Utilisateurs montre le résultat ; il ne date pas le changement. Les journaux d'un plugin de sécurité, l'access.log sur `/wp-json/`, ou un dump plus ancien le font.
Plusieurs users élevés le même jour, ou un seul compte « boutique » passé admin à 3 h : notez id, email, date d'inscription, date de modification si vous l'avez. Exportez avant de rétrograder. Cet export sert au constat, pas à « faire le ménage plus tard ».
Un second compte admin créé de zéro n'est pas une élévation, c'est une création. Le traitement se ressemble (retrait, sessions) ; la recherche d'entrée diverge : formulaire d'enregistrement, API `users`, ou insert SQL. Voir API REST abusée.
Les trois canaux d'élévation
Faille de plugin : un formulaire, un JWT, un builder, un plugin de rôles mal capé permet à un user authentifié (ou parfois anonyme) de poster une capability. Les CVE sont publiques ; les bots les rejouent. Désactiver le plugin après coup ne rétrograde personne.
REST API : une route qui met à jour l'user sans `current_user_can('promote_users')`. Moins spectaculaire, même résultat. Les access.log sur `wp/v2/users/<id>` en POST / PUT datent l'événement.
Accès base : phpMyAdmin ouvert, identifiants MySQL dans un wp-config lu, voisin de compte. L'attaquant UPDATE la meta. Aucune session wp-admin n'est nécessaire. Dans ce cas, changer uniquement le mot de passe WordPress du compte élevé est du théâtre : la meta sera réécrite. Panel et MySQL d'abord — premiers gestes.
- Plugin / thème : comparez à l'officiel, retirez l'abandonné.
- API : routes users et plugins de membership.
- Base : users MySQL, phpMyAdmin, `.env` exposé.
Retirer le rôle sans perdre la preuve
Export (CSV ou `wp user list --format=csv`), captures de l'écran utilisateurs, puis rétrogradation ou suppression. Si le compte est un vrai client WooCommerce, rétrogradez vers `customer` : supprimer casse l'historique de commandes. Si c'est un login inventé, supprimez après export.
Ne « fusionnez » pas les contenus de ce user vers votre admin avant d'avoir lu les posts : vous importeriez un article spam sous votre nom. Réassignez ensuite, à froid.
S'il reste un seul administrateur et que c'est le fantôme, créez d'abord un admin à vous (via WP-CLI ou la base, session panel déjà tournée), puis retirez l'autre. Inverser, c'est se retrouver sans accès.
Forcer la déconnexion de toutes les sessions
Changer le mot de passe du compte élevé ne tue pas forcément les cookies déjà émis. Régénérez les clés `AUTH_KEY` et consorts dans `wp-config.php`, ou `wp user session destroy --all`. Tous les users devront se reconnecter. C'est le but.
Les application passwords du même user survivent au mot de passe. Listez-les, révoquez. Une app « REST » collée sur ce compte est une porte parallèle.
Inverser l'ordre — nouveau mot de passe, fantôme encore admin, clés AUTH anciennes — laisse une session qui recrée le privilège. Sessions et rôle dans la même heure, pas « on verra lundi ».
Capabilities cachées et plugins de membership
Un user peut rester « Abonné » à l'affichage et avoir `install_plugins` dans une meta custom. Les plugins de membership, LMS, et « user role editor » ajoutent des couches. Après un incident, ouvrez l'éditeur de rôles et lisez les capabilities une à une pour les rôles métier. Un « Éditeur » avec `promote_users` est une élévation de rôle, pas d'user.
Réinitialiser les rôles du cœur (`wp role reset --all` selon versions / extensions) est brutal : les rôles WooCommerce et membership cassent. Préférez l'inventaire. Si vous n'avez plus la carte des rôles métier, exportez avant tout reset.
Clés et application passwords du même user
Un client WooCommerce élevé a pu émettre une clé REST avec son nouveau pouvoir, ou en profiter pour lire des commandes. Révoquez les clés attachées à cet user_id. Vérifiez les webhooks créés dans la même fenêtre. Le silence côté boutique (« les commandes marchent ») n'exclut pas une lecture.
Si des commandes ou des emails clients ont pu sortir, le dossier n'est plus seulement « rôle ». C'est un volet données. Ne communiquez pas « simple souci de compte » tant que ce point n'est pas tranché.
Relire les rôles à J+7
Une persistance (mu-plugin, cron, voisin) réeffectue l'UPDATE. La relecture à une semaine n'est pas de la paranoïa, c'est le test. Ajoutez une alerte si vous avez un plugin qui journalise les changements de rôle — posé après nettoyage, pas pendant.
Les comptes « prestataire temporaire » ont tendance à revenir admin « le temps d'une maj ». Donnez un rôle plus bas, un accès FTP révocable, ou WP-CLI le temps du chantier. Un admin de plus est une surface de plus.
- Plus aucun user élevé non nommé.
- Sessions détruites, clés AUTH neuves.
- Application passwords et clés REST relues.
- Contrôle rôles à J+7.
Ce qui n'est pas une élévation
WooCommerce passe un invité en `customer` à la commande : normal. Un import d'users depuis un CSV mal mappé qui pose tout le monde admin : erreur humaine, même urgence (rétrograder), autre cause. Un multisite où quelqu'un est admin d'un site et pas du réseau : lisez le contexte, ne rétrogradez pas le super-admin au jugé.
Si vous n'arrivez pas à départager faille, API et base, copiez, tournez le panel, et déclarez. Tricher un rôle dans phpMyAdmin sans trouver l'entrée, c'est gagner quarante-huit heures.