MySQLサーバーセキュリティ設定の堅牢化ベストプラクティス

重要なMySQLデプロイメントを保護するための、必須のセキュリティ堅牢化ベストプラクティスをまとめた包括的なガイドです。堅牢なユーザーおよびアクセス管理の実装方法、ファイアウォールとSSL/TLSによるネットワーク接続の保護、最適なセキュリティのための`my.cnf`の微調整、そしてOSレベルの保護の適用方法について学ぶことができます。一般的な脆弱性を軽減し、不正アクセスを防止し、データベースの整合性と機密性を確保するための実用的な設定ヒントと具体的な手順をご紹介します。MySQLセキュリティを担当するすべての人にとって必読のガイドです。

28 ビュー

MySQLサーバーセキュリティ構成を強化するためのベストプラクティス

MySQLは、小規模なブログから大規模なエンタープライズシステムまで、あらゆるものを動かす無数のアプリケーションの要石です。その人気は、堅牢性と柔軟性の証である一方で、悪意のある攻撃者にとって頻繁な標的ともなります。設定が不適切であったり、セキュリティ対策が不十分なMySQLサーバーは、機密データを露呈させ、インフラストラクチャ全体への不正アクセスの入り口を提供する、重大な脆弱性となる可能性があります。MySQLのデプロイを保護することは、一度限りの作業ではなく、警戒とセキュリティのベストプラクティスへの順守を要求する継続的な取り組みです。

この記事では、不可欠な構成のヒントとセキュリティ強化策に関する包括的なガイドを提供します。ユーザー管理やネットワーク保護から、構成ファイルの調整、オペレーティングシステムの考慮事項まで、さまざまなセキュリティの階層を掘り下げていきます。これらの推奨事項を実施することで、MySQLサーバーの攻撃対象領域を大幅に削減し、一般的な脆弱性や不正アクセス試行に対して、より回復力の高いデータベース環境を構築できます。

1. ユーザーおよびアクセス管理:最小権限の原則

効果的なユーザー管理は、MySQLセキュリティの基盤です。ユーザーに必要な権限のみを付与することが最も重要です。

特定のアプリケーションに特定のユーザーを作成する

アプリケーション接続に root ユーザーを使用することは避けてください。代わりに、きめ細かな権限を持つ専用のユーザーを作成します。

CREATE USER 'my_app_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT SELECT, INSERT, UPDATE, DELETE ON `your_database`.* TO 'my_app_user'@'localhost';
FLUSH PRIVILEGES;

強力なパスワードの強制

強力で一意のパスワードは、最初の防衛線です。利用可能な場合は、MySQLに組み込まれているパスワード検証プラグインを活用してください。

  • 複雑さ: 大文字、小文字、数字、記号を混ぜる。
  • 長さ: 少なくとも12~16文字を目指す。
  • 一意性: パスワードを再利用しない。
  • ローテーション: 定期的なパスワード変更のポリシーを実施する。

validate_password コンポーネント (MySQL 8.0+) またはプラグイン (MySQL 5.7+) を有効にすることができます。

INSTALL COMPONENT 'file://component_validate_password';
-- OR for older versions (または、古いバージョン向け)
INSTALL PLUGIN validate_password SONAME 'validate_password.so';

-- Configure strength policy (e.g., MEDIUM for 8+ chars, mix case, numbers, special) (強度ポリシーの設定。例:8文字以上、大文字小文字、数字、特殊文字を含むMEDIUM)
SET GLOBAL validate_password.policy = MEDIUM;
SET GLOBAL validate_password.length = 12;

デフォルトユーザーと未使用ユーザーの削除

MySQLにはデフォルトユーザー (root@localhost など) が同梱されています。root@localhost は必要ですが、強力なパスワードを設定してください。特に、mysql.sessionmysql.sys、および匿名ユーザーなど、明示的に必要で適切に構成されていないデフォルトユーザーは、削除または保護することが重要です。

-- To identify anonymous users: (匿名ユーザーを特定する場合)
SELECT user, host FROM mysql.user WHERE user = '';
-- To drop an anonymous user (if found): (匿名ユーザーを削除する場合(見つかった場合))
DROP USER ''@'localhost';

-- To remove test databases (if they exist): (テストデータベースを削除する場合(存在する場合))
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%';
FLUSH PRIVILEGES;

ホストアクセスの制限

特定のIPアドレスまたはホスト名からのみ接続できるようにユーザーアカウントを制限します。絶対に必要な場合、または他の強力なセキュリティ制御と組み合わされている場合を除き、ホストにワイルドカードとして % を使用することは避けてください。

-- User can only connect from localhost (ユーザーはlocalhostからのみ接続できます)
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'AnotherStrongPass!';

-- User can only connect from a specific IP address (ユーザーは特定のIPアドレスからのみ接続できます)
CREATE USER 'backup_user'@'192.168.1.100' IDENTIFIED BY 'BackupPass!';

