無料PHPプログラム

MySQL 5.1 リファレンスマニュアル :: 4 データベース管理 :: 4.7 MySQL アクセス権限システム :: 4.7.5 アクセス制御の段階 1: 接続確認
« 4.7.4 MySQL サーバへの接続

4.7.6 アクセス制御の段階 2: 接続確認 »
Section Navigation      [Toggle]
  • 4.7 MySQL アクセス権限システム
  • 4.7.1 権限システムの役割
  • 4.7.2 権限システムの機能
  • 4.7.3 MySQL 提供の権限
  • 4.7.4 MySQL サーバへの接続
  • 4.7.5 アクセス制御の段階 1: 接続確認
  • 4.7.6 アクセス制御の段階 2: 接続確認
  • 4.7.7 権限の変更が反映するタイミング
  • 4.7.8 Access denied エラーの原因
  • 4.7.9 MySQL 4.1 のパスワードハッシュ

4.7.5. アクセス制御の段階 1: 接続確認

ユーザが MySQL サーバに接続しようとした場合、そのユーザ ID、およびそれを正しいパスワードで裏付けできるかどうかによって、サーバは接続の許可または拒否を行います。パスワードが正しくない場合、サーバはアクセスを完全に拒否します。正しければ、サーバは接続を許可し、段階 2 に進んで要求を待ちます。

ユーザ ID は、2 つの情報に基づきます。

  • 接続元のホスト

  • MySQL ユーザ名

ID チェックには、user テーブルの 3 つのスコープフィールド(Host、 User、 Password)を使用します。user テーブルエントリが、指定した Host と User と一致し、入力したパスワードが正しい場合のみ、接続許可になります。

user テーブルの Host値 (スコープ フィールド) には次の方法で値を指定できます。

  • Host 値にはホスト名または IP アドレスを使用できる。ローカルホストを指定する場合は 'localhost' を使用する。

  • ワイルドカード文字 ‘%’ および ‘_’ を Host フィールドに使用できる。LIKE 演算子で実行するマッチング操作と同様の効果がある。たとえば、Host 値としての '%' はすべてのホスト名を意味する。これに対して、'%.mysql.com' という値は mysql.com ドメインのすべてのホスト名と一致する。

    MySQL ネットワーク.? ‘%’ のような広宿主の指示子はセキュリティ リスクをもたらします。 MySQL Network Monitoring and Advisory Service ではこのような脆弱性に対応するセーフガードを提供しています。詳細は http://www-jp.mysql.com/products/enterprise/advisors.html を参照してください。

  • IP アドレスとして指定する Host 値に、ネットワークアドレスを示すためのネットマスクを使用できます。次はその例です。

    GRANT ALL PRIVILEGES ON db.* TO david@'192.58.197.0/255.255.255.0';
    

    これは、david が client_ip という IP アドレスのクライアント ホストから接続できます。これには次の条件があります。

    client_ip & netmask = host_ip
    

    つまり、GRANT ステートメント表示です。

    client_ip & 255.255.255.0 = 192.58.197.0
    

    この条件に該当し、MySQL サーバに接続できる IP アドレスは、192.58.197.0 から 192.58.197.255 までの範囲のもということになります。

    ノート:ネットマスクの使用は 8、16、24、または 32 ビットのいずれかのアドレスを使用するようにサーバへ知らせます。たとえば、次の通りです。

    • 192.0.0.0/255.0.0.0: 192 クラスの A ネットワークのすべて

    • 192.168.0.0/255.255.0.0: 192.168 クラスの B ネットワークのすべて

    • 192.168.1.0/255.255.255.0: 192.168 1 クラスの C ネットワークのすべて

    • 192.168.1.1: 特定の IP のみ。

    次に示すネットマスク (28 ビット) は使用できません。

    192.168.0.1/255.255.255.240
    
  • db テーブル行 (エントリ) の 空白の Host 値

    は、その権限が、クライアントのホスト名と一致する host テーブルの行のものと組み合わさるという意味です。この権限は、OR (ユニオン) ではなく、AND (インターセクション) 操作を使用して組み合わせられています。 host テーブルの使用については、項4.7.6. 「アクセス制御の段階 2: 接続確認」 を参照してください。

    別の権限テーブルの空白の Host 値は、'%' と同じである。

