2019年01月22日

MySQLの新認証方式について

はてなブックマークに登録

MySQL 5.6 で新たな認証方式 sha256_password が追加され、 MySQL 8 ではその改良版となる caching_sha2_password が追加されました。詳しくは MySQL 8.0.4 : New Default Authentication Plugin : caching_sha2_password を参照してください。

これらは従来の native_password 方式よりも安全とされています。 3つの認証方式について特徴をまとめてみます。

攻撃経路

認証方式を考えるとき、ざっくりと2つの攻撃経路があります。

1つ目は mysql.user テーブルの authentication_string カラム (旧 password カラム) です。このカラムをSELECTできるユーザーが、他のユーザーの authentication_string を閲覧し、その情報を元になりすましができる可能性があります。

2つ目は通信経路です。具体的には盗聴したりサーバーになりすますことで、認証に必要な情報を取得する可能性があります。

3つの認証方式の詳細

caching_sha2_password は sha256_password の改良版です。特に初回の認証は sha256_password と同じです。なのでまずは native_password と sha256_password を比較してみましょう。

認証方式 native_password sha256_password
ハッシュ関数 SHA-1 SHA-256
SALT なし あり
認証プロトコル 非可逆なチャレンジ&レスポンス パスワードを可逆な形で送信

native_password

authentication_string カラムの内容は、 native_password が salt なしの純粋な SHA1(SHA1(password)) の先頭に、 MySQL 4.1 以前の形式と区別するための目印として "*" をつけたものです。

mysql> create user t3 identified with 'mysql_native_password' by 'password';
Query OK, 0 rows affected (0.20 sec)

mysql> select Host,User,plugin,authentication_string from mysql.user WHERE User='t3';
+------+------+-----------------------+-------------------------------------------+
| Host | User | plugin                | authentication_string                     |
+------+------+-----------------------+-------------------------------------------+
| %    | t3   | mysql_native_password | *2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19 |
+------+------+-----------------------+-------------------------------------------+
1 row in set (0.00 sec)

mysql> select SHA1(unhex(SHA1('password')));
+------------------------------------------+
| SHA1(unhex(SHA1('password')))            |
+------------------------------------------+
| 2470c0c06dee42fd1618bb99005adca2ec9d1e19 |
+------------------------------------------+
1 row in set (0.00 sec)

このため、複数のユーザーが同じパスワードを利用していると authentication_string も同じになります。また、 NIST により認証に SHA-1 を使うのをやめるように推奨されています。これが前述の記事で説明された、新認証方式が必要になった理由 (native_password の弱点) です。

Client-Serverプロトコル (以降プロトコルと呼ぶ) では、まずサーバーからクライアントに nonce が送られ、クライアントは次の計算結果をサーバーに返します。 (https://dev.mysql.com/doc/internals/en/secure-password-authentication.html#packet-Authentication::Native41 より引用)

SHA1( password ) XOR SHA1( "20-bytes random data from server" <concat> SHA1( SHA1( password ) ) )

サーバーは最初に送信した nonce と SHA1(SHA1(password)) を知っているので、再度 XOR を取ることで SHA1(password) を知ることができます。それにもう一度 SHA1() をかけて authentication_string と一致するかで認証することができます。

攻撃者がこの通信を盗聴した場合、 password や SHA1(password) を知ることができません。

また、 攻撃者がサーバーになりすました場合も、password や SHA1(password) を知ることができません。ただしリレー攻撃で本物のサーバーに接続することは可能です。

もちろん、攻撃者が authentication_string を知っている場合は、サーバーと同じ手順で SHA1(password) を得ることができます。生のパスワードがなくても SHA1(password) があれば本物のサーバーに対して認証を通ることができます。

sha256_password

authentication_string はSALT付きで SHA256 を複数ラウンドしたものらしいです。実際、同じパスワードのユーザーを複数作成してみても、全員が異なる authentication_string が異なります。攻撃者が同じMySQLサーバーにログインして mysql.user テーブルを閲覧可能な場合は、 native_password よりも格段に安全です。

一方で、認証プロトコルは次のようになっています。

  • 安全な経路 (SSL あるいは unix domain socket) では password + nonce を送る。
  • それ以外の経路では password を RSA で暗号化して送る。

どちらも適切に設定されている場合は native_password と同等以上に安全だと思います。

ただしサーバーになりすまされた場合に攻撃者に生の password を与えてしまう点は気になります。なりすましを許した時点でリレー攻撃により本物のサーバーに接続して SET PASSWORD を含む任意のクエリを実行されてしまう可能性があるのであくまでも気持ちの問題ですが。

caching_sha2_password

1度目の認証は sha256_password と同じですが、サーバーはそのときに SHA256(password) をキャッシュします。

2度めからの認証は native_password に似た(ただし SHA-256 を利用した)チャレンジ&レスポンス認証になるので、生パスワードがプロトコル上に乗ることもありませんし、SSLを使っていない環境でRSA暗号化するオーバーヘッドが要らなくなります。

RSA公開鍵に関する設定

SSL を利用しない場合にクライアントがパスワードをRSAで暗号化するための公開鍵は、ローカルにあるファイルを指定する (--server-public-key-path オプション)か、認証時にサーバーから自動取得する (--get-server-public-key オプション) 事ができます。

自動取得を有効にすると、サーバーになりすました攻撃者が自分の RSA 公開鍵を送りつけることで生パスワードを得ることができるようになります。パフォーマンスを考えてもラウンドトリップが1回ふえることになります。なので個人的には --server-public-key-path オプションをお勧めします。

なりすましサーバーにSSL接続してしまった場合にも生パスワード送信してしまうので、SSLを使わない場合は --ssl-mode=DISABLED も設定しておくと良いでしょう。

ただし、繰り返しになりますが、なりすまされてる時点でリレー攻撃可能なので、生パスワードがもれなかったらOKというわけではありません。


@methane

songofacandy at 21:56│Comments(0)

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント