GA

2021/09/15

MySQL 5.6とそれ以前は「testデータベースを消せば良いってもんじゃない」というはなし

TL;DR

  • MySQL 5.6とそれ以前のはなし。5.7とそれ以降はこの初期設定は入っていない。

    • MySQL 5.6でもインストール方法によっては存在しないし mysql_secure_installation を使った場合はこの設定は消されるし、MySQL 5.7とそれ以降だろうと5.6からインプレースアップグレードやmysqlスキーマまで含めたフルリストアでアップグレードした場合は設定は残っているだろう
  • 昔のMySQLは test というスキーマを mysql_install_db で作ってしまって、しかもこのスキーマは全アカウントに対して(ストアド以外の)読み書き権限がある

    • GRANT USAGE しかないアカウントでも平気で CREATE TABLEINSERT も一通りできる

    • ついでに言うと test スキーマだけじゃなくて test_1 スキーマにも同じことができる。 test_* のパターンを持つスキーマなら全部そう

  • DROP DATABASE test したところで、誰にでも CREATE DATABASE test する権限があるので、そんなことより権限を剥がす方が先

    • DELETE mysql.db WHERE user = '' AND host = '%'; FLUSH PRIVILEGES; かな

MySQL 5.6は2021/2/1で EOL になっているので、そもそも使わない方が良いだろうし、今日日の5.6とそれ以前限定の話をするのもどうかなとは思っている。が、アップグレードの仕方によってはこの設定は残っているので注意。

取り敢えず、5.6.51の吊るしの mysql_install_db でdatadirを初期化する。


$ ./scripts/mysql_install_db --datadir=/usr/mysql/5.6.51/data

Installing MySQL system tables...2021-09-15 15:11:03 0 [Note] Ignoring --secure-file-priv value as server is running with --bootstrap.

2021-09-15 15:11:03 0 [Note] ./bin/mysqld (mysqld 5.6.51-log) starting as process 4634 ...

OK

Filling help tables...2021-09-15 15:11:05 0 [Note] Ignoring --secure-file-priv value as server is running with --bootstrap.

2021-09-15 15:11:05 0 [Note] ./bin/mysqld (mysqld 5.6.51-log) starting as process 4666 ...

OK

..

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

この test スキーマができる。最近5.6とか使わないから久々に見たよ。

mysql56> CREATE USER yoku0825@localhost;
Query OK, 0 rows affected (0.00 sec)

コイツがどう悪いのかを試すために、何も権限を持っていないアカウントを作ってみる。

$ mysql56 -uyoku0825

mysql56> SHOW GRANTS;
+----------------------------------------------+
| Grants for yoku0825@localhost                |
+----------------------------------------------+
| GRANT USAGE ON *.* TO 'yoku0825'@'localhost' |
+----------------------------------------------+
1 row in set (0.01 sec)

mysql56> use test
Database changed

mysql56> CREATE TABLE t1 (num int);
Query OK, 0 rows affected (0.02 sec)

mysql56> SHOW TABLES;
+----------------+
| Tables_in_test |
+----------------+
| t1             |
+----------------+
1 row in set (0.00 sec)

フツーに CREATE TABLE できてしまった。これはいけない?
というか何の権限もないのに、この test スキーマをDROPすることももう一度CREATEすることもできる。

mysql56> DROP DATABASE test;
Query OK, 1 row affected (0.00 sec)

mysql56> CREATE DATABASE test;
Query OK, 1 row affected (0.00 sec)

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

それどころか、 test_ で始まるスキーマ名なら好きなようにできる。

mysql56> CREATE DATABASE test_yoku0825;
Query OK, 1 row affected (0.00 sec)

mysql56> ALTER DATABASE test_yoku0825 CHARSET utf8mb4;
Query OK, 1 row affected (0.00 sec)

mysql56> SHOW CREATE DATABASE test_yoku0825;
+---------------+---------------------------------------------------------------------------+
| Database      | Create Database                                                           |
+---------------+---------------------------------------------------------------------------+
| test_yoku0825 | CREATE DATABASE `test_yoku0825` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+---------------+---------------------------------------------------------------------------+
1 row in set (0.00 sec)

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

まれにだがよく(?) 「 test スキーマあるのいけないんで、DROPしてください」みたいな文面があるが、こんなもの消しても何の意味もなくて、この「SHOW GRANTSでは何も見えない何の権限も持っていないはずのアカウントが test スキーマを好きなようにできる」設定の方を何とかしないといけない。

ちなみにこの権限の根源は mysql.db テーブルにある。rootでログインしなおしてクエリーたたいてみる。

mysql56> SELECT * FROM mysql.db;
+------+---------+------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+
| Host | Db      | User | Select_priv | Insert_priv | Update_priv | Delete_priv | Create_priv | Drop_priv | Grant_priv | References_priv | Index_priv | Alter_priv | Create_tmp_table_priv | Lock_tables_priv | Create_view_priv | Show_view_priv | Create_routine_priv | Alter_routine_priv | Execute_priv | Event_priv | Trigger_priv |
+------+---------+------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+
| %    | test    |      | Y           | Y           | Y           | Y           | Y           | Y         | N          | Y               | Y          | Y          | Y                     | Y                | Y                | Y              | Y                   | N                  | N            | Y          | Y            |
| %    | test\_% |      | Y           | Y           | Y           | Y           | Y           | Y         | N          | Y               | Y          | Y          | Y                     | Y                | Y                | Y              | Y                   | N                  | N            | Y          | Y            |
+------+---------+------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+-----------------------+------------------+------------------+----------------+---------------------+--------------------+--------------+------------+--------------+
2 rows in set (0.00 sec)

空白のuserは「任意のuser」、hostの ‘%’ は任意のホスト。
この2行の設定により、 test スキーマと test_ で始まる任意のスキーマはほとんどのスキーマレベル権限を全アカウントに与えている。

mysql_secure_installation はこの2行を消してから FLUSH PRIVILEGES することでこの権限を消している。

https://github.com/mysql/mysql-server/blob/mysql-5.6.51/scripts/mysql_secure_installation.pl.in#L253

rootで消してから FLUSH PRIVILEGES

mysql56> DELETE FROM mysql.db WHERE user = '' AND host = '%';
Query OK, 2 rows affected (0.00 sec)

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

これで期待通りの動きになる。

$ mysql56 -uyoku0825

mysql56> SHOW GRANTS;
+----------------------------------------------+
| Grants for yoku0825@localhost                |
+----------------------------------------------+
| GRANT USAGE ON *.* TO 'yoku0825'@'localhost' |
+----------------------------------------------+
1 row in set (0.00 sec)

mysql56> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
+--------------------+
1 row in set (0.00 sec)

mysql56> use test;
ERROR 1044 (42000): Access denied for user 'yoku0825'@'localhost' to database 'test'

ただし、既存のコネクションは use でカレントデータベースを変えるか再接続しないと権限の変更は有効にはならないので、万全を期すならいったん再起動しておくと完璧だと思う。

0 件のコメント :

コメントを投稿