GRANT OPTION の使用には注意する

WITH GRANT OPTION 句を使用すると、ユーザーは自身の権限を他のユーザーに付与することができます。これは、信頼されていないユーザーに付与された場合、重大なセキュリティリスクとなる可能性があります。この機能を真に必要とする管理者アカウントにのみ、控えめに使用してください。

-- A user with ability to grant privileges (use with extreme caution) (権限付与能力を持つユーザー(極度の注意を払って使用してください))
GRANT ALL PRIVILEGES ON *.* TO 'superadmin'@'localhost' IDENTIFIED BY 'SuperAdminPass!' WITH GRANT OPTION;

2. ネットワークセキュリティ:データベースの隔離

ネットワークレベルの制御は、MySQLサーバーへの不正な外部アクセスを防ぐために不可欠です。

ファイアウォールの構成

MySQLのデフォルトポート (3306) への接続は、信頼できるIPアドレスまたはネットワークからのみ許可します。このポートへの他のすべてのインバウンド接続をブロックします。

Example (UFW on Linux):

sudo ufw enable
sudo ufw allow from 192.168.1.0/24 to any port 3306
sudo ufw deny 3306
sudo ufw status

Example (CentOS/RHEL with firewalld):

sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="3306" protocol="tcp" accept'
sudo firewall-cmd --permanent --remove-port=3306/tcp --zone=public # Ensure it's not open globally (グローバルに開かれていないことを確認)
sudo firewall-cmd --reload

SSL/TLSを使用した安全な接続

盗聴や中間者 (MitM) 攻撃を防ぐために、クライアントとMySQLサーバー間のすべてのトラフィックをSSL/TLSを使用して暗号化します。これは、信頼できないネットワークを介した接続にとって特に重要です。

SSL/TLSを有効にするには、通常、SSL証明書とキーを生成し、my.cnf を構成する必要があります。

# my.cnf
[mysqld]
ssl_ca=/etc/mysql/certs/ca.pem
ssl_cert=/etc/mysql/certs/server-cert.pem
ssl_key=/etc/mysql/certs/server-key.pem

その後、クライアントはSSL/TLSを使用して接続するように構成する必要があります。多くの場合、ユーザーの GRANT ステートメントで REQUIRE SSL を使用します。

CREATE USER 'ssl_user'@'%' IDENTIFIED BY 'SSLUserPass!';
GRANT SELECT ON `your_database`.* TO 'ssl_user'@'%' REQUIRE SSL;
FLUSH PRIVILEGES;

特定のIPアドレスへのバインド

デフォルトでは、MySQLは利用可能なすべてのネットワークインターフェース (0.0.0.0) でリッスンする場合があります。接続を受け入れる必要のあるインターフェース (例: ローカルアプリケーションの場合は localhost、内部接続の場合はプライベートネットワークIP) のみでリッスンするように制限します。

# my.cnf
[mysqld]
bind-address = 127.0.0.1  # For local connections only (ローカル接続のみの場合)
# OR (または)
bind-address = 192.168.1.10  # For a specific internal IP (特定の内部IPの場合)

Tip (ヒント): アプリケーションとMySQLサーバーが同じマシン上にある場合、bind-address = 127.0.0.1 (localhost) は、外部からの接続を完全に防ぐため、最も安全なオプションです。

3. 構成ファイル (my.cnf / my.ini) の強化

MySQL構成ファイル (Linuxでは my.cnf、Windowsでは my.ini) には、セキュリティを強化するための多数のパラメータが用意されています。

未使用の機能の無効化

デプロイに不要な機能を無効にすることで、攻撃対象領域を最小限に抑えます。

  • local_infile = 0: クライアントがサーバーホスト上の任意のファイルからデータをロードするようにサーバーに要求することを防ぎます。これは、データ抜き出しの一般的な経路です。
    ini [mysqld] local_infile = 0
  • skip-networking: データベースが同じサーバー上のアプリケーションからのみアクセスされる場合、ネットワークを完全に無効にします。これにより、すべての接続がUnixソケットまたは名前付きパイプを使用するように強制されます。
    ini [mysqld] skip-networking
  • symbolic-links = 0: データベーステーブルスペースへのシンボリックリンクの使用を防ぎます。これは、MySQLデータディレクトリ外のファイルにアクセスするために悪用される可能性があります。
    ini [mysqld] symbolic-links = 0
  • secure_file_priv: LOAD DATA INFILESELECT ... INTO OUTFILE などの機能によってファイルを読み書きできるディレクトリを制限します。
    ```ini
    [mysqld]
    secure_file_priv = "/var/lib/mysql-files" # Set to a specific, restricted directory (特定の制限されたディレクトリに設定)
    # OR (または)
    # secure_file_priv =