2013年8月26日月曜日

PHP5.5.2以降のstrict sessionsモードでセッションフィクセイション対策はどうすればよいか

先日のエントリ『【速報】PHP-5.5.2にて大垣さんのstrict sessionsが実装されました』にて、PHP5.5.2でセッションアダプションが解消されたことを報告しました(session.use_strict_mode=1の場合)。
セッションアダプションとは、未初期化のセッションID(たとえばPHPSESSID=ABC)をPHPが受け入れる問題のことです。strict sessionsを使用すると、PHPが生成し、現在有効であるセッションIDのみを受け入れ、そうでない場合、PHPはセッションIDを振り直します。

あいにくPHP5.5.2(PHP5.5.3も)にはバグがあり、session.use_strict_mode=1によるstrict sessionsは使用できませんが、既に大垣さん自身によりバグ修正されているので、PHP5.5.4からは使えるようになるでしょう。

strict sessionsの主な目的は、セッションフィクセイション攻撃に対する影響緩和ですが、では、strict sessionsを用いると、セッションフィクセイション対策はどのように変わるでしょうか?

従来のPHP、すなわちセッションアダプションがある状態では、セッションフィクセイション対策は下記の通りでした。
  • ログイン直後にsession_regenerate_id関数によりセッションIDを振り直す
これに対して、セッションアダプションがない状態ではどうでしょうか。先に『セッションアダプションがなくてもセッションフィクセイション攻撃は可能』で説明したとおり、攻撃者が、対象サイトのセッションIDを取得することにより、セッションフィクセイション攻撃は可能です。従って、strict sessionsの状況でも、セッションフィクセイション対策は下記の通りです。
  • ログイン直後にsession_regenerate_id関数によりセッションIDを振り直す
何も変わらないわけです。

…とここで終わりにしてもよいのですが、せっかく大垣さん8年越しのstrict sessionsが使えるようになったので、セッションIDの振り直しをしないでセッションフィクセイション対策ができないか考えてみましょう。

先に説明したように、セッションアダプションがない状況では、攻撃者は、対象サイトから有効なセッションIDを取得する必要があります。ここに着目し、「攻撃に使えるセッションIDを攻撃者に渡さない」アプローチを考えてみます。セッションアダプションがなく、セッションIDがとれない状況では、セッションフィクセイション攻撃はできません。

まず、上記がだめな状況として、ログイン状況でなくてもセッションを使っているサイトが挙げられます。この場合、サイトにアクセスさえすれば有効なセッションIDが取得できるため、セッションフィクセイション攻撃が可能になります。このため、以下では、セッションはログイン状態でのみ使用しているという前提とします。

以下、ログイン状態でのみセッションを使っているアプリケーションを想定して、セッションIDの振り直しをしないでセッションフィクセイション対策する方法を検討します。以下の処理毎に検討します。
  • ログイン前
  • ログイン処理
  • ログイン状態の確認処理
  • ログアウト処理

ログイン前

前述のように、ログイン前にセッションを有効にすると、そのセッションIDを悪用してセッションフィクセイション攻撃ができてしまいます。このため、ログイン前にはセッションは使えません。これによる副作用として、ログイン時にCSRF対策したい場合でも、それが困難になります。CSRFの標準的な対策にはセッションを利用するからです。

ログイン処理

ログイン処理の注意として以下があります。
  • ログインに失敗した場合は、セッションID悪用防止のためセッションを破棄する
  • 元々ログイン状態の場合は、ログイン処理を継続しない。攻撃者のログイン状態のセッションIDによる攻撃を防ぐため
これを実現する擬似コード例を下記に示します。
session_start();
if (ログイン済みの状態) {
  echo "ログイン済みです";
  // マイページなど、遷移可能なページへのリンクを表示
  // あるいは、異常事態としてセッション破棄するという考え方もあり
} else if (idとパスワードが有効) {
  // ログイン処理
  $_SESSION['user'] = $id;
  // その他の処理
} else {
  echo "IDまたはパスワードが違います";
  // 認証失敗の場合はセッションを破棄
  session_destroy();
}
重要なポイントとしては、(1)ログイン済みなのに他のユーザでログインすることを許さない、(2)認証に失敗した場合は必ずセッションを破棄する、ということがあげられます。
また、懸念点として、ログイン処理中にアプリケーションが異常終了すると、session_destroyが呼び出されず、有効なセッションが残ってしまう可能性があります。対策は、セッションを有効にする区間をできるだけ短くすることですが、詳しい説明を割愛します。

ログイン状態の確認処理

ログイン前の攻撃者がセッションIDを取得する方法として、攻撃者が、認証の必要なページにアクセスするというものがあります。
典型的なログイン確認は以下の通りです。
session_start();
if (! isset($_SESSION['user'])) {
  echo 'ログインしてください';
  // ログインページへのリンクを表示
  exit;
}
これだと、セッションIDは生成され、セッションは有効なままなので、攻撃者は有効なセッションIDを取得できます。これを防ぐには、exitする前にセッションを破棄します。
session_destroy();
これにより、セッションは有効でなくなるため、セッションフィクセイション攻撃に使えるセッションIDは取得できなくなります。この処理は、ログイン状態を確認するページ全てで、もれなく実装する必要があります。

ログアウト処理

ログアウト処理において重要なポイントは、かならずセッションを破棄するということです。そうしないと、ログアウト後に残ったセッションのセッションIDを用いて、セッションフィクセイション攻撃ができてしまいます。
具体的には、下記のようなログアウト処理はだめだと言うことです。
$_SESSION['user'] = false; // 認証ユーザをfalseにすることでログアウトとする

アプリ側のセッションタイムアウトに対する注意

アプリケーション仕様によっては、PHPのセッションは有効だが、アプリ側で定めたセッションタイムアウトになっているという状況が考えられます。この場合、「ログアウト状態だがセッションIDは有効」という状態になり、セッションフィクセイション攻撃に使えるセッションIDができてしまいます。
この対策としては、下記が考えられます。
  • ログイン状態の確認処理の中で、タイムアウトしたセッションを破棄する
  • ログイン処理においては、タイムアウトしたセッションは、いったん破棄して、再度セッションを開始する。