たとえば、'144.155.166.%' がサブネットのすべてのホストと一致する、というように、Host カラムの IP ワイルドカードの値を使用できるということは、ホストを 144.155.166.somewhere.com と命名するなどして、誰かがこの機能 (セキュリティー上の弱点) を悪用できるということです。これを阻止するために、MySQL では、数字やドットで始まるホスト名との一致しないようになっています。つまり、1.2.foo.com のようなホスト名の場合、この名前は、権限テーブルの Host カラムとは一致しないということです。IP ワイルドカード値は、IP アドレスとだけ一致し、ホスト名とは一致しません。

User フィールドには、ワイルドカード文字は使用できません。空白の値は使用でき、これは任意のユーザ名と一致します。user テーブル エントリに空白のユーザ名があり、接続で空白ユーザーにマッチする場合、そのユーザはクライアントが実際に指定した名前のユーザではなく、匿名ユーザ(名前なしのユーザ)との解釈になります。この場合、接続中(段階 2 の間)のフル アクセス チェックをすべて、空白のユーザ名で行うということです。

Password フィールドは空白にできます。これはどのパスワードにも一致するという意味ではなく、そのユーザがパスワードを指定せずに接続する必要があるという意味です。

user テーブルの空白ではない Password 値は、暗号化パスワードを表します。 MySQL では、パスワードを平文テキストでは保存しません。接続しようとするユーザが入力したパスワードを暗号化します(PASSWORD() 関数を使用)。クライアントおよびサーバがパスワードの確認を行うときは、その暗号化パスワードを使用します。(このとき、その接続を経由して、暗号化パスワードを転送することはありません)。注意: MySQL から見ると暗号化パスワードが実際のパスワードであるため、暗号化パスワードにだれにもアクセスできないようにしてください。特に、一般のユーザに mysql データベース内のテーブルの読み取りアクセス権を与えないでください。

MySQL 5.1 では (最初の実装は MySQL 4.1 から)、MySQL は従来とは異なるパスワードおよびログインメカニズムを採用しています。万が一、TCP/IP パケットの傍受や mysql データベースのキャプチャが行なわれた場合でも安全確保できるようになっています。パスワードの暗号化に関する詳細は 項4.7.9. 「MySQL 4.1 のパスワードハッシュ」 を参照してください。

次の一覧は、user テーブルエントリの Host 値および User 値のさまざまな組み合わせがどのように着信の接続に適用するかを示します。

Host 値 User 値 正当な接続
'thomas.loc.gov' 'fred' thomas.loc.gov から接続する fred
'thomas.loc.gov' '' thomas.loc.gov から接続するすべてのユーザ
'%' 'fred' 任意のホストから接続するfred
'%' '' 任意のホストから接続するすべてのユーザ
'%.loc.gov' 'fred' loc.govドメイン内の任意のホストから接続する fred
'x.y.%' 'fred' x.y.net、x.y.com、x.y.edu などから接続する fred (実用的ではない)
'144.155.166.177' 'fred' IP アドレス 144.155.166.177 のホストから接続する fred
'144.155.166.%' 'fred' 144.155.166 クラス C サブネットの任意のホストから接続する fred
'144.155.166.0/255.255.255.0' 'fred' 1 つ上の例と同じ

クライアントのホスト名と着信するユーザ名が、user テーブルのエントリ一つ以上と、一致する可能性があります。前述の例で説明すると、たとえば、thomas.loc.gov からの fred の接続は、前述の一覧のいくつかのエントリと一致します。

複数のエントリが一致した場合、サーバは該当するものを選択するために、次のことを行ないます。

  • サーバが user テーブルをメモリに読み込むときに、エントリのソートをする。

  • クライアントが接続しようとすると、サーバはソート順でエントリを照会する。

  • サーバはクライアントのホスト名とユーザ名が一致する最初のエントリを使用する。

