La sécurité des données est une priorité absolue de nos jours. Parfois, elle est imposée par des réglementations externes telles que PCI-DSS ou HIPAA, parfois c'est parce que vous vous souciez des données de vos clients et de votre réputation. Vous devez garder à l'esprit de nombreux aspects de la sécurité :accès au réseau, sécurité du système d'exploitation, autorisations, cryptage, etc. Dans cet article de blog, nous vous donnerons 10 conseils sur ce qu'il faut regarder lors de la sécurisation de votre configuration MySQL ou MariaDB.
1. Supprimer les utilisateurs sans mot de passe
MySQL était fourni avec un ensemble d'utilisateurs pré-créés, dont certains peuvent se connecter à la base de données sans mot de passe ou, pire encore, des utilisateurs anonymes. Cela a changé dans MySQL 5.7 qui, par défaut, n'est fourni qu'avec un compte root qui utilise le mot de passe que vous choisissez au moment de l'installation. Pourtant, il existe des installations MySQL qui ont été mises à niveau à partir de versions précédentes et ces installations conservent les utilisateurs hérités. De plus, MariaDB 10.2 sur Centos 7 est livré avec des utilisateurs anonymes :
MariaDB [(none)]> select user, host, password from mysql.user where user like '';
+------+-----------------------+----------+
| user | host | password |
+------+-----------------------+----------+
| | localhost | |
| | localhost.localdomain | |
+------+-----------------------+----------+
2 rows in set (0.00 sec)
Comme vous pouvez le voir, ceux-ci sont limités uniquement à l'accès depuis localhost, mais quoi qu'il en soit, vous ne voulez pas avoir d'utilisateurs comme ça. Bien que leurs privilèges soient limités, ils peuvent toujours exécuter certaines commandes qui peuvent afficher plus d'informations sur la base de données - par exemple, la version peut aider à identifier d'autres vecteurs d'attaque.
[[email protected] ~]# mysql -uanonymous_user
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 19
Server version: 10.2.11-MariaDB MariaDB Server
Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> SHOW GRANTS\G
*************************** 1. row ***************************
Grants for @localhost: GRANT USAGE ON *.* TO ''@'localhost'
1 row in set (0.00 sec)
MariaDB [(none)]> \s
--------------
mysql Ver 15.1 Distrib 10.2.11-MariaDB, for Linux (x86_64) using readline 5.1
Connection id: 19
Current database:
Current user: [email protected]
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server: MariaDB
Server version: 10.2.11-MariaDB MariaDB Server
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: latin1
Db characterset: latin1
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 12 min 14 sec
Threads: 7 Questions: 36 Slow queries: 0 Opens: 17 Flush tables: 1 Open tables: 11 Queries per second avg: 0.049
--------------
Veuillez noter que les utilisateurs avec des mots de passe très simples sont presque aussi peu sûrs que les utilisateurs sans mot de passe. Les mots de passe comme "password" ou "qwerty" ne sont pas vraiment utiles.
2. Accès à distance restreint
Tout d'abord, l'accès à distance pour les super-utilisateurs - cela est pris en charge par défaut lors de l'installation de la dernière version de MySQL (5.7) ou MariaDB (10.2) - seul l'accès local est disponible. Pourtant, il est assez courant de voir des superutilisateurs disponibles pour diverses raisons. Le plus courant, probablement parce que la base de données est gérée par des humains qui veulent faciliter leur travail, ils ajouteraient donc un accès à distance à leurs bases de données. Ce n'est pas une bonne approche car l'accès à distance facilite l'exploitation des vulnérabilités de sécurité potentielles (ou vérifiées) dans MySQL - vous n'avez pas besoin d'établir d'abord une connexion à l'hôte.
Une autre étape - assurez-vous que chaque utilisateur ne peut se connecter à MySQL qu'à partir d'hôtes spécifiques. Vous pouvez toujours définir plusieurs entrées pour le même utilisateur ([email protected], [email protected]), cela devrait aider à réduire le besoin de caractères génériques ([email protected]'%').
3. Supprimer la base de données de test
La base de données de test, par défaut, est accessible à tous les utilisateurs, en particulier aux utilisateurs anonymes. Ces utilisateurs peuvent créer des tables et y écrire. Cela peut potentiellement devenir un problème en soi - toute écriture ajouterait une surcharge et réduirait les performances de la base de données. Actuellement, après l'installation par défaut, seule MariaDB 10.2 sur Centos 7 est affectée par cela - Oracle MySQL 5.7 et Percona Server 5.7 n'ont pas le schéma "test" disponible.
[[email protected] ~]# mysql -uanonymous_user
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 13
Server version: 10.2.11-MariaDB MariaDB Server
Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> SHOW GRANTS\G
*************************** 1. row ***************************
Grants for @localhost: GRANT USAGE ON *.* TO ''@'localhost'
1 row in set (0.00 sec)
MariaDB [(none)]> USE test;
Database changed
MariaDB [test]> CREATE TABLE testtable (a INT);
Query OK, 0 rows affected (0.01 sec)
MariaDB [test]> INSERT INTO testtable VALUES (1), (2), (3);
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
MariaDB [test]> SELECT * FROM testtable;
+------+
| a |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
Bien sûr, il peut toujours arriver que votre MySQL 5.7 ait été mis à jour à partir de versions précédentes dans lesquelles le schéma "test" n'a pas été supprimé - vous devez vous en occuper et vérifier si vous l'avez créé.
4. Obfusquer l'accès à MySQL
Il est bien connu que MySQL s'exécute sur le port 3306 et que son superutilisateur s'appelle "root". Pour rendre les choses plus difficiles, il est assez simple de changer cela. Dans une certaine mesure, il s'agit d'un exemple de sécurité par l'obscurité, mais cela peut au moins arrêter les tentatives automatisées d'accès à l'utilisateur "root". Pour changer de port, vous devez modifier my.cnf et définir la variable "port" sur une autre valeur. En ce qui concerne les utilisateurs - après l'installation de MySQL, vous devez créer un nouveau superutilisateur (GRANT ALL … WITH GRANT OPTION), puis supprimer les comptes "[email protected]" existants.
5. Sécurité du réseau
Idéalement, MySQL ne serait pas disponible via le réseau et toutes les connexions seraient gérées localement, via le socket Unix. Dans certaines configurations, cela est possible - dans ce cas, vous pouvez ajouter la variable "skip-networking" dans my.cnf. Cela empêchera MySQL d'utiliser toute communication TCP/IP, seul le socket Unix serait disponible sous Linux (canaux nommés et mémoire partagée sur les hôtes Windows).
Cependant, la plupart du temps, une sécurité aussi stricte n'est pas réalisable. Dans ce cas, vous devez trouver une autre solution. Tout d'abord, vous pouvez utiliser votre pare-feu pour autoriser le trafic uniquement à partir d'hôtes spécifiques vers le serveur MySQL. Par exemple, les hôtes d'application (bien qu'ils devraient être d'accord pour atteindre MySQL via des proxys), la couche proxy et peut-être un serveur de gestion. Les autres hôtes de votre réseau n'ont probablement pas besoin d'un accès direct au serveur MySQL. Cela limitera les possibilités d'attaque sur votre base de données, au cas où certains hôtes de votre réseau seraient compromis.
S'il vous arrive d'utiliser des proxys qui permettent la correspondance d'expressions régulières pour les requêtes, vous pouvez les utiliser pour analyser le trafic SQL et bloquer les requêtes suspectes. Très probablement, vos hôtes d'application ne devraient pas exécuter "DELETE * FROM your_table;" régulièrement. S'il est nécessaire de supprimer certaines données, il peut être exécuté manuellement, localement, sur l'instance MySQL. Vous pouvez créer de telles règles en utilisant quelque chose comme ProxySQL :bloquer, réécrire, rediriger ces requêtes. MaxScale vous offre également la possibilité de bloquer les requêtes basées sur des expressions régulières.
6. Plug-ins d'audit
Si vous souhaitez collecter des données sur qui a exécuté quoi et quand, plusieurs plugins d'audit sont disponibles pour MySQL. Si vous utilisez MySQL Enterprise, vous pouvez utiliser MySQL Enterprise Audit qui est une extension de MySQL Enterprise. Percona et MariaDB ont également leur propre version de plugins d'audit. Enfin, le plugin McAfee pour MySQL peut également être utilisé avec différentes versions de MySQL. De manière générale, ces plugins collectent plus ou moins les mêmes données - événements de connexion et de déconnexion, requêtes exécutées, tables consultées. Tout cela contient des informations sur l'utilisateur qui a participé à un tel événement, à partir de quel hôte il s'est connecté, quand cela s'est-il produit, etc. La sortie peut être XML ou JSON, il est donc beaucoup plus facile de l'analyser que d'analyser le contenu général du journal (même si les données sont assez similaires). Une telle sortie peut également être envoyée à syslog et, en outre, à une sorte de serveur de journalisation pour le traitement et l'analyse.
7. Désactiver LOAD DATA LOCAL INFILE
Si le serveur et le client ont la possibilité d'exécuter LOAD DATA LOCAL INFILE, un client pourra charger des données d'un fichier local vers un serveur MySQL distant. Ceci, potentiellement, peut aider à lire les fichiers auxquels le client a accès - par exemple, sur un serveur d'application, on pourrait accéder à n'importe quel fichier auquel le serveur HTTP a accès. Pour l'éviter, vous devez définir local-infile=0 dans le my.cnf
8. Privilèges de fichier
Vous devez garder à l'esprit que la sécurité de MySQL dépend également de la configuration du système d'exploitation. MySQL stocke les données sous forme de fichiers. Le serveur MySQL écrit de nombreuses informations dans les journaux. Parfois, ces informations contiennent des données - journal des requêtes lentes, journal général ou journal binaire, par exemple. Vous devez vous assurer que ces informations sont sécurisées et accessibles uniquement aux utilisateurs qui doivent y accéder. En règle générale, cela signifie que seuls le root et l'utilisateur sous les droits desquels MySQL s'exécute doivent avoir accès à tous les fichiers liés à MySQL. La plupart du temps, il s'agit d'un utilisateur dédié appelé "mysql". Vous devez vérifier les fichiers de configuration MySQL et tous les journaux générés par MySQL et vérifier qu'ils ne sont pas lisibles par d'autres utilisateurs.
9. SSL et chiffrement des données en transit
Empêcher les gens d'accéder aux fichiers de configuration et aux fichiers journaux est une chose. L'autre problème est de s'assurer que les données sont transférées en toute sécurité sur le réseau. À l'exception des configurations où tous les clients sont locaux et utilisent le socket Unix pour accéder à MySQL, dans la majorité des cas, les données qui forment un ensemble de résultats pour une requête quittent le serveur et sont transférées au client via le réseau. Les données peuvent également être transférées entre les serveurs MySQL, par exemple via une réplication MySQL standard ou au sein d'un cluster Galera. Le trafic réseau peut être reniflé et, par ce biais, vos données seraient exposées.
Pour éviter que cela ne se produise, il est possible d'utiliser SSL pour chiffrer le trafic, à la fois côté serveur et côté client. Vous pouvez créer une connexion SSL entre un client et un serveur MySQL. Vous pouvez également créer une connexion SSL entre votre maître et vos esclaves, ou entre les nœuds d'un cluster Galera. Cela garantira que toutes les données transférées sont sécurisées et ne peuvent pas être reniflées par un attaquant qui a accédé à votre réseau.
La documentation MySQL explique en détail comment configurer le cryptage SSL. Si vous le trouvez trop lourd, ClusterControl peut vous aider à déployer un environnement sécurisé pour la réplication MySQL ou le cluster Galera en quelques clics :
10. Chiffrement des données au repos
La sécurisation des données en transit à l'aide du cryptage SSL ne résout que partiellement le problème. Vous devez également prendre soin des données au repos - toutes les données stockées dans la base de données. Le chiffrement des données au repos peut également être une exigence pour les réglementations de sécurité telles que HIPAA ou PCI DSS. Un tel cryptage peut être mis en œuvre à plusieurs niveaux - vous pouvez crypter l'intégralité du disque sur lequel les fichiers sont stockés. Vous pouvez chiffrer uniquement la base de données MySQL grâce aux fonctionnalités disponibles dans les dernières versions de MySQL ou MariaDB. Le cryptage peut également être implémenté dans l'application, afin qu'elle crypte les données avant de les stocker dans la base de données. Chaque option a ses avantages et ses inconvénients :le chiffrement de disque ne peut être utile que lorsque les disques sont physiquement volés, mais les fichiers ne seraient pas chiffrés sur un serveur de base de données en cours d'exécution. Le chiffrement de la base de données MySQL résout ce problème, mais il ne peut pas empêcher l'accès aux données lorsque le compte root est compromis. Le chiffrement au niveau de l'application est le plus flexible et le plus sûr, mais vous perdez alors la puissance de SQL ; il est assez difficile d'utiliser des colonnes chiffrées dans les clauses WHERE ou JOIN.
Toutes les variantes de MySQL fournissent une sorte de chiffrement des données au repos. MySQL d'Oracle utilise Transparent Data Encryption pour chiffrer les espaces de table InnoDB. Ceci est disponible dans l'offre commerciale MySQL Enterprise. Il fournit une option pour chiffrer les espaces de table InnoDB, d'autres fichiers qui stockent également des données sous une certaine forme (par exemple, les journaux binaires, le journal général, le journal des requêtes lentes) ne sont pas chiffrés. Cela permet à la chaîne d'outils (MySQL Enterprise Backup mais aussi xtrabackup, mysqldump, mysqlbinlog) de fonctionner correctement avec une telle configuration.
À partir de MySQL 5.7.11, la version communautaire de MySQL prend également en charge le chiffrement de l'espace de table InnoDB. La principale différence par rapport à l'offre d'entreprise est la manière dont les clés sont stockées - les clés ne sont pas situées dans un coffre-fort sécurisé, ce qui est requis pour la conformité réglementaire. Cela signifie qu'à partir de Percona Server 5.7.11, il est également possible de chiffrer l'espace de table InnoDB. Dans le Percona Server 5.7.20 récemment publié, la prise en charge du chiffrement des journaux binaires a été ajoutée. Il est également possible de s'intégrer au serveur Hashicorp Vault via un plug-in keyring_vault, correspondant (et même étendant - chiffrement de journal binaire) aux fonctionnalités disponibles dans l'édition MySQL Enterprise d'Oracle.
MariaDB a ajouté la prise en charge du chiffrement des données dans la version 10.1.3 - il s'agit d'une implémentation distincte et améliorée. Il vous donne la possibilité non seulement de chiffrer les espaces de table InnoDB, mais également les fichiers journaux InnoDB. Par conséquent, les données sont plus sécurisées, mais certains outils ne fonctionneront pas dans une telle configuration. Xtrabackup ne fonctionnera pas avec les redo logs chiffrés - MariaDB a créé un fork, MariaDB Backup, qui ajoute la prise en charge du chiffrement MariaDB. Il y a aussi des problèmes avec mysqlbinlog.
Quelle que soit la version de MySQL que vous utilisez, tant qu'il s'agit d'une version récente, vous aurez la possibilité d'implémenter le chiffrement des données au repos via le serveur de base de données, en vous assurant que vos données sont en outre sécurisées.
Sécuriser MySQL ou MariaDB n'est pas anodin, mais nous espérons que ces 10 conseils vous aideront tout au long du processus.
Résumé
Dans le paysage actuel, la sécurité des données est une priorité absolue pour chaque administrateur de base de données. Que votre motivation soit la conformité aux exigences réglementaires ou la protection de vos clients et de la réputation de votre entreprise, ces dix conseils pour sécuriser vos bases de données MySQL et MariaDB vous aideront à sécuriser davantage votre infrastructure et vous apporteront la tranquillité d'esprit.
Il existe de nombreuses mesures à prendre en compte pour garantir la sécurité de votre infrastructure de base de données. Dans cet article, nous avons couvert les principes fondamentaux tels que le cryptage des données, les contrôles d'accès au réseau, l'authentification et les privilèges des utilisateurs, la sécurité du système d'exploitation, etc.
Un logiciel d'automatisation de la gestion de base de données, comme ClusterControl, peut être un excellent outil pour vous aider dans vos efforts de sécurité globale de base de données. Si vous cherchez à approfondir chaque étape que vous devez suivre pour sécuriser vos bases de données MySQL, assurez-vous de consulter les parties 1 et 2 de notre série sur Comment sécuriser MySQL. Pour rester informé des autres meilleures pratiques de gestion de base de données, suivez-nous sur Twitter, LinkedIn et abonnez-vous à notre newsletter pour les mises à jour.