6.4. Configuration initiale

6.4.1. Utilisateurs

Par defaut, MySQL 5 sous Ubuntu est configuré avec 2 utilisateurs : root et debian-sys-maint. Le premier sert à l'administration du SGBD : création des bases, création des utilisateurs, etc... Le deuxième en revanche sert au démarrage, à l'arrêt et à la mise à jour des packages de la base. root n'a pas de mot de passe par défaut. La première des choses à faire après l'installation de la base est donc de lui en affecter un. mysqladmin permet de changer des mots de passe, mais aussi de créér/supprimer des bases de données, de démarrer/stopper un serveur, ...

Pour modifier le mot de passe d'un utilisateur MySQL il y a plusieurs possibilités, mais nous n'en verrons que deux. Nous pouvons le faire directement en ligne de commande soit en ligne de commande bash (voir les remarques à ce sujet dans Section 6.3.4, « Outils ») :

root@ubuntu:~# mysqladmin password "nouveaumotdepasse" ❶
root@ubuntu:~# mysqladmin password "nouveaumotdepasse" ❷

mysqladmin: connect to server at 'localhost' failed
error: 'Access denied for user 'root'@'localhost' (using password: NO)' ❸

root@ubuntu:~# history -r
root@ubuntu:~# 

modification du mot de passe

une fois le mot de passe modifié, il faut utiliser -p !

relecture de l'historique

Une autre solution est de le faire en ligne de commande MySQL :

root@ubuntu:~# mysql ❶
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 36
Server version: 5.0.38-Ubuntu_0ubuntu1-log Ubuntu 7.04 distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> SET PASSWORD FOR root@localhost=PASSWORD('nouveaumotdepasse'); ❷
Query OK, 0 rows affected (0.12 sec)

mysql> FLUSH PRIVILEGES; ❸
Query OK, 0 rows affected (0.02 sec)

mysql> QUIT ❹
Bye
root@ubuntu:~# cat /dev/null > ~/.mysql_history ❺

root@ubuntu:~#

démarrage du shell MySQL.

modification du mot de passe pour l'utilisateur root se connectant depuis localhost.

flush privileges permet de demander au serveur MySQL de relire les droits.

fermeture du shell MySQL

le shell mysql aussi a son historique... (voir Section 6.4.4, « En finir avec l'historique » pour une solution définitive)

Pour plus de sécurité, on peut aussi modifier le nom du « super-utilisateur » MySQL. Par défaut c'est root, mais une fois de plus, rien ne nous oblige à utiliser ce compte. Pour changer le nom de l'utilisateur, il faudra faire les modifications directement en SQL dans la table système (table mysql).

root@ubuntu:~# mysql -p ❶

Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 37
Server version: 5.0.38-Ubuntu_0ubuntu1-log Ubuntu 7.04 distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> USE mysql; ❷

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> UPDATE user SET user='dbadmin' WHERE user='root'; ❸  

Query OK, 3 rows affected (0.11 sec)
Rows matched: 3  Changed: 3  Warnings: 0

mysql> FLUSH PRIVILEGES; ❹

Query OK, 0 rows affected (0.01 sec)

mysql> QUIT
Bye
root@ubuntu:~# mysql -p
Enter password: 
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) ❺

root@ubuntu:~# mysql -u dbadmin -p

Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g. ❻

Your MySQL connection id is 39
Server version: 5.0.38-Ubuntu_0ubuntu1-log Ubuntu 7.04 distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> QUIT
Bye
root@ubuntu:~# cat /dev/null > ~/.mysql_history

démarrage du shell MySQL.

use permet de changer la base de données en cours. use mysql; indique que l'on veut utiliser la base de données mysql. On aurait pu aboutir au même résultat en démarrant le sheel mysql avec mysql en option (mysql mysql -p).

update est une commande SQL permettant de modifier des enregistrements dans une table. Ici, on demande de changer la valeur de user en dbadmin pour tous les enregistrements de la table user dont le champ user vaut root.

flush privileges permet de demander au serveur MySQL de relire les droits.

même avec le bon mot de passe, mysql nous refuse : l'utilisateur root n'existe plus. Nous devons donc spécifier l'utilisateur avec l'option -u.

avec le bon utilisateur, pas de problème

Selon les version de MySQL et les OS qui les packagent, on trouve parfois un utilisateur anonyme configuré par défaut[18]. Même si cet utilisateur n'a en général pas de droits, il est préférable de le supprimer afin d'éliminer un vecteur potentiel d'intrusion dans la base de données. Il faudra donc se connecter à la base mysql et supprimer l'utilisateur '' (dont le nom est vide) dans la table user.

