# Isoler la base de chaque client avec des utilisateurs MySQL aux droits stricts

> Un serveur mutualisé hérite d'utilisateurs MySQL aux droits trop larges accumulés au fil des années. Check-list de remise à plat des permissions, base par base.

- Auteur : Clément Hadrot
- Publié le : 2025-09-24
- Mis à jour le : 2025-09-24
- Catégorie : Hébergement &amp; serveurs
- URL : https://wpmoderne.dev.wordpress-developpement.fr/hebergement/isoler-base-mysql-par-client-droits-stricts/

## L’essentiel

- Un utilisateur avec le privilège global sur toutes les bases est un risque en cas de compromission
- La remise à plat se fait base par base, sans interruption de service
- GRANT et REVOKE suffisent, sans réinstallation ni migration

Un audit de sécurité de routine sur un serveur mutualisé hébergeant vingt-deux sites WordPress clients a révélé un chiffre qui a fait tiquer toute l'équipe : quatorze des vingt-deux utilisateurs MySQL configurés disposaient d'un accès en lecture-écriture sur l'ensemble des bases du serveur, alors qu'aucun d'eux n'avait légitimement besoin d'accéder à autre chose que la base de son propre site.

Cette check-list ne traite pas de l'isolation des processus PHP-FPM, sujet distinct déjà couvert séparément. Elle détaille la remise à plat des permissions MySQL sur un serveur mutualisé existant, base par base, sans réinstallation ni migration, applicable sur un serveur en production sans interruption de service pour les sites concernés.

## Comprendre l'origine du problème

Ces droits trop larges ne résultent presque jamais d'une décision volontaire. Ils s'accumulent au fil du temps : un utilisateur créé rapidement avec `GRANT ALL PRIVILEGES ON *.* TO 'client'@'localhost'` pour dépanner un import de base un soir pressé, jamais révoqué ensuite ; un script de provisioning ancien qui créait systématiquement des comptes avec des droits globaux par simplicité, avant que l'équipe ne standardise sur des droits restreints par base.

Le risque concret : si l'un de ces vingt-deux sites WordPress est compromis via une faille applicative (plugin vulnérable, thème obsolète), l'attaquant qui obtient les identifiants de base de données stockés dans `wp-config.php` peut, avec un utilisateur aux droits globaux, accéder également aux vingt et une autres bases du serveur, alors qu'un utilisateur correctement restreint ne lui aurait donné accès qu'à une seule.

> L'essentiel à retenir : Un utilisateur avec le privilège global sur toutes les bases est un risque en cas de compromission ; La remise à plat se fait base par base, sans interruption de service ; GRANT et REVOKE suffisent, sans réinstallation ni migration

## Étape 1 — Cartographier l'existant avant toute modification

La première étape, indispensable, consiste à lister précisément qui a accès à quoi avant de toucher à quoi que ce soit. La commande `SHOW GRANTS FOR 'utilisateur'@'localhost';` exécutée pour chaque utilisateur permet de dresser cette cartographie exacte. Sur MySQL 8 comme sur MariaDB, la table `mysql.db` et la vue `information_schema.SCHEMA_PRIVILEGES` permettent également une requête globale plus rapide pour repérer d'un coup tous les privilèges au niveau serveur (`*.*`) attribués à chaque compte.

## Étape 2 — Créer des comptes restreints en parallèle

Plutôt que de modifier directement les droits d'un utilisateur en production — ce qui coupe l'accès au site le temps de la transition — la méthode la plus sûre consiste à créer un nouvel utilisateur restreint, à basculer `wp-config.php` vers ce nouvel utilisateur, à vérifier que le site fonctionne normalement, puis seulement ensuite à révoquer et supprimer l'ancien compte trop permissif.

```
CREATE USER 'client_isole'@'localhost' IDENTIFIED BY 'mot-de-passe-genere';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX
  ON client_wp.* TO 'client_isole'@'localhost';
FLUSH PRIVILEGES;
```

Ce jeu de privilèges couvre l'ensemble des opérations dont WordPress a réellement besoin au quotidien (lecture, écriture, création de tables lors d'une migration de plugin, modification de structure) sans jamais octroyer d'accès aux autres bases du serveur ni de privilèges d'administration globale comme `SUPER` ou `GRANT OPTION`.

## Étape 3 — Basculer et vérifier sans interruption

- Mettre à jour les constantes `DB_USER` et `DB_PASSWORD` dans `wp-config.php`.
- Vérifier immédiatement l'accès au site et à l'administration WordPress.
- Tester une opération d'écriture réelle (publication d'un brouillon, mise à jour d'une option) pour confirmer les droits `INSERT` et `UPDATE`.
- Tester une opération de migration si un plugin est prévu prochainement, pour confirmer les droits `ALTER` et `CREATE`.

## Étape 4 — Révoquer proprement l'ancien compte

Une fois le nouveau compte validé sur plusieurs jours d'utilisation normale, l'ancien utilisateur aux droits globaux est révoqué puis supprimé : `REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'client'@'localhost'; DROP USER 'client'@'localhost';`. Cette étape est systématiquement reportée de quelques jours par précaution, le temps de s'assurer qu'aucun script de sauvegarde ou de supervision oublié n'utilisait encore cet ancien compte.

> Un droit accordé "pour dépanner un soir" devient, en pratique, un droit permanent tant que personne ne prend explicitement le temps de le révoquer. La remise à plat régulière n'est pas un luxe, c'est un entretien de base.

## Notre check-list finale

Sur ce serveur de vingt-deux sites, la remise à plat complète a pris deux journées de travail réparties sur une semaine, sans aucune interruption de service constatée par les clients. La documentation officielle de MySQL sur le système de privilèges reste la référence à consulter en cas de doute sur la portée exacte d'un privilège donné : [dev.mysql.com/doc/refman](https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html).