ログイン状態の確認…については、前述の処理でカバーされているとも考えられますが、ログイン処理の方は特に注意が必要です。

一方、PHP処理系側でタイムアウトしたセッションは、既に破棄されているため、アプリケーション側で特に注意することはありません。

まとめ

strict sessionsにおいても、セッションフィクセイション攻撃対策として、認証成功直後のsession_regenerate_idは必須ですが、敢えてこれをしないで、セッションフィクセイション攻撃対策する方法を検討し、以下が必要であることを示しました。
  • ログイン前にはセッションを使用しない
  • ログインに失敗した場合は、セッションを破棄する
  • 元々ログイン状態の場合は、ログイン処理を継続しない
  • ログイン状態の確認において、ログイン状態でない場合はセッションを破棄する
  • ログアウト処理ではセッションを破棄する
  • ログイン状態の確認処理の中で、タイムアウトしたセッションを破棄する
  • ログイン処理においては、タイムアウトしたセッションは、いったん破棄して、再度セッションを開始する
ご覧のように、strict sessionsによってセッションフィクセイション脆弱性を気にしないですむどころか、至る所でセッションフィクセイション脆弱性に配慮しなければならないことがわかりました。上記の1カ所でも漏れると、セッションフィクセイション脆弱性の可能性が生じます。

したがって、strict sessionsにおいても、下記を推奨します。これだと、セッションフィクセイション対策は、ログイン処理1カ所に集約できます。
  • ログイン直後にsession_regenerate_id関数によりセッションIDを振り直す
ということで、strict sessionsにおいても、アプリケーションの書き方は変わらない、というのが結論です。

2013年8月17日土曜日

【速報】PHP-5.5.2にて大垣さんのstrict sessionsが実装されました

