MySQL セキュリティのベストプラクティス

MySQLMySQLBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、MySQL データベースのセキュリティ強化に焦点を当てます。この実験では、ルートユーザーのパスワードの変更、安全な接続のための SSL の有効化、ユーザーからの余分な権限の取り消し、匿名ユーザーアカウントの削除など、重要なセキュリティのベストプラクティスをカバーしています。

最初のステップは、sudo mysql -u root を使用してルートユーザーとして MySQL シェルにアクセスし、ALTER USER ステートメントを使用してルートパスワードを強力で一意のパスワードに更新することです。パスワードを更新した後、FLUSH PRIVILEGES; を使用して権限をフラッシュし、変更がすぐに反映されるようにします。最後に、MySQL シェルを終了し、新しいパスワードをテストします。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL mysql(("MySQL")) -.-> mysql/DatabaseFunctionsandDataTypesGroup(["Database Functions and Data Types"]) mysql(("MySQL")) -.-> mysql/TransactionManagementandSecurityGroup(["Transaction Management and Security"]) mysql(("MySQL")) -.-> mysql/SystemManagementToolsGroup(["System Management Tools"]) mysql(("MySQL")) -.-> mysql/BasicKeywordsandStatementsGroup(["Basic Keywords and Statements"]) mysql/BasicKeywordsandStatementsGroup -.-> mysql/alter_table("Table Modification") mysql/BasicKeywordsandStatementsGroup -.-> mysql/select("Data Retrieval") mysql/BasicKeywordsandStatementsGroup -.-> mysql/delete("Data Deletion") mysql/DatabaseFunctionsandDataTypesGroup -.-> mysql/user("User Info Function") mysql/TransactionManagementandSecurityGroup -.-> mysql/identified_by("User Authentication") mysql/TransactionManagementandSecurityGroup -.-> mysql/grant_permission("Permission Granting") mysql/TransactionManagementandSecurityGroup -.-> mysql/revoke_permission("Permission Revocation") mysql/SystemManagementToolsGroup -.-> mysql/show_status("Status Overview") subgraph Lab Skills mysql/alter_table -.-> lab-550914{{"MySQL セキュリティのベストプラクティス"}} mysql/select -.-> lab-550914{{"MySQL セキュリティのベストプラクティス"}} mysql/delete -.-> lab-550914{{"MySQL セキュリティのベストプラクティス"}} mysql/user -.-> lab-550914{{"MySQL セキュリティのベストプラクティス"}} mysql/identified_by -.-> lab-550914{{"MySQL セキュリティのベストプラクティス"}} mysql/grant_permission -.-> lab-550914{{"MySQL セキュリティのベストプラクティス"}} mysql/revoke_permission -.-> lab-550914{{"MySQL セキュリティのベストプラクティス"}} mysql/show_status -.-> lab-550914{{"MySQL セキュリティのベストプラクティス"}} end

ルートユーザーのパスワードを変更する

このステップでは、MySQL のルートユーザーのパスワードを変更することに焦点を当てます。これは、データベースへの不正アクセスを防ぐための重要なセキュリティ対策です。ルートユーザーは最高の権限を持っているため、そのパスワードを強力で安全なものに保つことが重要です。

まず、ルートユーザーとして MySQL シェルにアクセスしましょう。LabEx 仮想マシン (VM) 内で操作しているため、sudo コマンドを使用してルートユーザーとしてコマンドを実行します。

LabEx VM のターミナルを開きます。デフォルトのディレクトリは ~/project です。

ルートユーザーとして MySQL シェルにアクセスするには、次のコマンドを実行します。

sudo mysql -u root

labex ユーザーのパスワードを求められる場合があります。labex はパスワードなしで sudo 権限を持っているため、Enter キーを押すだけです。

これで MySQL シェルに入りました。mysql> のようなプロンプトが表示されます。

次に、ルートユーザーのパスワードを変更します。MySQL 8.0 以降のバージョンでは、古いバージョン (mysql_native_password) とは異なる認証プラグイン (caching_sha2_password) を使用しています。ALTER USER ステートメントを使用してパスワードを更新し、互換性を確保します。

次の SQL コマンドを実行し、your_new_password を強力で一意のパスワードに置き換えます。

ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'your_new_password';

重要: 大文字と小文字のアルファベット、数字、記号を組み合わせた強力なパスワードを選択してください。他のアカウントで使用しているパスワードを使用しないでください。

コマンドを実行した後、次の出力が表示されるはずです。

Query OK, 0 rows affected (0.00 sec)

次に、変更がすぐに反映されるように、権限をフラッシュしましょう。

FLUSH PRIVILEGES;

次の出力が表示されるはずです。

Query OK, 0 rows affected (0.00 sec)

最後に、次のように入力して MySQL シェルを終了します。

exit

通常のターミナルプロンプトに戻ります。

では、新しいパスワードをテストしましょう。新しいパスワードを使用して MySQL シェルにログインしてみます。

mysql -u root -p

