本文はSoftware Design 2013年7月号に寄稿した文章の一部をWeb用に編集したものです。

すずきひろのぶ
suzuki.hironobu -at- gmail -dot- com

はじめに

パスワード管理の方法と、パスワードを入手された時の問題点を整理してみましょう。

その前に、パスワードに123456やpasswordといったものやアカウント名adminでパスワードがadminといったものを使っている「これはひどい」といいたくなるパスワードでは、さしたる事前の準備も必要なく、いくつか試せばいいので、いくらパスワードの管理をシステム側で頑張っても無理です。

これはさすがに、ウカツなパスワードとしか呼びようがありませんが、これはユーザだけが悪いわけではなく、システムがこのようなパスワードを許容すること自体が、システムの欠陥だと私は思います。最近のシステムではユーザがパスワードを選ぶ際に一定の強度を満たしていない場合は警告を出したり受け付けないといったものも多く、ずいぶんと状況は改善されつつあります。

ある程度の複雑さをもったパスワードに関しては、これはパスワード管理ファイルをサイトから流出させ、専用のコンピュータを用意してパスワードを見つける処理を行うというのが前提となります。 2012年に発生した45万件のパスワードを流出させたYahooのケース2013年に発生した3,800万件のパスワードを流出させたAdobeのケースなどがこれにあたります。

以下に3つのパスワード管理のパターンを説明し、次に、どのような方法でパスワードを見つけていくかの説明を加えます。

パスワードを防御なしに管理

パスワード認証というと、ユーザからの入力の文字列と、既に登録しているパスワードの文字列を突き合わせることだと思っている人も意外といるのではないかと思います。

簡単に実装することができますが、ただし、このパスワードファイルが外部に流出した時点で、サービスの存続にかかわるレベルで、システム全体のユーザ認証が崩壊します。なぜならば、そのままの形ですべてのパスワードを利用することが出来るからです。

ファイルへのアクセスをコントロールすることで安全性を保っていると理解してしまう人がいるでしょうが、逆をいえば、それだけしか保護をしておらず、情報流出する可能性の前提に立っていません。潜在的に1つのエラーがシステム全体をカタストロフな状態に導く可能性がある脆弱な状態におかれています。