user テーブルが次の内容であると仮定して、これがどのように作用するかを説明します。

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| %         | root     | ...
| %         | jeffrey  | ...
| localhost | root     | ...
| localhost |          | ...
+-----------+----------+-

サーバがテーブルをメモリに読み込むと、最も具体的な Host 値を最初にもってきます。ここでは、Host カラムの '%' は 「任意のホスト」 を意味し、具体性が最も低いものとなります。同じ Host 値のエントリ間で、最も具体的な User 値を最初にもってきます。ここでは、空白の User 値は 「任意のユーザ」 を意味し、具体性が最も低いものとなります。ソートした user テーブルは次のようになります。

+-----------+----------+-
| Host      | User     | ...
+-----------+----------+-
| localhost | root     | ...
| localhost |          | ...
| %         | jeffrey  | ...
| %         | root     | ...
+-----------+----------+-

クライアント接続が試みられると、サーバはソートしたエントリで突き合わせ (マッチング) を行い、最初に一致したものを使用します。localhost からの jeffrey による接続では、2 つのエントリが一致します (空白ユーザ名のエントリが接続ホスト名とユーザ名の両方で一致) 。Host と User のカラム値をみると、'localhost' と '' の値が一致します。 そして、'%' と 'jeffrey' の値が一致します。ここで、ソートしたときに、'localhost' が最も具体的な値であるため、これが最初に来ます。よってサーバは、表示の順序で選択します。

次に、別例を示します。user テーブルが次の内容である場合

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| %              | jeffrey  | ...
| thomas.loc.gov |          | ...
+----------------+----------+-

ソート後のテーブルは次のようになります。

+----------------+----------+-
| Host           | User     | ...
+----------------+----------+-
| thomas.loc.gov |          | ...
| %              | jeffrey  | ...
+----------------+----------+-

thomas.loc.gov からの jeffrey による接続は、最初のエントリを一致とし、whitehouse.gov からの jeffrey による接続は 2 番目のエントリとなります。

サーバが接続の突き合わせを行うとき、ユーザ名とは、明示的にそのユーザを名付けている (ユーザであると定義している) すべてのエントリが最初に来ると、考えることができますが、これは間違っています。上記の例でもわかるように、thomas.loc.gov からの jeffrey による接続は、'jeffrey' が User フィールド値であるエントリではなく、ユーザ名なしのエントリと最初に一致します。つまり、jeffrey で接続する、とユーザ名を指定したにもかわらず、彼は匿名ユーザとして認証されています。

接続したが、権限が予期したものと違うという場合、別のユーザで認証している可能性があります。サーバがどのユーザで認識が行なわれたかを突き止めるには、CURRENT_USER() 関数を (項11.10.3. 「情報関数」 参照) 使用します。(その接続に実際に一致しているユーザとホストの組み合わせを確認できます。) そのときに、 user_name@host_name という形の値を返します。これは、User と Host のカラムの値が、user テーブル行でどのように一致となっているのかを示します。たとえば、jeffrey で接続して、次のようなクエリを発行したとします。

mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost     |
+----------------+

ここでの結果は、user テーブル行で一致したものが、空白の User であることを示します。つまり、サーバは jeffrey を匿名ユーザとして扱っています。

このような認証に関わる診断をする、別の方法として、user テーブルを出力して、それをマニュアル (手動) でソートし、最初の組み合わせをどのような経緯でしたか調べます。

Copyright c 1997, 2010, Oracle and/or its affiliates. All rights reserved. Legal Notices
Top / Previous / Next / Up / Table of Contents
© 2010, Oracle Corporation and/or its affiliates

無料CGI PHPスクリプト | 新着情報スクリプト | 営業日カレンダー | PHPマニュアル | MySQLマニュアル | PEARマニュアル

Copyright (c) 2010 jmcodex.com All rights reserved.