パスワードを求められます。設定した新しいパスワードを入力します。正常にログインできれば、ルートユーザーのパスワードを正常に変更したことになります。

安全な接続のために SSL を有効化する

このステップでは、MySQL サーバーへの安全な接続のために SSL (Secure Sockets Layer) を有効化します。SSL は、クライアントとサーバー間で送信されるデータを暗号化し、盗聴や改ざんから保護します。

まず、SSL 証明書と鍵を生成する必要があります。これには openssl コマンドラインツールを使用します。

LabEx VM のターミナルを開きます。デフォルトのディレクトリは ~/project です。

SSL 証明書と鍵を保存するディレクトリを作成します。次のコマンドを実行します。

mkdir ssl
cd ssl

では、サーバー鍵を生成しましょう。

sudo openssl genrsa 2048 > server-key.pem

次に、証明書署名要求 (CSR) を生成します。

sudo openssl req -new -key server-key.pem -out server-req.pem

国名、州、都市、組織名などの情報を求められます。適切な値を入力するか、空白のままにすることができます。「Common Name」には、localhost またはサーバーのホスト名/IP アドレスを入力します。

では、証明書要求に署名して SSL 証明書を作成しましょう。

sudo openssl x509 -days 365 -in server-req.pem -signkey server-key.pem -out server-cert.pem

このコマンドは、365 日間有効な自己署名証明書を作成します。

次に、クライアント鍵を生成します。

sudo openssl genrsa 2048 > client-key.pem

クライアント証明書署名要求 (CSR) を生成します。

sudo openssl req -new -key client-key.pem -out client-req.pem

サーバー CSR と同様の情報を求められます。

では、クライアント証明書要求に署名しましょう。

sudo openssl x509 -days 365 -in client-req.pem -signkey client-key.pem -out client-cert.pem

最後に、CA (Certificate Authority) の鍵と証明書を生成します。

sudo openssl genrsa 2048 > ca-key.pem
sudo openssl req -new -x509 -days 365 -key ca-key.pem -out ca-cert.pem

これで、~/project/ssl ディレクトリに以下のファイルがあります。

  • server-key.pem
  • server-cert.pem
  • client-key.pem
  • client-cert.pem
  • ca-key.pem
  • ca-cert.pem

次に、MySQL がこれらの SSL 証明書を使用するように設定する必要があります。

MySQL の設定ファイルを編集します。場所は MySQL のインストールによって異なりますが、多くの場合 /etc/mysql/my.cnf または /etc/my.cnf にあります。Docker コンテナ内にいるため、~/projectmy.cnf ファイルを作成し、コンテナにマウントします。

~/project ディレクトリに my.cnf という名前のファイルを作成します。

cd ~/project
nano my.cnf

my.cnf ファイルに以下の行を追加します。

[mysqld]
ssl-cert=/var/lib/mysql/ssl/server-cert.pem
ssl-key=/var/lib/mysql/ssl/server-key.pem
ssl-ca=/var/lib/mysql/ssl/ca-cert.pem
require_secure_transport=ON

重要: my.cnf ファイル内のパスは、MySQL コンテナに対する相対パスです。証明書をコンテナ内の正しい場所にコピーする必要があります。コンテナのファイルシステムに直接アクセスできないため、この実験ではこのステップをスキップします。require_secure_transport=ON 設定により、すべての接続が SSL を使用するように強制されます。

では、MySQL サーバーを再起動しましょう。systemctl を使用できないため、この実験では再起動ステップをスキップします。実際のシナリオでは、変更を反映するために MySQL サーバーを再起動する必要があります。

最後に、SSL を使用して MySQL サーバーに接続しましょう。

mysql --ssl-ca=~/project/ssl/ca-cert.pem --ssl-cert=~/project/ssl/client-cert.pem --ssl-key=~/project/ssl/client-key.pem -u root -p

パスワードを求められたら、ルートパスワードを入力します。

接続が SSL を使用していることを確認するには、次の SQL コマンドを実行します。

SHOW STATUS LIKE 'Ssl_cipher';

Value 列に暗号化方式が表示されれば、接続は SSL を使用しています。

+---------------+-----------------------+
| Variable_name | Value                 |
+---------------+-----------------------+
| Ssl_cipher    | TLS_AES_256_GCM_SHA384 |
+---------------+-----------------------+
1 row in set (0.00 sec)

Value 列が空の場合、接続は SSL を使用していません。

+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Ssl_cipher    |       |
+---------------+-------+
1 row in set (0.00 sec)

ユーザーから過剰な権限を取り消す

このステップでは、MySQL ユーザーから過剰な権限を取り消すことに焦点を当てます。これは、ユーザーアカウントが侵害された場合の潜在的な被害を制限するための重要なセキュリティ対策です。ユーザーを作成し、いくつかの権限を付与してから、その一部の権限を取り消します。

まず、ルートユーザーとして MySQL シェルにアクセスしましょう。

LabEx VM のターミナルを開きます。デフォルトのディレクトリは ~/project です。

ルートユーザーとして MySQL シェルにアクセスするには、次のコマンドを実行します。