このシステムは、大きな問題をはらんでいるのは、改めて強調しなくとも多くの方には理解されているだろうと思います。その一方で、このようなシステムは、そんなに多くはないだろうと楽観的に考えるかも知れません。でも、パスワードを忘れたときに親切にも元々のパスワードを教えてくれるタイプのシステムは、まわりを見渡せばけっこうあるはずです。

  • 利点: パスワードを忘れたときに、パスワードを教えることができる。
  • 欠点: パスワードファイルが流出するとユーザ認証は壊滅的なダメージとなる。
  • 一方向性ハッシュ関数を導入する

    一方向性ハッシュ関数とは、値xに対しハッシュ関数Hを用いて計算した値H(x)から、逆をたどってxを見つけることは極めて困難であるという性質を持つ関数です。一方向性ハッシュ関数にはSHA256、SHA512といったものだけではなく、暗号化関数を使ったメッセージ認証コードなども同様に使えます。たとえば古典的UNIXのパスワード生成にはDES暗号を使っているDES-CBC-MACというメッセージ認証コード法が使われています。

    よく「パスワードを暗号化」するという表現を使うので、暗号化するなら、復号もできるだろうと類推してしまいそうになりますが、これは一方向にしか計算できません。

    パスワードを入力し、それを一方向性ハッシュ関数で計算した値を、事前に登録しておいた一方向性ハッシュ関数で計算した値と比較します。たとえばWindowsXPなどで使っていたLMハッシュ(LAN Manager hash)は、この方式です。

    生の文字列を持っている先ほどの方法よりは格段に安全性は上がりますが、例えば同じ入力のものは同じ出力値を持ってしまう弱点を持っています。そのため辞書に載っているようなパスワードであれば、事前に処理してハッシュ値辞書を作成することが出来きます。つまり、辞書攻撃には極めて脆弱なパスワードシステムだといえます。

    辞書を作るのに膨大な時間がかかると考えるかも知れませんが、英数字8文字のすべての文字の組み合わせのための逆引き辞書を 作るのに秋葉原で手に入る機材レベルで30時間もあれば十分作成できます。しかもophcrackサイトでは既にWindows XPやVistaのための辞書テーブルが既に用意されており、それを使えば検索成功率99パーセントだそうです。

    先ほどの紹介したAdobeの流出したパスワード情報は、このタイプで、さらに悪いことには、ユーザが入力するパスワードのヒント情報も入っており、そこからまず類推可能なパスワードを探し当て、次に同じパスワードを持つユーザをピックアップしてゆくということが出来てしまうという、極めて憂慮すべきシステムでした。

  • 利点: パスワードを見つけるためにはパスワード解析をする必要がある。
  • 欠点: 同じパスワードは同じ出力なので事前に辞書を作ることが可能。
  • ソルトを加えたパスワード管理

    一方向性ハッシュ関数だけだと逆引きの攻撃辞書が使えるので、それを困難にするようにソルト(salt)と呼ばれる、ユーザ毎に異なるランダムな値を加えたのちに一方向性ハッシュ関数に入力する方法をとります。

    このソルトは隠さなくてもかまいません。長ければながいほど逆引きの攻撃辞書のサイズが巨大になります。ソルトはランダムデータですが、そんなに大きなものは必要なく70年代では12ビット程度が使われており、もし将来的にも使うと考えるとしても64ビット(8バイト)程度あれば十分でしょう。

    古典的なUNIXのパスワード処理法では、さらに一方向性ハッシュ関数を複数回呼び出し計算時間をより多くかけさせるという手法を使っています。ただし一度に多数のユーザの対応をしなければならないようなシステム、例えばウェブサイトのパスワード認証などで行うのは、認証するサーバー側に負荷がかかりすぎる可能性があるので、本当にこの手法を選択すべきかどうかは熟慮が必要です。基本的には、複雑さを増すにはパスワードに使える文字種類を多くしたり、文字数を増やすことが重要です。

    これでやっと普通のパスワード管理の基準を満たすことができます。ここでの普通っていうのは、ただ単純に数として多くあるいう意味ではなく、理想に近い意味での普通です。 (cf. Dream Fighter by Y. Nakata)

  • 利点: 事前のパスワード解析を無効にできる。
  • 欠点: - (必要な基準は満たしている)。
  • さいごに:安全なパスワードシステムだけれども

    ここではパスワードシステムの仕組みの概要を説明したのですが、どうしてもパスワード方式はユーザの利用方法に問題があれば、どんなにシステム側で努力しようとも意味がありません。

    よく「安全なパスワードを運用しましょう」という説明には「むずかしい並びのパスワード」「長いパスワード」「頻繁に変更するパスワード」という条件が推奨されています。が、しかし、次のポイントを指摘したいと思います。

  • むずかしい並びのパスワード --- 人が考えるとバイアスが入るので安全なランダム性を確保できない。
  • 長いパスワード --- 人間の記憶能力を過大評価している。結果として思い出しやすいパスワードを選択するバイアスがかかる。
  • 頻繁に変更するパスワード --- 一番目と二番目の問題を何度も繰り返すことになり、結果として、覚えやすいパスワードか、同じパスワードを繰り返し使われることにつながる可能性が大きい。
  • 私は、銀行やクレジットカード会社のような偽ってログインされると被害が大きいサイトでは、ネットワーク経由でのパスワードログインはできるだけ回避し、ユーザのパスワード選択に依存しないワンタイム・パスワード・トークンのような機械式か、あるいは公開鍵方式を利用したユーザ認証方法を積極的に取り入れるべきだと思っています。


    $Id: index.html,v 1.11 2013/11/07 15:11:00 hironobu Exp hironobu $