Attention : les utilisateurs peuvent apparaître plusieurs fois dans la table user, puisque la clef de cette table est le couple (utilisateur, hôte de connexion).

root@ubuntu:~# mysql -u dbadmin -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 40
Server version: 5.0.38-Ubuntu_0ubuntu1-log Ubuntu 7.04 distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema | 
| mysql              | 
| test               | 
+--------------------+
3 rows in set (0.03 sec)

mysql> USE mysql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> DELETE FROM user WHERE user='';
Query OK, 1 row affected (0.00 sec)

mysql> DELETE FROM db WHERE user='';
Query OK, 2 rows affected (0.01 sec)

mysql> 

Enfin, on pourra faire une dernière passe sur la base de données système mysql afin de s'assurer que seuls les droits nécessaires sont activés.

mysql> DELETE FROM db; ❶
Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM user WHERE NOT (host="localhost" AND (user="dbadmin" OR user="debian-sys-maint")); ❷
Query OK, 3 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES; ❸
Query OK, 0 rows affected (0.00 sec)

mysql>

suppression de toutes les règles de la table db.

suppression de tous les utilisateurs qui ne sont pas root ou debian-sys-maint.

actualisation des droits.

6.4.2. Bases de données

Les opérations de création et suppression peuvent aussi s'effectuer de deux façons : en ligne de commande bash, ou en ligne de commande mysql. La première méthode utilise encore mysqladmin avec les arguments create ou drop :

root@ubuntu:~# mysqladmin create mabase -u dbadmin -p ❶
Enter password: 
root@ubuntu:~# mysqlshow -u dbadmin mabase -p ❷
Enter password: 
Database: mabase
+--------+
| Tables |
+--------+
+--------+
root@ubuntu:~# 

creation de la base en ligne de commande.

mysqlshow permet d'obtenir des informations sur des bases, des tables et des champs.

En cas de regrets mysqladmin drop permet de supprimer la base :

root@ubuntu:~# mysqladmin drop mabase -u dbadmin -p
Enter password: 
Dropping the database is potentially a very bad thing to do.
Any data stored in the database will be destroyed.

Do you really want to drop the 'mabase' database [y/N] y
Database "mabase" dropped
root@ubuntu:~# mysqlshow -u dbadmin mabase -p
Enter password: 
mysqlshow: Unknown database 'mabase'
root@ubuntu:~# 

Si l'on préfère la version ligne de commande mysql, on fera :

root@ubuntu:~# mysql -u dbadmin -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 17
Server version: 5.0.38-Ubuntu_0ubuntu1-log Ubuntu 7.04 distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> CREATE DATABASE mabase;
Query OK, 1 row affected (0.01 sec)

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema | 
| mabase             | 
| mysql              | 
| test               | 
+--------------------+
4 rows in set (0.00 sec)

mysql> DROP DATABASE mabase;
Query OK, 0 rows affected (0.01 sec)

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema | 
| mysql              | 
| test               | 
+--------------------+
3 rows in set (0.00 sec)

mysql>

On pourra pratiquer en réèl sur la base test. Cette base est livrée avec toutes les versions de MySQL et apparemment sous tous les OS supportés. Comme pour l'utilsateur anonyme, il est préférable de s'en débarasser : elle n'apporte rien sinon un vecteur potentiel pour un attaquant. Cela pourra éventuellement ennuyer quelques modules Perl liés à MySQL qui testent parfois leur bon fonctionnement en utilisant la base test comme cobaye. Dans ce cas, il faudra forcer leur installation ou recréer la base test.

mysql> DROP DATABASE test;
Query OK, 0 rows affected (0.01 sec)

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema | 
| mysql              | 
+--------------------+
2 rows in set (0.00 sec)

mysql> 

6.4.3. my.cnf

Une commande particulièrement dangereuse sous MySQL est LOAD DATA INFILE. Elle permet d'insérer le contenu d'un fichier dans une base de données. Si, via une application PHP, une attaquante arrive à injecter du code SQL, elle pourra éventuellement remplir des tables avec des informations sensibles :

root@ubuntu:~# mysql -u dbadmin -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.0.38-Ubuntu_0ubuntu1-log Ubuntu 7.04 distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> LOAD DATA LOCAL INFILE "/etc/passwd" INTO TABLE mydb.res;
Query OK, 29 rows affected (0.07 sec)
Records: 29  Deleted: 0  Skipped: 0  Warnings: 0

