mysql|セキュリティ|セキュリティ
MySQL システム管理者は、MySQL データベース システムのデータ セキュリティと整合性を維持する責任があります。この記事では主に安全な MySQL システムを構築する方法を紹介し、システムの内部ネットワークと外部ネットワークの両方の観点からガイドを提供します。
この記事では、主に次のセキュリティ関連の問題について検討します:
· セキュリティが重要なのはなぜですか?どのような攻撃から防御する必要がありますか?
・サーバーが直面するリスク (内部セキュリティ)、それにどう対処するか?
· クライアントがサーバーに接続するリスク (外部セキュリティ)、それにどう対処するか?
MySQL 管理者は、正しく許可されたユーザーのみがこれらのデータ レコードにアクセスできるように、データベース コンテンツのセキュリティを確保する責任があります。これには、データベース システムの内部セキュリティと外部セキュリティが関係します。
内部セキュリティは、ファイル システム レベルの問題、つまり、サーバー ホスト上のアカウント (正規のアカウントまたは盗難されたアカウント) を持つユーザーによる MySQL データ ディレクトリ (DATADIR) の攻撃の防止に関係します。データ ディレクトリの内容が過剰に許可され、誰もがこれらのデータベース テーブルに対応するファイルを簡単にオーバーライドできるようになってしまったら、ネットワーク経由のクライアント アクセスを制御する認可テーブルが正しく設定されていることを確認しても意味がありません。
外部セキュリティは、ネットワークを介して外部からサーバーに接続するクライアントの問題、つまり、ネットワークを介したサーバーへの接続からの攻撃から MySQL サーバーを保護することに関係します。有効なユーザー名とパスワードが提供されない限り、サーバー管理のデータベース コンテンツへのアクセスが許可されないように、MySQL 許可テーブルを設定する必要があります。
以下では、MySQL の 2 段階のセキュリティを実現するためのファイル システムと認可テーブル mysql の設定方法を詳しく紹介します。
1. 内部セキュリティ - データ ディレクトリ アクセスのセキュリティを確保します
MySQL サーバーは、MySQL データベース内の認証テーブルを通じて柔軟な権限システムを提供します。これらのテーブルの内容を設定して、データベースへのクライアント アクセスを許可または拒否できます。これにより、ホスト上の他のユーザーがデータベースの内容に直接アクセスできる場合でも、不正なネットワーク アクセスによる攻撃を防ぐことができます。データ ディレクトリでは、ネットワーク経由のデータベース アクセスに適切なセキュリティを確立しても、MySQL サーバーが実行されているホスト マシンにログインしているユーザーが自分だけであることがわかっていて、他のユーザーがログインしている可能性を考慮する必要がない限り役に立ちません。このマシン上でデータ ディレクトリへのアクセスを取得します。
保護すべきものは次のとおりです:
·データベース ファイル。サーバー管理データベースのプライバシーを維持したいのは明らかです。データベース所有者は通常、たとえ望まなくてもデータベース コンテンツのセキュリティを考慮しており、データベース コンテンツを不十分なデータ ディレクトリ セキュリティで公開するのではなく、公開することを検討する必要があります。
·ログファイル。一般ログと変更ログにはクエリ テキストが含まれるため、安全に保管する必要があります。ログ ファイルにアクセスできる人は誰でも、データベース上で実行される操作を監視できます。
ログ ファイルのセキュリティについてより重要な考慮事項は、GRANT や SET PASSWORD などのクエリも記録されることです。一般ログと更新ログには、パスワードを含む機密クエリのテキストが含まれています (MySQL はパスワード暗号化を使用しますが、これは設定が完了した後に行われます)。パスワードを設定するプロセスは GRANT や SET PASSWORD などのクエリを使用して設計されており、これらのクエリはログ ファイルにプレーン テキストで記録されます。攻撃者がファイルへの読み取りアクセスを取得した場合、ログ ファイルに対して grep を実行するだけで GRANT や PASSWORD などの単語を検索し、機密情報を発見することができます。
明らかに、サーバー ホスト上の他のユーザーにデータベース ディレクトリ ファイルへの書き込み権限を与えたくないのは、状態ファイルやデータベース テーブル ファイルが上書きされる可能性があるためですが、読み取り権限も危険です。データベース テーブル ファイルが読み取れる場合、そのファイルを盗んで MySQL 自体にアクセスしてテーブルの内容をプレーン テキストで表示するのは面倒です。なぜでしょうか。なぜなら、次のことを行う必要があるからです:
· 独自の「特別な」MySQL サーバーをサーバーホストにインストールしますが、公式サーバーバージョンとは異なるポート、ソケット、データディレクトリを使用します。
· mysql_install_db を実行してデータ ディレクトリを初期化すると、MySQL root ユーザーとしてサーバーにアクセスできるようになり、サーバー アクセス メカニズムを完全に制御できるようになります。
· 盗むテーブルに対応するファイルを、サーバーのデータベース ディレクトリの下のテスト ディレクトリにコピーします。
·サーバーを起動します。データベース テーブルには自由にアクセスでき、SHOW TABLES FROM テストは盗まれたテーブルのコピーがあることを示し、SELECT * はいずれかのテーブルの内容全体を示します。
· 本当に悪意がある場合は、サーバー上の匿名ユーザーにアクセス許可を公開し、誰でもどこからでもサーバーに接続してテスト データベースにアクセスできるようにします。これで、盗まれたデータベーステーブルが公開されました。
逆の視点で考えてみて、あなたは他人にこうしてもらいたいですか?もちろん違います!データベース ディレクトリで ls -l コマンドを実行すると、データベースに安全でないファイルやディレクトリが含まれているかどうかを確認できます。 「グループ」および「その他のユーザー」権限が設定されているファイルとディレクトリを探します。以下は、安全でないデータ ディレクトリの部分的なリストです:
% ls -l
合計 10148
drwxrwxr-x 11 mysqladm ホイール 1024 5 月 8 日 12:20 .
drwxr-xr-x 22 ルート ホイール 512 5 月 8 日 13:31 ..
drwx------ 2 mysqladm mysqlgrp 512 4 月 16 日 15:57 menagerie
drwxrwxr-x 2 mysqladm ホイール 512 1 月 25 日 20:40 mysql
drwxrwxr-x 7 mysqladm ホイール 512 1998 年 8 月 31 日 sql-bench
drwxrwxr-x 2 mysqladm ホイール 1536 5 月 6 日 06:11 テスト
drwx----- - 2 mysqladm mysqlgrp 1024 5 月 8 日 18:43 tmp
....
ご覧のとおり、一部のデータベースには正しい権限がありますが、他のデータベースには正しくありません。この例の状況は、一定期間後の結果です。新しいバージョンよりも権限設定の制限が緩い古いサーバーでは、制限の少ない権限が設定されます (より制限の厳しいディレクトリ menageria と tmp はどちらも最近作成されたものであることに注意してください)。 MySQL の現在のバージョンでは、サーバーを実行しているユーザーのみがこれらのファイルを読み取ることができます。
サーバーユーザーのみがアクセスできるようにこれらの権限を修正しましょう。主な保護ツールは、ファイルとディレクトリの所有権とモードを設定するために UNIX ファイル システム自体によって提供されるツールから得られます。私たちがしなければならないことは次のとおりです:
·ディレクトリを入力します
% cd DATADIR
·データディレクトリ内のすべてのファイルの所有者を、サーバーの実行に使用されるアカウントが所有するように設定します(この手順は次のように実行する必要があります)根) 。この記事では、mysqladm と mysqlgrp がアカウントのユーザー名とグループ名として使用されます。次のコマンドのいずれかを使用して所有者を変更できます:
# chown mysqladm.mysqlgrp .
# find . -follow -type d -print により、他のユーザーがデータベースの内容にアクセスできなくなります。ディレクトリ。次のコマンドのいずれかを使用して、root または mysqladm として実行できます。
% chmod -R go-rwx .
% find . -follow -type d -print | xargs chmod go-rwx
・データディレクトリの内容の所有者とモードはmysqladmに設定されます。ここで、データベース ディレクトリにアクセスできる唯一のユーザー (root 以外) が mysqladm ユーザーとして常にサーバーを実行していることを確認する必要があります。
これらの設定を完了すると、次のデータ ディレクトリのアクセス許可が得られるはずです:
% ls -l
total 10148
drwxrwx--- 11 mysqladm mysqlgrp 1024 May 8 12:20 .
drwxr-xr-x 22 root Wheel 512 5月8日 13:31 ..
drwx------ 2 mysqladm mysqlgrp 512 4月16日 15:57 menagerie
drwx------ 2 mysqladm mysqlgrp 512 1月25日 20:40 mysql
drwx------ -- 7 mysqladm mysqlgrp 512 1998 年 8 月 31 日 sql-bench
drwx------ 2 mysqladm mysqlgrp 1536 5 月 6 日 06:11 test
drwx------ 2 mysqladm mysqlgrp 1024 5 月 8 日 18:43 tmp
。 ...
2. 外部セキュリティ - ネットワーク アクセスのセキュリティの確保
MySQL のセキュリティ システムは非常に柔軟で、さまざまな方法でユーザーの権限を設定できます。通常、これは標準 SQL GRANT および REVOKE ステートメントを使用して実行できます。これらのステートメントは、クライアント アクセスを制御する付与テーブルを変更します。ただし、サポートされていない古いバージョンの MySQL (3.22.11 より前) が使用できない可能性があります。これらのステートメントは機能しません)、またはユーザー権限が希望どおりに機能しないことがわかります。この状況では、MySQL 認可テーブルの構造と、サーバーがそれらを使用してアクセス許可を決定する方法を理解しておくと、認可テーブルを直接変更することによってユーザー許可を追加、削除、または変更できるようになります。権限の問題を診断するときにこれらのテーブルを検査できます。
ユーザー アカウントの管理方法については、「MySQL ユーザー管理」を参照してください。 GRANT および REVOKE ステートメントの詳細については、「MySQL リファレンス マニュアル」を参照してください。
2.1 MySQL 認可テーブルの構造と内容
ネットワーク経由でサーバーに接続するクライアントによる MySQL データベースへのアクセスは、認可テーブルの内容によって制御されます。これらのテーブルは mysql データベース内にあり、MySQL の最初のインストール (mysql_install_db スクリプトの実行) 中に初期化されます。 user、db、host、tables_priv、columns_priv の 5 つの認可テーブルがあります。
テーブル 1 ユーザー、データベース、およびホストの認可テーブル構造
アクセス範囲列
user db host
Host Host Host
User Db Db
Password User
データベース/テーブル権限列
Alter_priv Alter_priv Alter_priv
Create_priv Create_priv Create_priv
Delete_priv 削除 ete_priv Delete_priv
Drop_priv Drop_priv Drop_priv
Index_priv Index_priv Index_priv
Insert_priv Insert_priv Insert_priv
References_priv References_priv References_priv
Select_priv Select_priv Select_priv
Update_priv Update_priv Update_priv
File_priv Grant_priv Grant_priv
Grant_priv
Process_priv
Reload_priv
Shutdown_priv
表 2 tables_priv と columns_priv の所有権テーブル構造
Access範囲列
tables_priv columns_priv
Host Host
Db Db
User User
Table_name Table_name
Column_name
Permission 列
Table_priv Column_priv
認可テーブルの内容は次の用途に使用できます:
·user table
ユーザー テーブルには、サーバーに接続できるユーザーとそのパスワードがリストされ、ユーザーが持つグローバル (スーパーユーザー) 権限が指定されます。ユーザーテーブルで有効になっている権限はすべてグローバル権限であり、すべてのデータベースに適用されます。たとえば、DELETE 権限が有効になっている場合、ここにリストされているユーザーは任意のテーブルからレコードを削除できるため、これを行う前に慎重に検討してください。
·db テーブル
db テーブルにはデータベースがリストされており、ユーザーはデータベースにアクセスする権限を持っています。ここで指定した権限は、データベース内のすべてのテーブルに適用されます。
·ホスト テーブル
ホスト テーブルは、データベースに対する特定のホストのアクセス権をより適切なレベルで制御するために、db テーブルと組み合わせて使用されます。これは、db を単独で使用するよりも優れている場合があります。このテーブルは GRANT および REVOKE ステートメントの影響を受けないため、まったく使用していないことがわかるかもしれません。
·tables_priv テーブル
tables_priv テーブルは、ここで指定された権限がテーブルのすべての列に適用されることを指定します。
·columns_priv テーブル
columns_priv テーブルは列レベルの権限を指定します。ここで指定した権限は、テーブルの特定の列に適用されます。
「GRANT を使用しないユーザーの設定」セクションでは、これらのテーブルを変更するために GRANT ステートメントがどのように機能するか、また認可テーブルを直接変更することで同じ効果を達成する方法について説明します。
tables_priv テーブルと columns_priv テーブルは、MySQL バージョン 3.22.11 で (GRANT ステートメントと同時に) 導入されました。以前のバージョンの MySQL を使用している場合、mysql データベースには user、db、および host テーブルのみが含まれます。古いバージョンから 3.22.11 以降にアップグレードし、tables_priv テーブルと columns_priv テーブルがない場合は、mysql_fix_privileges_tables スクリプトを実行して作成します。
MySQL には rows_priv テーブルがありません。これは、レコードレベルの権限を提供していないため、テーブル内の特定の列値を含む行にユーザーを制限することができません。この機能が本当に必要な場合は、アプリケーション プログラミングを使用して提供する必要があります。推奨されるレコードレベルのロックを実行したい場合は、GET_LOCK() 関数を使用して実行できます。
権限テーブルには、権限がいつ適用されるかを決定するスコープ列と、どの権限が付与されるかを決定する権限列の 2 種類の列が含まれています。
2.1.1 認可テーブル範囲列
認可テーブル範囲列は、テーブル内の権限がいつ適用されるかを指定します。認可テーブルの各エントリには、特定のホストからの特定のユーザーの接続にいつ権限を適用するかを指定するためのユーザー列とホスト列が含まれています。他のテーブルには追加の範囲列が含まれています。たとえば、権限が適用されるデータベースを示す Db 列を含む db テーブルなどです。同様に、tables_priv テーブルと columns_priv テーブルには、データベース内の特定のテーブルまたはテーブルの特定の列に範囲を狭める範囲フィールドが含まれています。
2.1.2 認可テーブルの権限列
認可テーブルには、スコープ列で指定されたユーザーがどのような権限を持っているかを示す権限列も含まれています。 MySQL でサポートされる権限を次の表に示します。この表では、GRANT ステートメントの権限名が使用されています。 user、db、および host テーブル内のほとんどの権限列名の場合、GRANT ステートメント内の名前の間には明らかな関連性があります。たとえば、Select_priv は SELECT 権限に対応します。
2.1.3 データベースとテーブルの権限
次の権限は、データベースとテーブルの操作に適用されます。
·ALTER
を使用すると、ALTER TABLE ステートメントを使用できます。これは、実際には、データベースに対して実行する操作に応じて、他の権限が必要です。
·CREATE
を使用すると、データベースとテーブルを作成できますが、インデックスは作成できません。
·DELETE
を使用すると、テーブルから既存のレコードを削除できます。
·DROP
を使用すると、データベースとテーブルを削除 (破棄) できますが、インデックスを削除することはできません。
·INDEX
を使用すると、インデックスを作成および削除できます。
·参考資料
現在は使用されていません。
·SELECT
を使用すると、SELECT ステートメントを使用してテーブルからデータを取得できます。 SELECT NOW() や SELECT 4/2 など、テーブルを含まない SELECT ステートメントの場合は必要ありません。
·UPDATE
を使用すると、テーブル内の既存のレコードを変更できます。
2.1.4 管理権限
次の権限は、サーバーの操作またはユーザー認証機能を制御する管理操作に使用されます。
·FILE
を使用すると、サーバーホスト上のファイルの読み取りまたは書き込みをサーバーに指示できます。この権限は安易に付与すべきではありません。危険です。「権限テーブルのリスクの回避」を参照してください。サーバーは、この権限を制限内に保つためにある程度の注意を払います。誰でも読み取り可能なファイルのみを読み取ることができます。書き込み中のファイルは存在してはなりません。これにより、/etc/passwd や他の人のデータベースに属するデータ ディレクトリなどの重要なファイルをサーバーに強制的に書き換えることができなくなります。
ファイル権限を付与する場合は、UNIX root ユーザーとしてサーバーを実行しないようにしてください。root はファイル システムのどこにでも新しいファイルを作成できるからです。サーバーを特権のないユーザーとして実行する場合、サーバーはユーザーがアクセスできるディレクトリにのみファイルを作成できます。
·GRANT
を使用すると、GRANT を含む自分の権限を他の人に付与できます。
·PROCESS
を使用すると、SHOW PROCESS ステートメントまたは mysqladmin process コマンドを使用して、サーバー内で実行されているスレッド (プロセス) に関する情報を表示できます。この権限により、KILL ステートメントまたは mysqladmin kill コマンドを使用してスレッドを強制終了することもできます。
いつでも自分のスレッドを表示したり、強制終了したりできます。 PROCESS 権限により、任意のスレッドでこれらの操作を実行できるようになります。
·リロード
幅広いサーバー管理操作を実行できます。 FLUSH ステートメントを発行できます。また、mysqladmin の reload、refresh、flush-hosts、flush-logs、flush-privileges、および flash-tables コマンドを参照することもできます。
·SHUTDOWN
を使用すると、mysqladmin shutdown でサーバーをシャットダウンできます。
user、db、host テーブルでは、各権限は個別の列で指定されます。これらの列はすべて ENUM ("N", "Y") 型として宣言されているため、各重みのデフォルト値は "N" です。 tables_priv および columns_priv の権限は SET によって表され、単一の列と任意の組み合わせで権限を指定できます。これら 2 つのテーブルは他の 3 つよりも新しいため、より効率的な表現が使用されます。 (将来的には、user、db、および host テーブルも SET タイプで表される可能性があります。)
tables_priv テーブルの Table_priv 列は、次のように定義されます:
SET('Select','Insert' ,'Update',' Delete','Create','Drop','Grant','References','Index','Alter')
coloums_priv テーブルの Column_priv 列は次のように定義されます:
SET(' Select','Insert' ,'Update','References')
列の権限はテーブルの権限よりも低くなります。これは、より少ない列レベルの権限が合理的であるためです。たとえば、テーブルを作成することはできますが、独立した列を作成することはできません。
ユーザー テーブルには、他の認可テーブルには存在しない特定の権限列 (File_priv、Process_priv、Reload_priv、Shutdown_priv) が含まれています。これらのアクセス許可は、特定のデータベースやテーブルに関連しない、サーバーに実行を要求する操作に適用されます。現在のデータベースの内容に基づいてユーザーがデータベースを閉じることを許可するのは意味がありません。
2.2 サーバーがクライアント アクセスを制御する方法
MySQL を使用する場合、クライアント アクセス制御には 2 つの段階があります。最初のフェーズは、サーバーに接続しようとしたときに発生します。サーバーはユーザー テーブルを調べて、ユーザーの名前、接続元のホスト、および指定したパスワードに一致するエントリが見つかるかどうかを確認します。一致しない場合は接続できません。一致するものがあれば、接続を確立し、第 2 フェーズに進みます。このフェーズでは、発行するクエリごとに、サーバーは認可テーブルをチェックして、クエリを実行するための十分な権限があるかどうかを確認します。第 2 フェーズは、サーバーとの会話が終了するまで続きます。
このセクションでは、MySQL サーバーが認証テーブルのエントリを受信した接続リクエストまたはクエリと照合するために使用する原則について詳しく説明します。これには、認証テーブルの範囲列の正当な値の種類、権限情報を組み合わせる方法が含まれます。権限テーブルとエントリがチェックされる順序。
2.2.1 範囲列の内容
一部の範囲列にはリテラル値が必要ですが、ほとんどの列ではワイルドカードまたはその他の特別な値が許可されます。
·ホスト
ホスト列の値には、ホスト名または IP アドレスを指定できます。値 localhost はローカルホストを意味しますが、ホスト名を使用した場合ではなく、ローカルホストのホスト名を使用した場合にのみ一致します。ローカル ホスト名が pig.snake.net で、ユーザー テーブルに 2 つのレコードがあり、1 つはホスト値または localhost で、もう 1 つは pig.snake.net である場合、localhost のレコードは次のように扱われます。これは localhost に接続した場合に一致し、他のものは pig.snake.net に接続した場合にのみ一致します。クライアントが 2 つの方法で接続できるようにするには、ユーザー テーブルに 2 つのレコードが必要です。
ワイルドカードを使用してホスト値を指定することもできます。 SQL パターン文字「%」および「_」を使用でき、クエリで LIKE 演算子を使用する場合と同じ意味になります (正規表現演算子は使用できません)。 SQL パターン文字は、ホスト名と IP アドレスの両方に使用できます。たとえば、%wisc.edu は wisc.edu ドメイン内の任意のホストに一致し、%.edu は College of Education 内の任意のホストに一致します。同様に、192.168.% は 192.168 クラス B サブネット上の任意のホストに一致し、192.168.3.% は 192.168.3 クラス C サブネット上の任意のホストに一致します。
% 値はすべてのホストに一致し、ユーザーがどこからでも接続できるようにするために使用できます。空白のホスト値は % に相当します。 (例外: DB テーブルで、空白の Host 値は「ホスト テーブルをさらに確認する」ことを意味します。このプロセスは「クエリ アクセスの検証」で紹介されています。)
MySQL 3.23 以降では、次の値に基づいて IP アドレスを指定することもできます。 192.168.128.0/17 などのネットワーク アドレスのネットマスクは 17 ビットのネットワーク アドレスを指定し、IP アドレスが 192.168.128 の最初の 17 桁であるホストと一致します。
·ユーザー
ユーザー名はテキストまたは空白にする必要があります。空白の値は任意のユーザーと一致します。ユーザー値としての % は空白を意味するのではなく、リテラルの % 名と一致しますが、これはおそらくあなたが望むものではありません。
受信接続がユーザー テーブルを通じて認証され、一致するレコードに空のユーザー値が含まれている場合、クライアントは匿名ユーザーとみなされます。
·パスワード
パスワード値は空でも空以外でも構いません。ワイルドカードは使用できません。空のパスワードは、どのパスワードでも一致するという意味ではなく、ユーザーがパスワードを指定する必要がないことを意味します。
パスワードはリテラルテキストではなく、暗号化された値として保存されます。 「パスワード」列に文字通りのパスワードを保存すると、ユーザーは接続できなくなります。 GRANT ステートメントと mysqladminpassword コマンドはパスワードを自動的に暗号化しますが、INSERT、REPLACE、UPDATE、SET PASSWORD などのコマンドを使用する場合は、単に "new_password" ではなく PASSWORD("new_password") を使用してパスワードを指定してください。 。
·DB
columns_priv テーブルと tables_priv テーブルでは、Db 値は実際のデータベース名 (文字通り) である必要があり、パターンと空白は許可されません。 db および host では、Db 値を文字通り指定することも、SQL パターン文字「%」または「_」を使用してワイルドカードを指定することもできます。 「%」または空白は任意のデータベースに一致します。
·Table_name、Column_name
これらの列の値は、リテラルのテーブル名または列名である必要があり、パターンと空白は許可されません。
一部の範囲列はサーバーによって大文字と小文字が区別されると見なされますが、残りは区別されません。これらの原則を以下の表にまとめます。特に、クエリ内のテーブル名の大文字と小文字の区別は、サーバーが実行されているホストのファイル システムによって異なりますが、Table_name の値は常に大文字と小文字が区別されるものとして扱われることに注意してください (UNIX では大文字と小文字が区別されますが、Windows では大文字と小文字が区別されません)。 )。
表 3 認可テーブル範囲の列の大文字と小文字の区別
Column
Host
User
Password
Db
Table_name
Column_name
大文字と小文字の区別
No
Yes
Yes
Yes
Yes
No
2.2.2 クエリアクセス検証
クエリを発行するたびに、サーバーはクエリを実行するための十分な権限があるかどうかをチェックし、適切なアクセス権があると判断するか、すべてのテーブルを検索しても何も見つからないまで、user、db、tables_priv、columns_priv の順にチェックします。より具体的には:
· サーバーは、ユーザー テーブルで接続を開始したレコードと一致するレコードをチェックし、ユーザーがどのようなグローバル権限を持っているかを確認します。クエリに必要な情報があり、それらがクエリに十分であれば、サーバーはクエリを実行します。
· グローバル権限が十分でない場合、サーバーはデータベーステーブルを検索し、レコード内の権限をグローバル権限に追加します。結果がクエリに対して十分である場合、サーバーはクエリを実行します。
· グローバル レベルとデータベース レベルの権限を組み合わせた権限が不十分な場合、サーバーは引き続き最初に tables_priv テーブルを検索し、次に columns_priv テーブルを検索します。
· すべてのテーブルをチェックしても権限がない場合、サーバーはクエリの実行を拒否します。
ブール用語で言えば、認可テーブルの権限はサーバーによって次のように使用されます:
user OR tables_priv OR columns_priv
実際には 5 つの認可テーブルがあるのに、前の説明ではなぜ 4 つの認可テーブルしか参照していないのか疑問に思われるかもしれません。実際、サーバーは次のようにアクセス許可をチェックします:
user OR (db AND host) OR tables_priv OR columns_priv
最初の簡単な式は、ホスト テーブルが GRANT および REVOKE ステートメントの影響を受けないためです。ユーザー権限の管理に常に GRANT と REVOKE を使用する場合は、ホスト テーブルについて考える必要はありません。しかし、それがどのように機能するかを知っておく必要があります:
· サーバーがデータベース レベルの権限をチェックするとき、クライアントの db テーブルを検索します。 [ホスト] 列が空の場合は、「ホスト テーブルをチェックしてデータベースにアクセスできるホストを確認する」ことを意味します。
· サーバーは、ホスト テーブル内で DB テーブルのレコードと同じ DB 列の値を探します。クライアントのホストと一致するホスト レコードがない場合、データベース レベルのアクセス許可は付与されません。これらのレコードのいずれかに、接続されたクライアントのホストと一致するホスト列の値がある場合、db テーブル レコードとホスト テーブル レコードが結合されて、クライアントのデータベース レベルのアクセス許可が生成されます。
ただし、アクセス許可は論理 AND で結合されます。これは、特定のアクセス許可が両方のテーブルに存在しない限り、クライアントはそのアクセス許可を持たないことを意味します。このようにして、db テーブルで基本的な権限セットを付与し、ホスト テーブルを使用して特定のホストに対してそれらの権限を選択的に無効にすることができます。たとえば、ドメイン内のすべてのホストからのデータベース アクセスを許可し、安全性の低いゾーンにあるホストのデータベース アクセス許可をオフにすることができます。
上記の説明では、特にサーバーが発行するすべてのクエリに対して権限チェックを実行すると考えると、アクセス チェックがかなり複雑なプロセスのように聞こえるかもしれませんが、サーバーは実際には承認テーブルをチェックしないため、このプロセスは非常に高速です。代わりに、起動時にテーブルの内容をメモリに読み取り、クエリがメモリ内のコピーを使用していることを確認します。これにより、アクセスチェック操作のパフォーマンスが大幅に向上します。しかし、非常に明らかな副作用があります。権限テーブルの内容を直接変更すると、サーバーは権限の変更を認識できません。
たとえば、INSERT ステートメントを使用してユーザー テーブルに新しいレコードを追加して新しいユーザーを追加すると、レコード内で指定されたユーザーはサーバーに接続できなくなります。これは新しい管理者 (場合によっては経験豊富なベテラン) にとって混乱を招くものでしたが、当時の解決策は単純でした。許可テーブルの内容を変更した後にサーバーに再ロードするように指示することでした。FLUSH PRIVILEGES を送信するか、mysqladmin flash-privileges (または、フラッシュ権限をサポートしていない古いバージョンを使用している場合は、mysqladmin reload を使用してください。)
2.2.3 範囲列の一致順序
MySQL サーバーは、認可テーブル内のレコードを特定の方法でソートし、レコードを順番に参照して受信接続を一致させます。最初に見つかった一致によって、どのレコードが使用されるかが決まります。 MySQL、特にユーザーテーブルで使用されるソート順序を理解することが重要です。
サーバーはユーザー テーブルの内容を読み取るときに、ホスト列とユーザー列の値に基づいてレコードを並べ替えます。ホスト値が決定要素となります (同じホスト値はまとめて並べ替えられ、次に、それに基づいて並べ替えられます)ユーザー値に基づいて)。ただし、ソートはアロディックな順序付け (単語による順序付け) ではなく、部分的にのみ行われます。覚えておくべきことは、文字通りの単語がパターンよりも優先されるということです。これは、client.your.net からサーバーに接続しており、Host に client.your.net と %.your.net という 2 つの値がある場合、最初の値が最初に選択されることを意味します。同様に、%.your.net は %.net よりも優先され、次に % が優先されます。 IP アドレスの照合についても同様です。
一言で言えば、優先順位がより具体的になるということです。例については、この記事の付録を参照してください。
2.3 認可テーブルのリスクを回避する
このセッションでは、認可時のいくつかの予防策と、不明な値の選択によって引き起こされるリスクについて紹介します。一般に、スーパーユーザー権限の付与は非常に「ケチ」にする必要があります。つまり、ユーザー テーブルのエントリで権限を有効にせず、他の権限テーブルを使用して、データベース、テーブル、または列に対するユーザー権限を制限する必要があります。ユーザー テーブルの権限により、サーバーの操作に影響を与える任意のデータベース内の任意のテーブルへのアクセスが許可されます。
mysql データベースにアクセス許可を与えないでください。認可テーブルを含むデータベースに対する権限を持つユーザーは、テーブルを変更して他のデータベースに対する権限を取得できます。ユーザーに mysql データベース テーブルの変更を許可する権限を付与すると、ユーザーにグローバル GRANT 権限も効果的に付与されます。ユーザーがテーブルを直接変更できる場合、これは想像できるあらゆる GRANT ステートメントを発行できることと同じです。
FILE 権限は特に危険です。簡単に許可しないでください。 FILE 権限を持つ人ができることは次のとおりです:
CREATE TABLE etc_passwd (pwd_entry TEXT);
LOAD DATA INFILE "/etc/passwd" into TABLE etc_passwd;
SELECT * FROM etc_passwd;
これらのステートメントを発行した後、ユーザーはすでにパスワード ファイルの内容が含まれています。実際、サーバー上の一般に読み取り可能なファイルの内容には、FILE 権限を持つユーザーがネットワーク経由でアクセスできます。
FILE 権限は、十分に制限的なファイル権限が設定されていないシステム上のデータベースを侵害するために悪用される可能性もあります。このため、サーバーのみが読み取りできるようにデータ ディレクトリを設定する必要があります。データベース テーブルに対応するファイルが、ユーザーのサーバー アカウントを持つユーザーだけでなく、誰でも読み取り可能な場合は、FILE 権限を持つユーザーもネットワーク経由で接続してファイルを読み取ることができます。プロセスは以下に示されています:
· LONGBLOB 列を持つテーブルを作成します:
USER test;
CREATE TABLE tmp (b LONGBLOB);
· このテーブルを使用して、盗むデータベースに対応する各データベースを読み取りますテーブル ファイルを作成し、テーブルの内容を独自のデータベース内のファイルに書き込みます:
LOAD DATA INFILE "./other_db/x.frm" INTO TABLE tmp
FIELDS ESCAPED BY "" LINES TERMINATED BY "";
SELECT * FROM tmp INTO OUTFILE "y.frm"
FIELDS ESCAPED BY "" LINES TERMINATED BY ";
DELETE FROM tmp;
LOAD DATA INFILE "./other_db/x.ISD" INTO TABLE tmp
FIELDS ESCED BY "" LINES TERMINATED BY "";
SELECT * FROM tmp INTO OUTFILE "y.ISD"
FIELDS ESCED BY "" LINES TERMINATED BY "";
DELETE FROM tmp;
LOAD DATA INFILE "./other_db/x.ISM" INTO TABLE tmp
FIELDS ESCAPED BY "" LINES TERMINATED BY "";
SELECT * FROM tmp INTO OUTFILE "y.ISM"
· これで、other_db.x の内容を含む新しいテーブル y が作成され、それに完全にアクセスできるようになりました。
他の人が同じように攻撃するのを防ぐには、「パート 1 内部セキュリティ - データ ディレクトリの保護」の手順に従って、データ ディレクトリにアクセス許可を設定します。サーバーの起動時に --skip-show-database オプションを使用して、ユーザーがアクセス権のないデータベースに対して SHOW DATABASES および SHOW TABLES を使用することを制限することもできます。これにより、ユーザーがアクセスできないデータベースやテーブルに関する情報を見つけることができなくなります。
ALTER 権限は意図しない方法で使用される可能性があります。 user1 には table1 にはアクセスできるが、table2 にはアクセスできないようにしたいとします。 ALTER 権限を持つユーザーは、ALTER TABLE を使用して table1 の名前を変更することで、table2 を変更できます。
GRANT 権限に注意してください。異なる権限を持つ 2 人のユーザーが両方とも GRANT 権限を持っている場合、互いの権限を強化できます。
2.4 GRANT を使用しないユーザーの設定
MySQL バージョン 3.22.11 より前の場合、GRANT (または REVOKE) ステートメントを使用してユーザーとそのアクセス権を設定することはできませんが、認可テーブルの内容を直接変更することはできます。 GRANT ステートメントが付与テーブルをどのように変更するかを理解していれば、これは簡単です。その後、INSERT ステートメントを手動で発行することで、同じことを自分で行うことができます。
GRANT ステートメントを発行するときは、ユーザー名とホスト名、場合によってはパスワードを指定します。このユーザーに対してユーザー テーブル レコードが生成され、これらの値が [ユーザー]、[ホスト]、および [パスワード] 列に記録されます。 GRANT ステートメントでグローバル権限を指定すると、これらの権限はレコードの権限列に記録されます。 GRANT ステートメントではパスワードが暗号化されますが、INSERT ではパスワードを暗号化するために PASSWORD() 関数を使用する必要がないことに注意してください。
データベースレベルの権限を指定すると、ユーザー名とホスト名が db テーブルの [ユーザー] 列と [ホスト] 列に記録されます。承認したデータベースは [Db] 列に記録され、付与したアクセス許可は [Permissions] 列に記録されます。
テーブルレベルと列レベルの権限の場合、効果は同様です。 tables_priv テーブルと columns_priv テーブルにレコードを作成して、ユーザー名、ホスト名、データベース、および関連するテーブルと列を記録します。付与された権限は、「権限」列に記録されます。
前の紹介を覚えていれば、GRANT ステートメントなしで GRANT の動作を実行できるはずです。認可テーブルを直接変更する場合は、サーバーに認可テーブルをリロードするように指示することになります。そうしないと、サーバーは変更を認識できません。 mysqladmin flash-privileges または mysqladmin reload コマンドを実行することで、リロードを強制できます。これを忘れると、なぜサーバーが期待通りの動作をしないのか疑問に思うことになります。
次の GRANT ステートメントは、所有権を持つスーパーユーザーを作成します。他の人を承認する機能を含みます:
GRANT ALL ON *.* TO anyname@localhost IDENTIFIED BY "passwd"
WITH GRANT OPTION
このステートメントは、anyname@localhost のユーザー テーブルにレコードを作成し、すべての権限をオンにします。ここにスーパー ユーザー (グローバル) 権限が保存されます。同じことを行うには INSERT ステートメントを使用する必要があります。ステートメントは次のとおりです。
INSERT INTO user VALUES("localhost","anyname",PASSWORD("passwd) "),
"Y", "Y","Y","Y","Y","Y","Y","Y","Y","Y","Y","Y ","Y","Y ")
MySQL のバージョンによっては、動作しない場合があります。権限テーブルの構造が変更されたため、ユーザー テーブルに 14 個の権限列が存在しない可能性があります。 SHOW COLUMNS を使用して、認可テーブルに含まれる各権限列を検索し、それに応じて INSERT ステートメントを調整します。 次の GRANT ステートメントでも、スーパーユーザー ステータスを持つユーザーが作成されますが、権限は 1 つだけです:
GRANT RELOAD ON *.* TO flash@localhost IDENTIFIED BY "flushpass"
この例の INSERT ステートメントは、前のステートメントよりも単純です。列名をリストし、権限列を 1 つだけ指定するのは簡単です。他のすべての列はデフォルトの「N」に設定されます:
INSERT INTO user (Host,Password,Reload) VALUES("localhost","flush",PASSWORD("flushpass"),"Y")
データベースレベルの権限ON *.* の代わりに ON db_name.* 句を使用して承認します:
GRANT ALL ON sample.* TO boris@localhost IDENTIFIED BY "ruby"
これらの権限はグローバルではないため、ユーザー テーブルには保存されません。 (ユーザーが接続できるように) ユーザー テーブルにレコードを作成する必要がありますが、データベース セットの権限を記録するための db テーブルも作成する必要があります:
INSERT INTO user (Host,User,Password) VALUES("localhost "," boris",PASSWORD("ruby"))
INSERT INTO db VALUES("localhost","sample_db","boris","Y","Y","Y","Y","Y) "," Y","N","Y","Y","Y")
"N" 列は GRANT 権限用です。データベース レベルの最後に WITH GRANT OPTION を指定した GRANT ステートメントの場合、この列を「Y」に設定する必要があります。
テーブルレベルまたは列レベルの権限を設定するには、tables_priv または columns_priv で INSERT ステートメントを使用します。もちろん、GRANT ステートメントがない場合、これらのテーブルはすべて MySQL に同時に表示されるため、これらのテーブルは存在しません。これらのテーブルがあり、何らかの理由でそれらを手動で操作したい場合は、個々の列に対して権限を有効にできないことに注意してください。
tables_priv.Table_priv または columns_priv.Column_priv 列を設定して、有効にする権限の値を含めます。たとえば、テーブルに対する SELECT および INSERT 権限を有効にするには、関連する tables_priv レコードで Table_priv を「Select,Insert」に設定します。
MySQL アカウントを持つユーザーの権限を変更する場合は、権限を追加するか取り消すかに関係なく、INSERT ではなく UPDATE を使用してください。ユーザーを完全に削除するには、ユーザーが使用しているすべてのテーブルからレコードを削除します。
全権限テーブルを直接変更するクエリの発行を避けたい場合は、MySQL に付属の mysqlaccess スクリプトと mysql_setpermissions スクリプトを参照してください。
付録 1 クイズ
MySQL サーバーをインストールし、MySQL への接続を許可されたユーザーを追加した後、次のステートメントを使用します:
GRANT ALL ON samp_db.* TO fred@*.snake .net 「cocoa」が識別されました
そして、fred はたまたまサーバー ホストにアカウントを持っていたため、サーバーに接続しようとしました:
%mysql -u fred -pcocoa samp_db
エラー 1045: ユーザーのアクセスが拒否されました: 'fred @localhost' (使用パスワード: YES)
なぜですか?
その理由は次のとおりです:
まず、mysql_install_db が初期権限テーブルを確立する方法と、サーバーが顧客の接続を照合するためにユーザー テーブル レコードを使用する方法を検討します。 mysql_install_db を使用してデータベースを初期化すると、次のようなユーザー テーブルが作成されます。最初の 2 つのレコードでは、root が localhost またはホスト名を指定してローカル サーバーに接続できるようになり、最後の 2 つのレコードでは、匿名ユーザーがローカル エリアから接続できるようになります。 fred ユーザーが追加されると、
ホスト ユーザー
localhost
pit.snake.net
localhost
pit.snake.net
%.snake.net root
root
fred
サーバーの起動時に、記録して並べ替えます (最初はホスト、次にホスト上のユーザー) が上位になるほど具体的になります:
ホスト ユーザー
localhost
localhost
pit.snake.net
pit.snake.net
%.snake.net root
root
fred
localhost の 2 つのレコードが隣り合ってランク付けされている場合、root のレコードは null よりも具体的であるため、最初にランク付けされます。 pig.snake.net の記録も同様です。これらはすべて、ワイルドカードを含まないリテラルのホスト値であるため、fred のレコードの前、特に匿名ユーザーは fred の前にランク付けされます。
その結果、fred が localhost から接続しようとすると、[Host] 列に空のユーザー名を持つレコードが、%.snake.net を含むレコードの前に一致します。デフォルトの匿名ユーザーにはパスワードがないため、このレコードのパスワードは空です。フレッドが接続時にパスワードを指定したため、不一致が発生し、接続に失敗しました。
ここで覚えておくべきことは、ユーザーが接続できるホストを指定するにはワイルドカードを使用すると便利ですが、ということです。ただし、テーブルに匿名ユーザー レコードを保持している限り、localhost からの接続に問題が発生します。
一般に、匿名ユーザー レコードを削除することをお勧めします。
mysql> DELETE FROM user WHERE User="";
さらに進んで、User 列を含むテーブル内の匿名ユーザーも同時に削除します。 db、tables_priv、columns_priv。
付録 2 新しい MySQL インストールをより安全にする
新しい MySQL サーバーを自分でインストールした後、MySQL root ユーザー (デフォルトではパスワードなし) のディレクトリを指定する必要があります。これを忘れた場合は、MySQL を非常に危険な状態(少なくともしばらくは)。
Unix (Linux) では、マニュアルの指示に従って MySQL をインストールした後、mysql_install_db スクリプトを実行して、認可テーブルと初期権限を含む mysql データベースを確立する必要があります。 Windows では、ディストリビューション内のセットアップ プログラムを実行して、データ ディレクトリと mysql データベースを初期化します。サーバーも稼働していると想定されます。
初めて MySQL をマシンにインストールすると、mysql データベース内の認証テーブルが次のように初期化されます:
· パスワードを指定せずに、ローカル ホスト (localhost) から root として接続できます。 root ユーザーはすべての権限 (管理者権限を含む) を持ち、何でもできます。 (ちなみに、MySQL スーパーユーザーは Unix スーパーユーザーと同じ名前であり、互いに何の関係もありません。)
· test という名前のデータベースと、その名前が始まるデータベースにローカルに接続できるユーザーに匿名アクセスが許可されます。 test_ 付き。匿名ユーザーはデータベースに対して何でも行うことができますが、管理権限はありません。
接続ユーザーがローカルホストのホスト名を使用するか実際のホスト名を使用するかに関係なく、ローカルホストから複数のサーバーへの接続が許可されます。例:
% mysql -h localhost test
% mysql -h pig.snake.net test
パスワードを指定せずに root として MySQL に接続するという事実は、初期インストールが安全ではないことを意味するだけです。管理者として最初に行うべきことは、root パスワードを設定することです。次に、パスワードの設定に使用する方法に応じて、サーバーにこの変更を認識させるために認証テーブルをリロードするように指示することもできます。 (サーバーが起動すると、テーブルがメモリに再ロードされるため、テーブルが変更されたことに気付かない可能性があります。)
MySQL 3.22 以降の場合、mysqladmin でパスワードを設定できます:
% mysqladmin -u root password yourpassword
MySQL のどのバージョンでも、mysql プログラムを使用して、mysql データベース内のユーザー認証テーブルを直接変更できます:
% mysql -u root mysql
mysql>UPDATE user SET password=PASSWORD("yourpassword") WHERE User=" root ";
古いバージョンの MySQL を使用している場合は、mysql と UPDATE を使用してください。
パスワードを設定した後、次のコマンドを実行して、サーバーに認証テーブルをリロードするように指示する必要があるかどうかを確認します:
% mysqladmin -u root status
サーバーがまだ root としてサーバーに接続できるかどうかパスワードを指定してリロードする 認可テーブルをリロードします:
% mysqladmin -u root reload
root パスワードを設定した後 (必要に応じて認可テーブルをリロードした後)、サーバーに接続するたびにパスワードを指定する必要があります。ルートとして。