大垣さんのツイートで、strict sessionsがPHPにマージされることを知りました。
本日、PHP-5.5.2が公開されましたので、ChangeLogを確認したところ、確かに入っているようです。
  • Sessions:
    • Implemented strict sessions RFC (https://wiki.php.net/rfc/strict_sessions) which protects against session fixation attacks and session collisions.
PHP 5 ChangeLog より引用
8年越しのstrict sessionsのマージ、まことにおめでとうございます。

さっそく、PHP-5.5.2をビルドして確認してみました。まずはデフォルトの状態(php.ini-productionを使用)。


確かに、session.use_strict_modeが追加されていますね。デフォルトはOffのようです。これは後方互換性に配慮したものでしょう。session.use_strict_modeを有効にするには、php.iniに下記を追加すればよいのでしょうね。
session.use_strict_mode = On
これを設定して再度phpinfoを実行すると、下記の画面に。


いい感じです(当たり前か)。
さっそくこの状態で試してみましょう。スクリプトとして以下を用いました。
<?php
  session_start();
  if (isset($_SESSION['counter'])) {
    $_SESSION['counter']++;
  } else {
    $_SESSION['counter'] = 0;
  }
  echo 'phpversion: ' . htmlspecialchars(phpversion()) . '<br>';
  echo 'session_id: ' . htmlspecialchars(session_id()) . '<br>';
  echo 'counter : ' . htmlspecialchars($_SESSION['counter']);
これを実行すると下記の表示になります。
phpversion: 5.5.2
session_id: i0h3ej9hcs6dd40sopac9pf483
counter : 0>
セッションファイルを見ると、確かに生成されています。
$ sudo cat /tmp/sess_i0h3ej9hcs6dd40sopac9pf483
counter|i:0;$
しかし、セッションクッキーとして違うIDが返ってきています(HTTPレスポンスの抜粋)。
HTTP/1.1 200 OK
Set-Cookie: PHPSESSID=7irqs0dkccnusq9ckjcnlmkn21; path=/
Content-Length: 74
Content-Type: text/html

phpversion: 5.5.2<br>session_id: i0h3ej9hcs6dd40sopac9pf483<br>counter : 0
このため、新規にセッションを開始することができず、永遠にカウンタは 0 のままです。この状態で、PHPの下記の警告が表示されます。
PHP Warning:  session_start(): The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in /var/www/session.php on line 2
ちなみに、session.use_strict_mode = Off (あるいは指定しない)の場合は、セッションは正常に使用でき、カウンターはインクリメントされます。そして、有効なセッションがある状態(セッションクッキーとセッションファイル名が一致している状態)では、session.use_strict_mode = On でもセッションは有効に使用できます。

まとめ

PHP-5.5.2にて、大垣さんの提唱されてきたstrict sessionsがマージされました。私の検証した範囲では、まだ不具合があり使えないようですが、私の環境に依存する問題かもしれませんので、PHP関係者が追試されることを希望します。
このstrict sessionsにて、PHPのセッションアダプションが解消されるはずです。私は「PHPのセッションアダプションは重大な問題ではないが、ない方がよい」という認識でしたので、この改善を私は歓迎いたします。
現時点ではPHP5.3とPHP5.4にはstrict sessionsはマージされていないようですが、だから言ってこれらPHPのバージョンが脆弱だとまではいえないと考えます。

追記(2013/08/17 21:00)

その後テスト用のサンプルをいじっているうちに、セッションが空の場合session_regenerate_id(true);を実行すると、期待したとおりに動作することが分かりました。上記のサンプルだと、「} else {」 の次の行に session_regenerate_id(true); を追加すると、セッションが維持できるようになります。

追記(2013/08/21 9:00)

bugs.php.netにバグ報告したところ、大垣さん自身が速攻で修正してクローズしていただきました。大垣さん、ありがとうございました。

関連するエントリ

2013年8月16日金曜日

MACHIDA.KANAGAWA.JPはなぜ「まぎらわしい」のか

私は検証用にいくつかのドメイン名を登録していますが、そのうちの一つが「発掘」され、世間をお騒がせすることになってしまいました。

このページのページビューは、8月16日(金) 9:00現在で、31438となっています。ずいぶんよく参照されています。ちなみに、「本物の」町田市のホームページは下記の通りです。


しかし、上記のような主張はいままでにもあったし、今更二番煎じのこのネタが、上記のような簡素な内容で話題になる理由としては、やはり MACHIDA.KANAGAWA.JPというドメイン名にあるのでしょう。これは「都道府県型JPドメイン名」というもので、「日本国内に住所を持つ個人・組織であれば、いくつでも登録ができます」(こちらより引用)。

では、どうして紛らわしいドメイン名が登録できるかという理由を説明します。
都道府県型JPドメイン名ができる前に地域型JPドメイン名というものがあり、多くの地方公共団体が利用しています。以下は、地域型JPドメイン名のうち、「地方公共団体ドメイン名」の説明です。JPDirectの説明ページから引用しました。


上記のように、政令指定都市をのぞく「市」のドメイン名は以下のルールに従います。


地域型JPドメイン名のルールは複雑なので、「地域型ドメイン名は廃止してはどうか」という指摘もあったものの、市のホームページに限っていえば、上記のルールに従ったドメイン名は「市」のものであることが確実でありました。
世の中には偽サイトというものがあり、フィッシングや偽情報の流布に使われます。ドメイン名を暗記していないサイトの場合、サイトの内容やデザインを見ただけでは区別がつかないので、ドメイン名の形式から簡単に地方公共団体のものであることが判別できると安心です。たとえば、日本の政府機関のドメイン名は「.go.jp」で終わるドメイン名となっている(例外もある)ので、簡単に判別できます。

地域型JPドメイン名は、個人や一般の団体でも取得できましたが、第4レベルが選べるもので、「市」のドメイン名とは簡単に区別がつきました。
  • TOKUMARU.BUNKYO.TOKYO.JP (私のドメイン名)
  • MITA.MINATO.TOKYO.JP (三田典玄氏のドメイン名)
※ 三田典玄氏のドメイン名は、港区三田という地名が実際にあるのでややこしいですが、大きな誤解は生じないでしょう。このドメイン名もシャレなんでしょうね。

さて、地域型JPドメイン名は、とにかく長いという欠点があり、あまり活用されていなかったようです。このため、2012年3月31日で新規登録が終了し、2012年11月から都道府県型JPドメイン名というものが使えるようになりました。その形式は下記となります(都道府県型.jpより引用)。


上図のように、「〈都道府県名〉.JP」の部分が旧の地域型JPドメイン名と重なっているため、地域型JPドメイン名の部分は予約され、都道府県型JPドメイン名としては登録できないようになっています。予約名の一覧はこちらから参照できます。
このように、ドメイン名を見ただけでは、地域型JPドメイン名なのか都道県型JPドメイン名なのか区別がつかなくなってしまいました(地域型JPドメイン名をすべて暗記していない限り)。このため、以下のようにややこしいことが起こります。
  • CITY.MACHIDA.TOKYO.JP : 町田市の本物のドメイン名(地域型JPドメイン名)
  • CITY.MACHIDA.KANAGAWA.JP : 筆者のドメイン名(のサブドメイン名)(都道府県型JPドメイン名)
すなわち、都道府県型JPドメイン名が出現するまでは、下記の形式のドメイン名は「市のドメイン名」であることが確実だったのに、その保証がなくなってしまったことになります。従来地域型JPドメイン名を使っていた地方公共団体や、市民にとっては迷惑な話ですね。


では、どうすればよいかというと、地方公共団体には、LG.JPドメイン名に移行してもらうしかないでしょう。
LG.JPドメイン名創設の目的
地方公共団体では、政府がe-Japan戦略に掲げる電子政府・電子自治体の実現に向け、住民・企業がインターネットを利用していつでもどこでも申請・届出等の手続が行える仕組みづくりを進めています。
匿名性が高いインターネット上で、住民・企業の皆様が安心して行政サービスを利用できるようにするためには、まずは行政サービスの提供者が地方公共団体であることを、住民・企業の皆様に分かりやすく示す必要があります。このため、政府機関等を収容するドメイン空間「GO.JP」に対応する、厳密に地方公共団体及び地方公務員を収容した住民・企業の皆様に分かりやすい地方公共団体行政専用のドメイン空間が必要とされました。
LG.JPドメイン名の創設は、地方公共団体組織認証基盤(LGPKI)の整備などと合わせて、地方公共団体が提供する電子行政サービスの信頼性を確保し、住民・企業の皆様が安心してサービスを受けられるようにすることを目的としています。
LG.JPドメイン名について - 財団法人 地方自治情報センター(LASDEC) より引用
以下は、LG.JPドメイン名を活用している地方公共団体の例です。
LG.JPドメイン名の登録開始が2002年10月で、それから10年以上を経ていますので、そろそろ地方公共団体は地域型JPドメイン名からLG.JPドメイン名に移行してほしい・・・ということなのでしょう。

まとめ

以前から地域型JPドメイン名の一種として「地方公共団体ドメイン名」というものがあり、地方公共団体の識別ができるドメイン名として今も多数利用されていますが、都道府県型JPが登場したことで、簡単には地方公共団体のドメイン名であることが識別できなくなりました。既にLG.JPドメイン名という識別しやすいドメイン名が用意されているので、できるだけ早くLG.JPドメイン名への移行が望まれます。
住民の立場からは、地方公共団体のサイトを利用して、重要な情報を得る場合や個人情報を入力する場合は、ドメイン名がLG.JPでないサイトについては、本当に地方公共団体のサイトであるか、信頼出来る方法で確認した方がよいでしょう。
例えば、地方自治情報センター(LASDEC)のホームページには、全国自治体マップ検索というページが用意されています。LASDECのサイトはEV SSLを利用しているので、本物であることの確認が容易に行えます。

追記

地域型JPドメイン名と都道府県型JPドメイン名を簡単に区別する方法として、Firefoxを使って閲覧するというものがあります。冒頭の画面キャプチャのアドレスバーを見ていただくと、都道府県型JPドメイン名(1番目の画像)の方はmachida以下が濃くなっていますが、地域型JPドメイン名(2番目の画像)だと、city以下が濃くなっています。これで区別ができますが、一般の方が活用するのは難しいでしょうし、Google ChromeやIEではこの方法は使えません。Firefoxをお使いの方は、試してみてください。

2013年8月8日木曜日

パスワードの定期的変更について徳丸さんに聞いてみた(2)

高橋: こんにちは、高橋です。前回に引き続き、徳丸さんをお招きして、パスワードの定期的変更問題についてお話を伺います。徳丸さん、よろしくお願いします。

徳丸: はい。よろしくお願いします。

高橋: 前回は、「オンライン攻撃に対する予防としてパスワードの定期的変更は意味がない」という結論でしたが、今回は、事後の被害軽減策として、パスワードの定期的変更に意味があるか、というテーマですね。

徳丸: はい。その事後の話ですが、2つの話題があります。まず、前回の続きで、パスワードハッシュ値が漏洩してオフライン攻撃で解読されるまでの時間稼ぎとして、パスワードの定期的変更に意味があるか、次に、パスワードそのものが漏れている場合の緩和策として、定期的変更に意味があるかです。

高橋: それでは、まずハッシュ値が漏洩しているケースについてお願いします。

徳丸: はい。まず、前提として「パスワードを3ヶ月毎に変更する」というポリシーを想定しましょう。3ヶ月に深い意味はありませんが、ありがちな想定です。

高橋: 四半期毎だと、企業人としてもキリがいい感じです。

徳丸: 次に、ハッシュ値の解読に要する時間がどれくらい掛かるかが問題です。これが短過ぎても、長過ぎても、パスワードの定期的変更には意味がありません。

高橋: なぜでしょうか?

徳丸: まず、短すぎる場合、例えば 1週間でハッシュからパスワードが分かるとすると、定期的変更の前にパスワードが悪用される可能性が高いですよね。逆に、解読に30年掛かる場合は、変更しなくても、30年も経てばそのパスワードは使わなくなっている可能性が高いでしょう。

高橋: それでは、ハッシュの解読に1年掛かるくらいに予め想定して、パスワードの保存方法を決めれば良いのではありませんか? そうすると、3ヶ月毎のパスワードの変更がいい感じです。

徳丸: そうはいかないのですよ。まず、ハッシュの解読に 1年掛かると想定しても、攻撃側がマシンの台数を 12倍に増やせば、1ヶ月で終わってしまいます。パスワードの変更が間に合わない可能性が高いです。

高橋: ハッシュの解読は並列処理が容易という話題は、前回にも出てきました。

徳丸: 次に、わざわざ 1年で解読できるように調整する必要もないですよね。1000年でも、1万年でも、うーんと長くすれば、パスワードの定期的変更の必要はないわけですから。

高橋: 前回教えて頂いたソルト、ストレッチングや、長いパスワードの設定により、それが可能になるわけですね。

徳丸: そうです。8文字英数字パスワードのハッシュが、GPUの活用で、 1日で解読できるとしましょう。同じ条件で、英数字記号で12桁のパスワードに変えると、ハッシュの解読にはどれくらい掛かると思いますか?

高橋: 前回のお話では、1000万倍ということでしたね。

徳丸: それは、さまざまな条件を考慮した控え目な(安全側の)数字です。計算してみると、約56億倍掛かります。

高橋: 徳丸さん、さばを読み過ぎ…逆か、控え目過ぎたのではないですか?

徳丸: パスワードに記号を使えるようにした寄与もあり、それが12乗で掛かるので莫大な差になるのです。年で言うと、1500万年掛かる計算です。

高橋: ひゃー、ハードの性能向上や攻撃マシンの台数増強を考慮しても、十分な余裕がありそうですね。

徳丸: そうです。加えて、ソルトやストレッチングの寄与もあり得るわけですが、利用者に目に見える範囲だけでも、これだけの改善ができるわけです。

高橋: なるほど…でも、前回のお話では、まだ8文字英数字のパスワードのサイトが多いというお話でしたよね。

徳丸: そうなんです。例えば、三井住友銀行のネットバンキングでは、「半角4~8桁の英数字」となっています。

高橋: 4桁もありですか!

徳丸: まぁ、4桁パスワードをつけてしまうは利用者の責任としても、上限は緩和して欲しいですね。

高橋: もっとマシな銀行はないですのか?

徳丸: どこも似たり寄ったりですし、実は、三井住友のネットバンキングやめようと思った矢先に、ワンタイムパスワードのトークンを無償化するという英断があったので、引き続き利用しています。

高橋: ワンタイムトークンの無償化はいいですね。

徳丸: そうなんです。前は、月に105円払ってましたから、ありがたいです。

高橋: また、話がそれてしまいました(_ _) 次に、パスワードそのものが漏れてしまった場合の緩和策について教えて下さい。

徳丸: わかりました。この場合重要なことは、「パスワードが漏れた事実を利用者が気づけるか、それはいつか」ということです。

高橋: 時々、個人情報漏洩のニュースやリリースが発表されますが、それのことですか?

徳丸: はい。加えて、利用者がサイトを使っていて気づくこともありますね。

高橋: どんな場合でしょうか?

徳丸: 正しいパスワードを入力しているのにログインできないとか、不正利用(メッセージスパムの送信、意図しない振込…)に気づいたとかですね。

高橋: パスワード漏洩のお知らせがないのに、実際にはパスワードが漏洩しているとすると、サイト側が気づいていないか、気づいているのに隠しているということでしょうか?

徳丸: そういうケースもあり得るとは思いますが、実際に多いのは利用者の不注意でパスワードが漏洩するケースだと思います。

高橋: 具体的に教えて下さい。

徳丸: 一番ありそうなのはフィッシングですね。こちらの記事も参照して下さい。

高橋: なるほど、自分の不注意で漏らしてしまったら、中々気づけないし、サイト側も気づかない場合が多そうです。

徳丸: そうです。最悪の場合、パスワードが漏洩したことに、利用者は永遠に気づかないことになりますね。

高橋: それは困ります。それでは、やはりパスワードの定期的変更が必要なのではありませんか?

徳丸: パスワードの定期的変更は最後の手段として、もっとよい方法がないか考えましょうよ。

高橋: そんな方法がありますか?

徳丸: はい。まず、定期的にログイン履歴を確認するという方法があります。下図は、Googleの最近のアクティビティです。

高橋: 結構詳しい情報が表示されていますね。

徳丸: そうです。これを見て、怪しいログインがあれば、不正ログインの可能性と見てパスワードを変更します。

高橋: ……結局、定期的にチェックして、怪しければパスワードを変更するので、手間はあまり変わらない気がしますが…

徳丸: でも、手間が似たようなものとしても、管理レベルは随分違います。パスワードの定期的変更は、不正アクセスがあるかないか分からない前提で、とにかくパスワードを変更するわけですから。しかし、もっとよい方法もあります。

高橋: なんだ、早くそれを教えて下さい。

徳丸: 2段階認証が使える場合は、2段階認証をぜひ設定しましょう。

高橋: Googleや、facebookやYahoo!で導入されている、6桁数字を追加で入れるあれですか。

徳丸: はい。2段階認証を設定しておけば、フィッシングに関しては十分な対策になります。

高橋: フィッシング以外の原因、例えばサイトが不正アクセスされて情報が漏洩した場合も大丈夫ですか?

徳丸: 大丈夫な場合と大丈夫でない場合があり得ますね。

高橋: 大丈夫でない場合とは?

徳丸: 2段階認証にワンタイム生成アプリを使っている場合、ワンタイムパスワードは秘密のシード(シークレットキー)と時刻からパスワードの数字を生成します。このシードはサイト側でも保存していないとパスワードの照合ができないので、この値まで漏洩したら、第三者がワンタイムパスワードを知り得ることになります。

高橋: そんなことがあり得るのでしょうか?

徳丸: あり得るのかと疑問に思うのはもっともですが、RSAのワンタイムトークンのシードが漏洩して不正アクセスされたという事例があります。IIJの根岸さんが素晴らしい解説記事を書いておられるので、ぜひお読み下さい。

高橋: 2段階認証まで破られる可能性があるとしたら、やはりパスワードは定期的に変更した方がよいのではありませんか?

徳丸: レアなケースだとは思いますが、そこまで心配するのであれば、ログイン履歴の定期的な確認をお勧めしますよ。

高橋: でも、ログイン履歴が確認できないサイトも多いですよ。

徳丸: そこです。どのサイトに対してもログイン履歴を定期的に確認するなんて現実には不可能です。ですが、全てのサイトのパスワードを3ヶ月毎に変更することも、労力が大きすぎます。

高橋: どうすればいいの? と思ってしまいますが。

徳丸: サイトの性質によって、管理レベルを区別することをお勧めします。区別の基準として、サイトに不正ログインできる場合、短期的な攻撃で終わるものと、長期に攻撃が続くものがあります。

高橋: 短期的に攻撃が終わってしまうことがあり得ますか? 攻撃者はいつまでも攻撃したいのでは?

徳丸: 具体的には、メッセージスパム、寸借詐欺、不正な振込、不正な物品購入等は、長期的に攻撃したいと思っても、被害者が直に気づいて、パスワード変更などの処置をしてしまいます。攻撃者側も心得ていて、たとえば預金のありったけを振り込みしてしまいます。

高橋: なるほど、ちびちび攻撃したら、儲けが減るということですね。では、長期に攻撃が続くものとはどのようなものでしょうか?

徳丸: 利用者に気づかれない攻撃としては、情報の漏洩が代表的です。たとえば、メールの盗聴が目的であれば、スパム送信などしないで、じっと静かに盗聴を続けるでしょうね。

高橋: それは怖い! やはりパスワードの定期…

徳丸: (遮って)いや、情報漏洩が心配ということは、秘密情報を扱うサイトということなので、そのようなサイトは少数に絞り、2段階認証やログイン履歴確認ができるサイトを選定することですね。

高橋: あー、ようやく道筋が見えてきたような気がします。秘密情報を扱うサイトは、2段階認証をサポートしたサイトに限定しろ、と。

徳丸: それをお勧めします。

高橋: でも、現時点で2段階認証に対応しているサイトは大抵米国のサービスだから、CIAが傍受しているのではないですか?

徳丸: CIAではなく、国家安全保障局(NSA)ですが、政府関係者ならともかく、民間のメールの中身を一々確認するほど彼らも暇ではない気がしますが、心配であれば、Yahoo!ジャパンなど、日本のサービスで2段階認証に対応しているものもありますよ。

高橋: まぁ、そこはよく考えます。

徳丸: あと、メールに関しては、元々盗聴のリスクがあるものなので、機密性の高いメールはPGPなどで暗号化するほうがよいでしょうね。

高橋: 分かりました。その他のサイトはどうなんでしょうか?

徳丸: オンラインバンキング等も含めて、短期的に被害を受けるサイトは、パスワードの定期的変更では間に合わないので、他の施策をとるのがいいですね。ジャパンネット銀行と三井住友銀行は無料でワンタイムトークンを配っていますし、有料でトークンを配布している銀行もあります。パスワードリスト攻撃の被害の多いネットゲームも、2段階認証に対応しているサイトがあります。

高橋: わかりました。では、そろそろ今回のまとめをいただけますか?

徳丸: はい。先に述べたように、利用者側で警戒が特に必要な状況は、長期にわたって情報が漏洩し続ける事態ですから、そのような秘密情報を預けるサイトはむやみに増やさず、2段階認証に対応した安全性の高いサイトに絞るのがよいでしょう。これができれば、パスワードの定期的変更をすべき理由はなくなります。

高橋: その他のサイトはどうでしょうか?

徳丸: 秘密情報の有無に関わらず、攻撃者にとって金銭的価値の高いサイト、オンライン銀行やクレジットカードを扱うECサイト等は、短期集中的に狙われやすいので、パスワードの定期的変更は意味がありませんが、それ以外で、パスワードの文字数が多く設定できるとか、パスワードリセットの機能がちゃんとしているなど、セキュリティ施策のしっかりしているサイトを選んだ方がいいですね。

高橋: ちょっと素人には難しい判断ですね。

徳丸: 機会があれば別の記事に書きましょうかね。

高橋: 結局、パスワードの定期的変更は意味がないという結論なんですか?

徳丸: そう言いたいところですが、理論的には、次の条件を満たすサイトを使わないといけない場合は、パスワードの定期的変更が効果がなくはない、ということになります。

高橋: 微妙な言い方ですね。どのような条件ですか?

徳丸: はい。箇条書きにしますね。以下の3条件を満たす場合、パスワードの定期的変更が意味がある可能性があります。

  • 長期に情報が漏洩し続けると被害の拡大するメール、メッセージング、ストレージなどのサービスである
  • 2段階認証、リスクベース認証、ログイン履歴確認画面などのセキュリティ施策がない
  • 情報漏洩があっても、サイトからアナウンスされない可能性がある or フィッシング被害にあう心配がある

高橋: フィッシングは利用者の責任ですが、他は残念な感じがしますね。しかし、このようなサイトを使う場合は、パスワードの定期的変更で安全性が高まるのですか?

徳丸: いや、攻撃を受けると、過去のデータは全て漏洩した上で、次のパスワード変更までは情報が漏洩し続けます。

高橋: 次回の「定期的変更」で漏洩が止まる、と。

徳丸: いや、それも確実なものではありません。

高橋: あっ、そうなですか?

徳丸: はい。情報が漏洩してもサイトからアナウンスがないということは、サイト側も気づかない「完全犯罪」の可能性が高いわけです。この場合は、攻撃者が再度攻撃すると、パスワードを変更していても防御できません。

高橋: なんか、残念な上に、パスワードを変更しても、攻撃を断ち切れる訳ではないのですか…

徳丸: それが現実です。フィッシングの方はパスワードの変更で情報流出が確実に止まりますが、フィッシング対策という点では、2段階認証なら事後対策だけでなく、侵入も止められるわけですから、2段階認証が使えるならぜひ使うべきです。

高橋: わかりました。ところで、今まで、住所、氏名、メールアドレス、電話番号などの個人情報の話が出てこなかったと思いますが、これらはどうですか?

徳丸: 個人情報は侵入された時点で漏洩しているはずですので、諦めてください。パスワードの定期的変更による被害緩和は、新しい情報までもが漏洩し続けないようにする話です。

高橋: つらいですね(>_<) では、最後に、利用者のとるべきセキュリティ施策についてまとめていただけますか?

徳丸: はい、これも箇条書きにしましょう。

  • パスワードはできれば12文字以上で、できるだけ長く設定する
  • パスワードは他のサイトとは別のものに設定する(パスワードリスト攻撃対策)
  • 秘密情報を扱うサービスは、少数に絞り、以下のセキュリティ施策のあるサイトを可能な限り選択する
    • 2段階認証に対応している(強く推奨)
    • リスクベース認証、ログイン履歴の確認画面(推奨)
    • 長いパスワードを設定できること(12文字以上推奨、長いほど安全)
  • 秘密情報を扱うサービスは、定期的にログイン履歴を確認する
  • サイトやWebニュースなどで、サイトのパスワード変更の案内が来た場合は、すみやかにパスワードを変更する
  • マルウェア対策として以下を実施する
    • 端末のOSやソフトウェアを常に最新の状態に保つ
    • ウイルス対策ソフトを導入してパターンファイルを最新に保つ
    • ブラウザのプラグインやアドオンは最低現に絞り最新に保つ

高橋: ありがとうございました。これで、パスワードの定期的変更に関する徳丸さんへのインタビューは終わりです。みなさま、ごきげんよう~


※注: ここに登場する人物はすべて架空の人物です。文責は徳丸浩にあります。

2013年8月5日月曜日

パスワードの定期的変更について徳丸さんに聞いてみた(1)

高橋: こんにちは、高橋です。今日は徳丸さんをお招きして、パスワードの定期的変更問題についてお話を伺います。徳丸さん、よろしくお願いします。

徳丸: 徳丸です。よろしくお願いします。

高橋: まず、お伺いしたいことですが、パスワードを定期的に変更すべしという根拠には、どのようなものがあるのでしょうか?

徳丸: 大きく分けて2つの理由が挙げられていると思います。一つは、パスワードを定期的に変更すると、パスワードを破って侵入する攻撃の予防になるというもの、すなわち事前の予防策です。もう一つは、パスワードが漏洩した際に、被害を軽減できるというもので、事後の緩和策ということですね。

高橋: もう少し詳しくお願いします。

徳丸: まず、「事前」の方ですが、オンライン攻撃とオフライン攻撃があります。

高橋: オンライン攻撃とはどのようなものでしょうか?

徳丸: オンライン攻撃は、ネット経由でパスワードを順に試すことですね。文字通り片っ端から順に試すブルートフォース攻撃、辞書攻撃、リバースブルートフォース攻撃、パスワードリスト攻撃などがあります。このうち、ブルートフォース攻撃はオンラインでは現実的ではありません。

高橋: なぜでしょうか? コンピュータが高速になったので大量のパスワードが試せるようになったという記事を読みましたが。

徳丸: オンラインのパスワード攻撃の速度は、攻撃側端末の性能ではなく、攻撃対象サイトの性能に依存します。しょぼいサイトなら1秒間に1個のパスワードしか試せないが、高負荷に耐えるサイトでは、1秒間に1万個のパスワードを試せるかもしれません。

高橋: 「バルス」のようなものでしょうか?

徳丸: そうそう、バルス…先日のラピュタの放映では、Twitterは14万3199バルス/秒を達成したそうですね…同様にパスワードも秒間10万個試せる…とは限らないのですよ

高橋: なぜでしょうか?

徳丸: 対策しているからですよ。Twitterは、なりすましの価値の高いサイトなので、さまざまななりすまし対策(参考)をとっています。私は試していませんが、パスワード試行も対策していると思います。

高橋: もう少し具体的に教えてください。

徳丸: 例えば、同じIDで続けてパスワードを間違えると、そのアカウントを一時的にロックする「アカウントロック」という方法があります。10回連続してパスワードを間違えると30分ロックするという具合です。10万個のパスワードを試すには約5000時間掛かりますから、約208日掛かります。

高橋: 208日攻撃され続けると怖いですね。

徳丸: さすがにその前に遮断するでしょう。それと、10万個のパスワードは辞書攻撃としては十分ですが、ブルートフォース(総当たり)としてはまったく不十分です。

高橋: …と、おっしゃいますと?

徳丸: twitterは最短6文字のパスワードがつけられますが、パスワードの文字種は制限していないので、6文字に限定しても、95^6 = 約7350億通りのパスワードがあり得ます。先のアカウントロックがある条件で総当たりするには、約420万年掛かります。

高橋: なら、辞書攻撃で攻めてくるのでは?

徳丸: twitterは独自の辞書をもっていて「password」のようなありきたりの単語はパスワードに設定することができないので、辞書攻撃は難しいでしょう。

高橋: そうですか…しかし、パスワードの定期的変更から話がそれていませんか?

徳丸: そうでした。辞書攻撃が短期間に終わるのであれば、パスワードを変更する前に攻撃が終わるので、定期的変更は意味がありませんね。

高橋: では、パスワードの定期的変更の期間、例えば3ヶ月をまたいで攻撃する場合はどうでしょうか?

徳丸: いくらなんでも、サイト側で攻撃を検知して、遮断などの処置をとって欲しいですね。あるいは当該のユーザーに「パスワードの辞書攻撃が来ているので対処して欲しい」と連絡してくれてもいいでしょう。

高橋: その場合もパスワードを変更するのではないですか?

徳丸: そうです。しかし、「定期的に」変更するのではなく、「攻撃されている」ことをトリガーとして変更するので、全然違います。辞書攻撃が来ていることが分かれば、辞書に載っていない、長い文字列をパスワードに設定すれば、辞書攻撃は怖くありません。

高橋: サイト側で対策を取っていない場合、パスワードの定期的変更は意味がありませんか?

徳丸: それが、意味がないのですよ。パスワードを定期的に変更すべしという人の中には、パスワードを変更すると「ひらりと」パスワード攻撃を避けることができるという人がいますが、それは違います。

高橋: 違うのですか?

徳丸: はい。攻撃側も防御側も相手の手の内がわからない状態なので、「たまたま攻撃をかわせる」可能性もあれば、「パスワードを変更したら、たまたま攻撃に掛かってしまう」場合もあります。闇夜にむやみやたらに鉄砲を撃ってくるのを避ける状況を想像してみて下さい。むやみによけても、よけた先で弾に当たるかもしれません。

高橋: でも、しらみつぶしに撃ってくる相手はよけたくなりますね。

徳丸: そうです。なので、「しらみつぶし」攻撃には、アカウントロックその他の施策で対策することが重要です。また、利用者側でも、辞書に載っているような単語を避けて、長く複雑なパスワードをつければ辞書攻撃は回避できます。

高橋: 辞書攻撃以外の方法に対してはどうでしょうか?

徳丸: リバースブルートフォース攻撃に対しても、パスワードの定期的変更は意味がないですね。リバースブルートフォース攻撃はパスワードを固定してIDの方を変えていくので、1人のIDに対しては攻撃は1度だけです。1つのパスワードを試し終わったら次のパスワードに進みますが、辞書攻撃と同じ理由で、パスワードを定期的に変更しても効果がありません。リバースブルートフォース攻撃も、辞書攻撃同様、パスワードを複雑なものにすることで防げます。

高橋: パスワードリスト攻撃はどうでしょうか?

徳丸: パスワードリスト攻撃に対しては、他のサイトとは別のパスワードをつけることが必要十分な対策で、パスワードを定期的に変更する必要はありません。

高橋: わかりました。次に、オフライン攻撃について教えて下さい。

徳丸: パスワードのオフライン攻撃というのは、保護された形式のパスワードファイルが外部に漏れて、それを解読する行為を指します。

高橋: パスワードの保護というと、暗号化でしょうか?

徳丸: 暗号化する場合もありますが、パスワードの場合は、ハッシュを用いることが多いですね。

高橋: ハッシュというと、MD5とかSHA-1のことですか?

徳丸: そうそう。パスワードの保護用に開発されたハッシュ関数もありますが、MD5やSHA-1のような汎用的なハッシュ関数を用いる場合も多いですね。

高橋: ハッシュでパスワードを保存すると、元に戻せないから保護できるというのは分かりますが、サイト運営者がパスワードを照合する時に困りませんか?

徳丸: パスワード照合の場合も、ユーザが入力したパスワードからハッシュ値を求めて、会員DBに保存されたパスワードハッシュ値と比較します。ハッシュ値同士で照合する訳です。

高橋: そうか、ハッシュなら絶対に元のパスワードに戻される心配はありませんね!

徳丸: それが、そうでもないのです。

高橋: なぜでしょうか? わかった! MD5の脆弱性で元に戻せるのですね! なら、脆弱なハッシュ関数を使わなければよいのでは?

徳丸: そうではありません。MD5には一部弱点が見つかっていますが、ハッシュ値から元の文字列(平文)が戻せるほどには弱くなって(危殆化して)はいません。

高橋: それではなぜパスワードが分かるのでしょうか?

徳丸: 総当たり(ブルートフォース)攻撃を使います。パスワードの文字種や文字数は限られているので、総当たりでハッシュ値を求めていけば、いつかはハッシュ値が一致するパスワードが見つかります。

高橋: でも、お高い(時間が掛かる)んでしょう?

徳丸: そうでもないのです。まず、レインボーテーブルと言って予め全てのハッシュ値を計算したものを圧縮したファイルを用いて高速にハッシュ値から元パスワードを算出する方法が考案されました。

高橋: レインボーテーブルは聞いたことがあります。

徳丸: 次に、GPUというグラフィック用のプロセッサが高速演算できることに着目して、ハッシュ値の高速演算をするようになりました。これは約2年前の記事ですが、当時でも1秒間にMD5ハッシュが20億回計算できるとしています。

高橋: 「また上野宣か」で有名な上野さんの記事ですね。

徳丸: 8桁英数字のパスワードのパターンは218兆通りですから、1秒間に20億回計算できると、約11万秒、すなわち30時間ほどですべてのパターンを試行できることになりますね。

高橋: 丸1日ちょっとですか。これだとパスワードを毎日変更しないと駄目ですね。

徳丸: 今ならもっと高速だから、毎日パスワードを変更しても駄目でしょう。

高橋: 困りましたね。どうすればいいですか?

徳丸: ソルトとストレッチングというものを使います。

高橋: ソルトとはなんでしょうか?

徳丸: ソルトは、ハッシュ値を計算する前のパスワードにつけてやる短い文字列です。パスワードに「塩をまぶす」ようなニュアンスからソルト(salt)と命名されました。ソルトはユーザ毎に異なるように、乱数等を使って生成します。

高橋: ソルトがあると、なぜ良いのでしょうか?

徳丸: LinkedInの事例で説明しましょう。2012年の6月にLinkedInから約650万件のパスワードが流出しました。パスワードはSHA-1ハッシュの形で保存されていましたが、約1週間で540万件の元パスワードを「解読」したという人物が現れました。

高橋: 1週間で540万件というと、ものすごく高速ですね。

徳丸: そうでもないのです。単純なハッシュだと、パスワードが同じであれば全ての利用者でハッシュ値も同じになりますから、利用者が何人でも総当たりの手間は変わりません。

高橋: ソルトがあると違うのですか?

徳丸: はい。ソルトは利用者毎に異なるので、ハッシュ値を求める前に、どのソルトを使うか決めなければなりません。つまり、1人ずつハッシュ値を求めないといけないので、LinkedInの場合で言うと、手間が650万倍になります。

高橋: 650万倍! それはすごいですね!

徳丸: LinkedInが大規模なサイトだからで、利用者が100人のサイトだったら、100倍止まりですが。

高橋: 1日が100日に増えるだけだと、パスワードを定期的に変更したくなりませんか?

徳丸: いや、それもあるのですが、LinkedInの場合でも全員が安心という訳ではありません。最初の1人は1週間程度で解読されてしまうわけですから。

高橋: オバマ大統領もLinkedInに登録されているようですから、そういう著名人は真っ先に解読されそうですね。

徳丸: そうなんです。このため、ストレッチングという方法を使う場合があります。

高橋: ストレッチングとは何でしょうか?

徳丸: ストレッチングとは、ハッシュ計算を何回も繰り返すことです。例えば1万回ハッシュ値の計算を繰り返したものをパスワードのハッシュ値として保存します。

高橋: 1万回も計算するとCPU資源を浪費しそうですね。

徳丸: そうです。しかし、攻撃側も1万倍遅くなりますから、1日強で解析できたものが1万日、すなわち約27年かかることになります。

高橋: 27年掛かれば大丈夫そうですが、攻撃側に対抗策はないのですか?

徳丸: あります。ハッシュ値の計算は並列処理が容易なので、マシンの台数を27倍にすれば、1年で計算が終わることになります。

高橋: 1年で解読されてしまったら、パスワードを定期的に変更する動機になりますね。

徳丸: オバマ大統領ならともかく、あなたのパスワードを知るためにモンスターマシンを1年間占有させるかという疑問がありますが、心配なら利用者側にも対抗策がありますよ。

高橋: 心配なので、ぜひ教えてください!

徳丸: パスワードの桁数を増やすことです。パスワードを1桁増やすとパスワードのパターン数は60倍~90倍程度になりますから、8桁のパスワードではなく12桁のパスワードを使うようにすれば、ハッシュの解読の時間は1千万倍以上掛かります。

高橋: それは良いことを教わりました。今後は、全てのサイトで12桁以上のパスワードをつけます!

徳丸: でも、サイト側の制限で、今でも8桁パスワードまでというところが多いんですけどね。

高橋: …既に長くなりましたので、本日はこれくらいにして、ここまでのまとめをいただけますか?

徳丸: はい。結局「事前の予防策」として、オンライン攻撃に対しては「パスワードの定期的変更」は意味がないということです。オフライン攻撃に対しては、サイト側のパスワードハッシュでの保存やソルト、ストレッチングなどの施策、利用者側での長いパスワードの設定で十分な強度が得られますが、パスワードの保存方法は利用者には分からないので、不安は残りますね。

高橋: では、パスワードの定期的変更に意味があるということでしょうか?

徳丸: そうとは限りません。オフライン攻撃が行われているという状況は、既にパスワードのハッシュ値が洩れていると言うことですから、事後対処という意味もあります。既に長くなりましので、「事後の緩和策」としてのパスワード定期的変更と、結局パスワードは定期的に変更しないといけないのかどうかについては、次回に説明することにしましょうか。

高橋: そうですね。それでは、皆様、次回をお楽しみにぃ! 徳丸さん、ありがとうございました~


※注: ここに登場する人物はすべて架空の人物です。文責は徳丸浩にあります。

続きはこちら: パスワードの定期的変更について徳丸さんに聞いてみた(2)

フォロワー