mysql> SELECT * FROM res WHERE texte LIKE 'root%';
+---------------------------------+
| texte                           |
+---------------------------------+
| root:x:0:0:root:/root:/bin/bash | 
+---------------------------------+
1 row in set (0.00 sec)

mysql>

On voit les problèmes que ce genre de commande peut amener : une exposition de la totalité des fichiers de configuration système : réupération des identifiants utilisateur sur le système afin de préparer une attaque par force brute, escalade de privilèges en récupérant les informations d'authentification dans /etc/mysql/debian.cnf, etc... On veillera donc à supprimer l'accès à LOCAL INFILE dans le fichier de configuration en ajoutant : set-variable = local-infile=0 dans la section [mysqld]. Après avoir redémarré la base de données, il faudra vérifier que la configuration est correctement appliquée :

root@ubuntu:~# mysql -u dbadmin -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.0.38-Ubuntu_0ubuntu1-log Ubuntu 7.04 distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> LOAD DATA LOCAL INFILE "/etc/passwd" INTO TABLE mydb.res;
ERROR 1148 (42000): The used command is not allowed with this MySQL version
mysql> 

Par defaut sous Ubuntu la directive bind-address = 127.0.0.1 est dans le fichier de configuration par défaut. Elle permet de restreindre l'accès au port 3306 à la machine locale (127.0.0.1). On devra commenter cette directive uniquement si l'accès au serveur MySQL est requis depuis une autre machine. Si le serveur possède plusieurs interfaces, on ne « bindera » le serveur que sur l'interface nécessaire. Il est aussi possible de supprimer complètement l'accès au serveur MySQL via le réseau avec la directive skip-networking. Dans ce cas les clients devront utiliser la socket unix /var/run/mysqld/mysqld.sock pour se connecter à la base.

6.4.4. En finir avec l'historique

Comme on a pû le remarquer plus haut, le shell MySQL conserve un historique, à l'image de bash, dans le fichier ~/.mysql_history. On peut demander à mysql d'utiliser un autre fichier grâce à la variable d'environnement MYSQL_HISTFILE (tout comme HISTFILE dans le cas de bash).

Pour supprimer l'historique, il y a deux possibilités :

  • mettre « /dev/null » dans la variable MYSQL_HISTFILE (export MYSQL_HISTFILE="/dev/null" dans le fichier ~/.bashrc par exemple),

  • lier ~/.mysql_history à /dev/null (ln -sf /dev/null ~/.mysql_history).

6.4.5. Filtrage

La structure du filtrage étant déja en place, l'ouverture de l'accès à la base MySQL est très simple. On n'ouvrira l'accès au port que si cela est réèllement nécessaire, et, si possible, uniquement aux adresses IP qui le nécessitent. Il n'y a pas de raison d'ouvrir l'accès IP au serveur de bases de données à tout le monde.

Exemple 6.1. MySQL : configuration du filtrage TCP en entrée

#
# ######################################
# TCP entrant
# Il faudra ouvrir des ports au fil de l'eau
# lors de la mise en place de 
# services TCP (ssh, apache, ...).
# ######################################
#
-A TCP_IN -j TCP_INLIMITS
-A TCP_IN -j STATEFUL
-A TCP_IN -j TCP_SYNLIMITS
-A TCP_IN -p tcp -m tcp ! --tcp-flags SYN,RST,ACK SYN -m limit --limit 10/min -j LOG --log-prefix "TCP_IN:" --log-level 6 
-A TCP_IN -p tcp -m tcp ! --tcp-flags SYN,RST,ACK SYN -j DROP
# Ajouter les rêgles ici lors de l'installation de services TCP si ces services
# doivent être ouverts
#
-A TCP_IN -s adresse_ip_autorisée -p tcp -m tcp --dport 3306 -j ACCEPT ❶
# on peut aussi débloquer le port 3306 pour tout le monde
-A TCP_IN -p tcp -m tcp --dport 3306 -j ACCEPT ❷
#

Régle autorisant l'accès au port 3306/tcp (mysql) pour l'adresse adresse_ip_autorisée (qui peut aussi être un subnet). Cette règle peut être répétée autant de fois que nécessaire.

Régle autorisant l'accès au port 3306/tcp (mysql) pour tout le monde.




[18] Ce n'est pas le cas sous la Ubuntu 7.04 serveur