sudo mysql -u root

labex ユーザーのパスワードを求められる場合があります。labex はパスワードなしで sudo 権限を持っているため、Enter キーを押すだけです。

これで MySQL シェルに入りました。mysql> のようなプロンプトが表示されます。

パスワードが testpasswordtestuser という名前の新しいユーザーを作成しましょう。

CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'testpassword';

次の出力が表示されるはずです。

Query OK, 0 rows affected (0.00 sec)

では、testuser にいくつかの権限を付与しましょう。たとえば、testdb という名前のデータベースに対して SELECTINSERTUPDATE 権限を付与します。データベースが存在しない場合は、まず作成します。

CREATE DATABASE IF NOT EXISTS testdb;
GRANT SELECT, INSERT, UPDATE ON testdb.* TO 'testuser'@'localhost';

次の出力が表示されるはずです。

Query OK, 0 rows affected (0.00 sec)

ここで、testuser から UPDATE 権限を取り消したいとします。REVOKE ステートメントを使用することができます。

REVOKE UPDATE ON testdb.* FROM 'testuser'@'localhost';

次の出力が表示されるはずです。

Query OK, 0 rows affected (0.00 sec)

次に、変更がすぐに反映されるように、権限をフラッシュしましょう。

FLUSH PRIVILEGES;

次の出力が表示されるはずです。

Query OK, 0 rows affected (0.00 sec)

testuser の権限を確認するには、SHOW GRANTS ステートメントを使用することができます。

SHOW GRANTS FOR 'testuser'@'localhost';

出力には、testuser に付与された権限が表示されます。SELECTINSERT 権限が表示され、UPDATE は表示されないはずです。

+---------------------------------------------------------------------------------------------------------------------------------------+
| Grants for testuser@localhost                                                                                                       |
+---------------------------------------------------------------------------------------------------------------------------------------+
| GRANT SELECT, INSERT ON `testdb`.* TO `testuser`@`localhost`                                                                        |
| GRANT USAGE ON *.* TO `testuser`@`localhost`                                                                                           |
+---------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

最後に、次のように入力して MySQL シェルを終了します。

exit

通常のターミナルプロンプトに戻ります。

匿名ユーザーアカウントを削除する

このステップでは、MySQL サーバーから匿名ユーザーアカウントを削除します。匿名ユーザーアカウントとは、ユーザー名が ''(空文字列)のアカウントで、データベースへの不正アクセスを許可する可能性があります。これらのアカウントを削除することは、良好なセキュリティ対策です。

まず、ルートユーザーとして MySQL シェルにアクセスしましょう。

LabEx VM のターミナルを開きます。デフォルトのディレクトリは ~/project です。

ルートユーザーとして MySQL シェルにアクセスするには、次のコマンドを実行します。

sudo mysql -u root

labex ユーザーのパスワードを求められる場合があります。labex はパスワードなしで sudo 権限を持っているため、Enter キーを押すだけです。

これで MySQL シェルに入りました。mysql> のようなプロンプトが表示されます。

匿名ユーザーアカウントを特定するには、mysql.user テーブルをクエリします。

SELECT User, Host FROM mysql.user WHERE User='';

このクエリは、ユーザー名が空のユーザーを表示します。Host 列は、ユーザーが接続できるホストを示します。'@'localhost'@'%' のようなエントリが表示される場合があります。

匿名ユーザーアカウントを削除するには、DROP USER ステートメントを使用します。たとえば、localhost から接続できる匿名ユーザーアカウントを削除するには、次のコマンドを実行します。

DROP USER ''@'localhost';

次の出力が表示されるはずです。

Query OK, 0 rows affected (0.00 sec)

他の匿名ユーザーアカウント(例:'@'%')がある場合は、それらも削除します。

DROP USER ''@'%';

次の出力が表示されるはずです。

Query OK, 0 rows affected (0.00 sec)

匿名ユーザーアカウントを削除した後、変更がすぐに反映されるように、権限をフラッシュしましょう。

FLUSH PRIVILEGES;

次の出力が表示されるはずです。

Query OK, 0 rows affected (0.00 sec)

匿名ユーザーアカウントが削除されたことを確認するには、SELECT クエリを再度実行します。

SELECT User, Host FROM mysql.user WHERE User='';

今回は、クエリの結果セットは空になるはずです。

最後に、次のように入力して MySQL シェルを終了します。

exit

通常のターミナルプロンプトに戻ります。

まとめ

この実験では、最初のステップとして、ルートユーザーのパスワードを変更することで MySQL のセキュリティを強化することに焦点を当てました。これには、sudo mysql -u root コマンドを使用してルートユーザーとして MySQL シェルにアクセスする作業が含まれていました。

このステップの核心は、ALTER USER ステートメントを実行してルートユーザーのパスワードを更新することで、MySQL 8.0 以降で使用される caching_sha2_password 認証プラグインとの互換性を確保することでした。その後、FLUSH PRIVILEGES コマンドを使用して変更を即座に適用し、最後に MySQL シェルを終了しました。