First Creation 2005/02/12
Last Update 2007/02/05
Bloody Mary > Technical Notes > MySQL のユーザー管理 - セキュリティ編

MySQL のユーザー管理 - セキュリティ編

ユーザーを追加したものの、実はまだセキュリティ的に不安が残る。なぜなら前回追加したユーザーは、スーパーユーザーに匹敵するほどの過剰な権限を与えられているのである。しかも、全てのデータベースにアクセスできる。これはとても危険なことだ。

本当は test というデータベースだけ操作できればいいのに、重要なデータベースに対してあらゆる操作ができてしまう。

他のユーザの(ZAURUS は一人で使っているからありえないが)データベースを閲覧したり、改ざんしたり、MySQL の管理者である root もしくは Administrator が削除されてしまうことだってあり得る。

そこで MySQL のユーザーに対し、特定のデータベースしか操作できないようにしてみた。

さらに、データベースに対する操作(コマンド)も制限してみよう。

不要なユーザと DB の削除

データベースへのアクセス権限が保存される場所

アクセス権限は mysql データベースの db テーブルに保存される。

mysql> use mysql;
Database changed

mysql> show tables;
+-----------------+
| Tables in mysql |
+-----------------+
| columns_priv    |
| db              |
| func            |
| host            |
| tables_priv     |
| user            |
+-----------------+
6 rows in set (0.00 sec)

では、db テーブルのカラムを見てみよう。

mysql> describe db;
+-----------------+---------------+------+-----+---------+-------+
| Field           | Type          | Null | Key | Default | Extra |
+-----------------+---------------+------+-----+---------+-------+
| Host            | char(60)      |      | PRI |         |       |
| Db              | char(32)      |      | PRI |         |       |
| User            | char(16)      |      | PRI |         |       |
| Select_priv     | enum('N','Y') |      |     | N       |       |
| Insert_priv     | enum('N','Y') |      |     | N       |       |
| Update_priv     | enum('N','Y') |      |     | N       |       |
| Delete_priv     | enum('N','Y') |      |     | N       |       |
| Create_priv     | enum('N','Y') |      |     | N       |       |
| Drop_priv       | enum('N','Y') |      |     | N       |       |
| Grant_priv      | enum('N','Y') |      |     | N       |       |
| References_priv | enum('N','Y') |      |     | N       |       |
| Index_priv      | enum('N','Y') |      |     | N       |       |
| Alter_priv      | enum('N','Y') |      |     | N       |       |
+-----------------+---------------+------+-----+---------+-------+
13 rows in set (0.00 sec)

mysql データベースの user テーブルにはなかった Db というこカラムが存在する。これがデータベースへの権限を保存しておくための場所らしい。

ユーザーの確認

どんなユーザーが存在するか、SELECT コマンドで確認してみる。

mysql> select user,host,db from db;
+------+------+---------+
| user | host | db      |
+------+------+---------+
|      | %    | test    |
|      | %    | test\_% |
+------+------+---------+
2 rows in set (0.00 sec)

空のユーザがあるではないか。どうやら test データベースにアクセスするためのユーザーらしい。

不要な空ユーザを削除する。

mysql> delete from mysql.user where user="";
Query OK, 2 rows affected (0.01 sec)

mysql> select user,host,db from db;
Empty set (0.00 sec)

test データベースの削除

test データベースは不要なので削除する。

mysql> drop database test;
Query OK, 0 rows affected (0.00 sec)

mysql> show databases;
+----------+
| Database |
+----------+
| mysql    |
| user_db  |
+----------+
2 rows in set (0.00 sec)

mysql と user_db データベースのみ残った。

ユーザ毎のデータベースへの権限を設定

bloody というデータベースを作成する一方、mary というユーザーを作成し、bloody への全権限を付与する。

1. bloody データベースの作成
mysql> create database bloody;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+----------+
| Database |
+----------+
| bloody   |
| mysql    |
| user_db  |
+----------+
3 rows in set (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
2. mary ユーザーの作成
mysql> grant all on bloody.* to mary@localhost identified by "my_password" with grant option;
Query OK, 0 rows affected (0.01 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)

とりあえずは全権限を付与してしまう。

「flush privileges;」はリロードの呪文だ。ユーザーを追加したり削除したりしたら唱えておいた方がいい。それほど手間ではないだろうし。

3. ユーザーと db テーブルの確認
mysql> select host,user,password from mysql.user;
+-----------+---------------+------------------+
| host      | user          | password         |
+-----------+---------------+------------------+
| localhost | mary          | 3c21f78362fdb84c |
| localhost | Administrator | 442455895eac74e7 |
+-----------+---------------+------------------+
2 rows in set (0.01 sec)

mysql> select * from mysql.user;
+-----------+---------------+------------------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+
| Host      | User          | Password         | Select_priv | Insert_priv | Update_priv | Delete_priv | Create_priv | Drop_priv | Reload_priv | Shutdown_priv | Process_priv | File_priv | Grant_priv | References_priv | Index_priv | Alter_priv |
+-----------+---------------+------------------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+
| localhost | mary          | 3c21f78362fdb84c | N           | N           | N           | N           | N           | N         | N           | N             | N            | N         | N          | N               | N          | N          |
| localhost | Administrator | 442455895eac74e7 | Y           | Y           | Y           | Y           | Y           | Y         | Y           | Y             | Y            | Y         | Y          | Y               | Y          | Y          |
+-----------+---------------+------------------+-------------+-------------+-------------+-------------+-------------+-----------+-------------+---------------+--------------+-----------+------------+-----------------+------------+------------+
2 rows in set (0.00 sec)

mysql> select * from db;
+-----------+--------+------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+
| Host      | Db     | User | Select_priv | Insert_priv | Update_priv | Delete_priv | Create_priv | Drop_priv | Grant_priv | References_priv | Index_priv | Alter_priv |
+-----------+--------+------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+
| localhost | bloodY | mary | Y           | Y           | Y           | Y           | Y           | Y         | Y          | Y               | Y          | Y          |
+-----------+--------+------+-------------+-------------+-------------+-------------+-------------+-----------+------------+-----------------+------------+------------+
1 row in set (0.00 sec)

ちなみに、上記の検索結果は、1280 * 1024 のモニタが2 つないと、折り返さず表示することはできない。おかげで分かりづらいことこの上ない。ナメてんのか・・・

気を取り直して、「select * from mysql.user;」で、mary権限がすべて N になっている。これは、mary というユーザでは、user データベースは一切操作ができない、ということを表している。

一方、「select * from db;」 を実行すると、mary の権限がすべて Y になっているのが確認できる。これは、mary というユーザが、bloody というテーブルに対して、全ての権限を持っている、ということを表している。

この状態で exit し、mary で MySQL を使ってみよう。

4. 権限の確認
# mysql -u mary -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 43 to server version: 3.22.32-log


Type help for help.


mysql> show databases;
+----------+
| Database |
+----------+
| bloody   |
| mysql    |
| user_db  |
+----------+
3 rows in set (0.00 sec)

mysql> use mysql;
ERROR 1044: Access denied for user: 'mary@localhost' to database 'mysql'

mary で mysql を使おうとすると、ちゃんと Access denied されてる。

逆に、bloody データベースに対しては何でもできてしまう。ちょっと権限を与えすぎた気もするが、これでよしとしよう。

戻る 上へ 次へ