MySQL ユーザ アカウントは、mysql
データベースの user
テーブルでリストしています。それぞれの MySQL
アカウントにはパスワードを割り当てますが、user
テーブルの Password
カラムで保存になるのは、平文テキストのパスワードではなく、パスワードで計算したハッシュ値です。パスワード
ハッシュ値は、PASSWORD()
関数で計算しています。
MySQL は、クライアントとサーバ間通信の 2 つのフェーズでパスワードを使用します。
フェース 1 :
クライアントがサーバに接続しようとするとき、初期認証ステップとして、クライアントがパスワードを提示する。このパスワードは、クライアントが使用するアカウントの
user
テーブルで保存するハッシュ値と一致している必要がある。
フェーズ 2:
クライアントは接続した後、クライアントで、user
テーブルにあるパスワード
ハッシュを設定または変更することができる(適切な権限がある場合)。これには、クライアントが、PASSWORD()
関数を使用してパスワード
ハッシュを生成するか、GRANT
または SET PASSWORD
ステートメントを使用する。
つまり、クライアントが最初の接続を試行するとき、サーバが認証にハッシュ値を使用します。接続したクライアントが
PASSWORD()
関数を呼び出したり、GRANT
または
SET PASSWORD
ステートメントを使用してパスワードの設定または変更を行うと、サーバがハッシュ値を生成
します。
セキュリティ面での向上と、パスワード盗難の危険性に対応する パスワード ハッシュ メカニズムを MySQL 4.1 で更新しました。しかし、この新しいメカニズムはサーバとクライアント同士が相互に MySQL 4.1 以上での使用を必要とするため、それ以外のバージョンを使用している場合には、互換性に問題があります。つまり、MySQL 4.1以上のクライアントは、パスワード ハッシュの新旧メカニズムの両方を理解するため、MySQL 4.1 より前のサーバにも接続できます。MySQL 4.1 より前のクライアントで MySQL 4.1 以上の サーバに接続する場合、問題が発生する可能性があります。たとえば、MySQL 3.23 の mysql のクライアントが 5.1 サーバに接続を試行すると、次のようなエラー メッセージ表示を伴う問題があります。
shell> mysql -h localhost -u root
Client does not support authentication protocol requested
by server; consider upgrading MySQL client
別の例として、 MySQL 4.1
以上にアップグレードしてから、古いバージョンの
PHP で mysql
拡張モジュールを使用するときにも、このような問題が発生します。(
項23.3.1. 「MySQLとPHPに対する共通問題」 を参照のこと。)
次に、新旧のパスワード
メカニズムでの違いと、MySQL 4.1
前の古いクライアントとの下位互換性の維持を必要とする場合のアップグレードについて説明します。項B.1.2.3. 「Client does not support authentication protocol
」
で、追加情報の参照もしてください。ここでの内容は、PHP
で MySQL データベースを 4.0 以前から 4.1
以上にする場合に特に重要です。
注意:ここでの内容は、MySQL 4.1 を境とする動作について説明しています。ここで、4.1 の動作として説明している内容は、実際には 4.1.1 で導入しています。MySQL 4.1.0 は 「特異的なリリース」 が行なわれたため、4.1.1 以降に実装したメカニズムとは若干異なります。4.1.0 以降のバージョン間での違いに関する詳細は、MySQL 5.0 Reference Manual を参照してください。
MySQL 4.1
より前のバージョンでは、PASSWORD()
関数で計算するパスワード ハッシュは 16
バイト長です。次にその例を示します。
mysql> SELECT PASSWORD('mypass');
+--------------------+
| PASSWORD('mypass') |
+--------------------+
| 6f8c114b58f2ce9e |
+--------------------+
MySQL 4.1
より前のバージョンでは、user
テーブルの Password
カラム(ハッシュを保存する場所)も 16
バイト長です。
MySQL 4.1 からは、PASSWORD()
関数で、それまでより長い、41
バイトのハッシュ値を生成します。
mysql> SELECT PASSWORD('mypass');
+-------------------------------------------+
| PASSWORD('mypass') |
+-------------------------------------------+
| *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
+-------------------------------------------+
それに伴い、このバイト幅に合わせて、user
テーブルの Password
カラムも 41
バイト幅です。
MySQL 5.1
の新規インストールで、Password
カラムは自動的に 41 バイト幅になる。
MySQL 4.1 (4.1.1 を含む 4.1 シリーズ) から MySQL 5.1 へのアップグレードでは、パスワード ハッシュ メカニズムが同一であるため、このアップグレードでは、ここに挙げるパスワード ハッシュに関する問題は発生しません。これ以外のアップグレード、たとえば、MySQL 4.1 よりも古いバージョンから 5.1 にする場合は、まず、MySQL 4.1 へアップグレードしてから、 5.1 へのアップグレード (インルトール) を行ないます。
拡張後の Password
カラムには、新旧どちらの形式でもパスワード
ハッシュを保存できます。パスワード
ハッシュ値の形式を次の 2
つの基準で判断します。
バイト幅 (文字列の長さが16 バイトまたは41 バイトのどちらか)。
パスワード
ハッシュの開始文字。新しい形式のパスワードは
‘*
’
文字で始まる。旧形式のパスワードはこれ以外の文字で始まる。
パスワードハッシュ形式は、長い方が暗号化に優れ、クライアント認証においても、旧形式の短いハッシュよりもセキュリティ面での安全性が高まります。
パスワードハッシュのバイト幅の違いは、サーバでのパスワード認証方法と、接続クライアントのパスワード変更に対するサーバでのパスワード ハッシュの生成方法に影響します。
サーバでのパスワード認証方法では、Password
カラムの幅で、次のように影響します。
カラム幅が短いと、ハッシュ認証が短くなる。(制限への影響)
カラムが長いと、長短両方のハッシュを保てるため、サーバ認証では、次のどちらかの方法を使用する。
4.1 より前でのクライアント接続は可能。しかし、旧ハッシュ メカニズムで理解するため、短いハッシュのアカウントだけを認証する。
4.1 以降のクライアントは、長短どちらのハッシュのアカウントも認証する。
ハッシュのアカウントが短くでも、実際は認証プロセスが 4.1 以降のクライアントであれば、古いクライアントを使用しているよりは、セキュリティ面での安全を確保しています。認証のセキュリティは以下の順で高くなります。
短いパスワード ハッシュでアカウントに対して、4.1 より前のバージョンのクライアント認証
短いパスワード ハッシュでアカウントに対して、4.1 以降のクライアント認証
長いパスワード ハッシュのアカウントに対して、 4.1 以降のクライアント認証
サーバが接続クライアントに対してパスワード
ハッシュを生成する方法には、Password
カラムの幅と --old-passwords
オプションが影響を与えます。つまり、4.1
以降のサーバでは、Password
カラムがハッシュ値 (長さ)
に対応する、そして、--old-passwords
オプションを指定していない、という条件を満たすと、長いハッシュを生成します。ここでは、次のことに注意します。
Password
カラムが 41 バイト
のハッシュを保存できる長さであること。4.1
へのアップグレード後に、mysql_fix_privilege_tables
スクリプトを実行して、Password
カラムが長くなったことを更新して知らせる。ここで、カラムの更新を行なわず、4.1
より前の長さの 16
バイトのままの状態にしておくと、クライアントが
PASSWORD()
、GRANT
、SET
PASSWORD
を使用してパスワードの変更操作を行うときに、サーバはまだハッシュが長くなったことを知らされていないため、長いハッシュは収まらないと認識し、短いハッシュを生成する。
Password
カラムの長さ (幅)
が十分であれば、長短どちらのパスワードハッシュも保存できる。この場合、サーバを
--old-passwords
オプションで起動していないときは、PASSWORD()
、GRANT
、SET
PASSWORD
で、長いハッシュを生成する。このオプションを指定すると、強制的に短いパスワードハッシュを生成する。
--old-passwords
オプションを使用する目的には、サーバが長いパスワード
ハッシュを生成する環境において、4.1
より前のクライアントと下位互換性を保てるようにすることがあります。このオプションは認証に影響するのではなく、4.1
以降のクライアント、つまり新しいメカニズムのクライアントでは長いパスワード
ハッシュのアカウントを使用できるようになっているため、それがパスワードの変更操作の結果として、サーバの
user
テーブルに、長いパスワード
ハッシュを保存しないようにします。長いパスワード
ハッシュを保存してしまうと、 4.1
より前のクライアントが、このアカウントを使用できなくなります。たとえば、--old-passwords
オプションを指定しないで接続を行なうと、次に示すようなシナリオが想定できます。
古いバージョンのクライアントが、短いパスワード ハッシュのアカウントで接続する。
このクライアントがアカウントのパスワードを変更する。--old-passwords
オプションをかけていなければ、アカウントに長いパスワード
ハッシュの生成が可能になる。
そして、古いバージョンのクライアントがアカウントに長いパスワード ハッシュをセットしていた場合、長いパスワードは新しいメカニズムでの認証を行なうため、このクライアントが改めて、その長いパスワードをセットしたアカウントからは接続ができなくなります。つまり、このアカウントに長いパスワード ハッシュがあることを、テーブルに読み込ませてしまうと、そのクライアントが古いバージョンであるために、長いハッシュを認識することができません。(4.1 以降の新しいバージョンのクライアントは長いパスワードを認識します。)
このシナリオでは、4.1
より前のバージョンのクライアントをサポートする必要がある場合には、4.1
以降のサーバを稼動するのは危険であり、これを回避するには、--old-passwords
オプションが必要であることを示しています。--old-passwords
オプションでサーバを立ち上げていれば、パスワード変更の操作を行なっても、長いパスワード
ハッシュを生成することはありません。これにより、古いバージョンのクライアントでアカウントにアクセスできなくなるということはありません。つまり、クライアントの不注意で、パスワード変更が長いパスワード
ハッシュの生成を起因して、アクセスできなくなるということはありません。
--old-passwords
オプションの短所は、どのようなパスワードを作成しても、短いハッシュになることです。これは
4.1
を使用しているクライアントにも該当します。そのため、長いパスワード
ハッシュによるセキュリティのメリットを活用できません。4.1
を使用しているクライアントに、長いハッシュでアカウントを作成する必要がある場合などは、--old-passwords
オプションを使用しないで、サーバが実行中のときに、その操作を行なう必要があります。
4.1 以降のサーバが実行中のときに考えられるケースとしては、次のようなシナリオがあります。
シナリオ 1: ユーザ
テーブルの Password
カラム値の幅が短い場合
Password
カラムには、短いハッシュだけが保存の対象になる。
クライアント認証に、サーバが短いハッシュだけをし使用する。
接続クライアントでは、PASSWORD()
、GRANT
、SET
PASSWORD
などを使用するパスワード
ハッシュの生成操作では、完全に短いハッシュを使用する。アカウントのパスワードの変更で、長くで設定してもパスワード
ハッシュは短くなる。
--old-passwords
を使用するが、これには何の効果もない。その理由は、Password
カラムが短いハッシュだけを受け入れるため、サーバは短いパスワード
ハッシュだけを生成しているからである。
シナリオ 2:
Password
カラムに長いハッシュを保存できるが、サーバを
--old-passwords
オプションで起動しない場合
Password
カラムには、長短、両方のハッシュが保存の対象になる。
4.1 以降のクライアントは、長短どちらのハッシュのアカウントも認証する。
4.1より前のクライアントでは、短いハッシュのアカウントだけを認証する。
接続クライアントでは、PASSWORD()
、GRANT
、
SET PASSWORD
などを使用するパスワード
ハッシュの生成操作では、完全に長いハッシュを使用する。アカウントのパスワードの変更で、長いパスワード
ハッシュのアカウントになる。
前述したように、このシナリオでの問題点は、4.1
より前のクライアントが短いパスワード
ハッシュのアカウントでアクセスができなくなることです。GRANT
,
PASSWORD()
, or SET
PASSWORD
を使用して該当アカウントのパスワードを変更することは、そのアカウントに長いパスワード
ハッシュを与えることになります。この時点から、4.1
より前のクライアントを、4.1
にアップグレードしなければ認証ができません。
この問題の対処するには、パスワードを特別の方法で変更します。たとえば、通常、アカウントのパスワード変更には、SET
PASSWORD
を次のように使用しています。
SET PASSWORD FOR 'some_user
'@'some_host
' = PASSWORD('mypass');
パスワードを変更するけれども短いハッシュで作成する場合には、OLD_PASSWORD()
関数を使用します。
SET PASSWORD FOR 'some_user
'@'some_host
' = OLD_PASSWORD('mypass');
OLD_PASSWORD()
関数は、明らかに短いハッシュを生成する必要があるような場合に使用します。
シナリオ 3:
Password
カラムに長いハッシュを保存できるが、サーバを
--old-passwords
オプションで 4.1
以降のサーバ起動する場合
Password
カラムには、長短、両方のハッシュが保存の対象になる。
4.1
以降のクライアントは、長短どちらのハッシュのアカウントも認証する。(注意:長いハッシュは、--old-passwords
オプションを使用しないでサーバを起動したときにだけ作成できる。
)
4.1より前のクライアントでは、短いハッシュのアカウントだけを認証する。
接続クライアントでは、PASSWORD()
、GRANT
、SET
PASSWORD
などを使用するパスワード
ハッシュの生成操作では、完全に短いハッシュを使用する。アカウントのパスワードの変更で、長くで設定してもパスワード
ハッシュは短くなる。
このシナリオでは、--old-passwords
オプションが長いハッシュの生成を抑制するため、長いパスワード
ハッシュのアカウントを作成することはできません。さらに、--old-passwords
オプションを使用する前に長いハッシュでアカウントを作成する場合、--old-passwords
を行使中にアカウントのパスワードを変更すると、短いパスワードのアカウントになるため、長いハッシュのセキュリティ面でのメリットを活用できなくなります。
次に、これらのシナリオの問題を概括します。
シナリオ 1 では、セキュリティ上の安全をより確保できる長いハッシュの長所を活用できません。
シナリオ 2 では、OLD_PASSWORD()
を明示的に使用しないで、パスワードを変更する場合、4.1
より前のバージョンのクライアントが短いハッシュのアカウントではアクセスできなくなる。
シナリオ 3 では、--old-passwords
オプションが、短いハッシュのアカウントのアクセスを抑制していますが、パスワード変更操作が長いハッシュを短いハッシュに戻します
(操作で長いハッシュに変更してもその操作が取り消しになる)。この短くなったハッシュは、--old-passwords
を施行している間は、元 (長いハッシュ)
に戻せません。