パスワードの保存方法について

343 views
Skip to first unread message

lets_skeptic

unread,
Aug 30, 2011, 9:51:59 PM8/30/11
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
こんにちは。

 パスワードの保存方法についての話題です。私の頭の整理のために余計なことも書きます。


【私の理解】
 現在、標準的な方法として提案されているのは「ランダムソルト+ハッシュ化+ストレッチング」。

 レインボーテーブルへの耐性を付けるために、ランダムソルトを用いる。
 ソルト値とハッシュ化されたパスワードを同一レコード内に保存している場合を想定すると、SQLインジェクション一発で両方の値を取得できる。する
と、ブルートフォースへの耐性はない。そこで、ブルートフォースでの解析スピードを落とすために提案されているのが、ストレッチングである。

【私の疑問】
 ブルートフォース対策を考えるのならば、単純にソースコード内に固定ソルトを埋め込み(ランダムソルト+固定ソルト+ハッシュ化)で対応できるのでは
ないか。
 又は、ソルトを分割して元パスワードの途中に埋め込んだ状態でハッシュ化するなど(ソルトがどう元パスワードに埋め込まれているかわからないので解析
の計算量が増える)。

【暗黙の前提?】
 攻撃者がパスワード保存部分のソースコードを保有しているという前提があるということか(ストレッチングの代替案の場合はソースコードが見れる攻撃者
には無意味なので)。

徳丸浩

unread,
Aug 31, 2011, 10:38:37 AM8/31/11
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
こんにちは。質問ありがとうございます。

パスワードのハッシュ保存の目的は、パスワード情報がDBなどから漏洩した後にパスワードそのものを知られないようにすることです。
このため、外部から侵入されたことを前提として考える必要があります。

仮に、なんらかの理由で、侵入の経路をSQLインジェクションに限ってよい場合は、(SQLインジェクションでファイルが参照できない場合)ソースコー
ドは漏洩しないことが保証されます。この前提であれば、ソースコードに秘密情報を書いていても、外部には漏洩しません。そのため、ソルトの一部として固
定の秘密文字列を書いておけば、パスワードを平文に戻すことは、相当困難になると考えられます。

しかし、ここで2つのことを考えておく必要があります。

まず、ソースコードに秘密情報を記述しても漏洩しないことが保証されるのであれば、秘密鍵を用いた暗号化もパスワード保護の候補になる、ということで
す。PCI-DSS2.0の基準 8.4項では、以下のように記述されており、パスワード情報をハッシュで保存することは要求していません。

8.4 強力な暗号化を使用して、すべてのシステムコンポーネントでの伝送および保存中のすべてのパスワードを読み取り不能にする

第2に、そもそも侵入されてもソースコードは安全だという前提をおいてよいかという問題です。こちらの方が現実的な問題だと思います。
たとえば、ソニーのPSNの事件では、外部からの侵入により管理者権限を奪取されたと発表されています。そのような状況では、ソースコードにアクセスさ
れる可能性は当然ありますし、Javaなどソースコードがサーバー上にないばあいでも逆コンパイルなどの手法により、ソース情報を復元できる可能性があ
ります。管理者権限が奪取された状態では、ソースコードや暗号鍵にもアクセスされた可能性は想定しなければならないと考えます。

# このため、クレジットカード情報が暗号化されていたというソニーの発表に対しても、安全性に対する懸念は残るわけです。

このため、ハッシュによるパスワード保護では、アルゴリズムも、ハッシュ値も、ソルトも、ストレッチング回数もすべて漏洩しても、なお平文パスワードが
保護できることが求められるわけです。ストレッチングはそのための工夫であると考えられます。

しかし、ストレッチングには以下のようなジレンマもあります。

・辞書に載っているようなパスワードを使っている場合は、ストレッチングしていても辞書攻撃により平文パスワードを解読される
・非常に安全なパスワードを使っている場合は、ストレッチングなしでも平文パスワードを解読されるリスクは低い

それでは、ストレッチングが有効なパスワードとはどんなパスワードかというと、例えば、8文字英数字で、規則性のないパスワードが該当すると考えます。
現状のWebアプリケーションでは、8文字までの英数字という仕様は非常に一般的です。たとえば、三井住友銀行のネットバンクでは、「半角英数字4桁~
8桁」という仕様です。この程度の複雑性ならば、ストレッチングの保護が必要ではないかと考えます。

つまり、ストレッチングというのは、ソースコード(アルゴリズムや鍵情報)などが漏洩するという前提の元に、現在一般的なパスワード仕様(8文字英数字
など)に対して、パスワードを少しでも安全に保護する(絶対確実ではない)ためのものであると考えます。

lets_skeptic

unread,
Sep 1, 2011, 9:15:48 PM9/1/11
to 「体系的に学ぶ 安全なWebアプリケーションの作り方」サポートML
こんにちは。
詳しく丁寧な解説ありがとうございます。

なるほど、確かにサーバーのルートを取られるとか、逆コンパイルなどまで考慮すると、
ソースコード中に秘密情報を埋め込んでも、ちょっと解析の手間が増えるだけということになりますね。
ストレッチングの有効性が理解できました。

最終的には元パスワードの強度が問題というのにも同意です。
ところで、パスワードの最大文字数がごく小さく設定(8文字以内とか)されているWebサービスが沢山あるのですが、
あれには合理的な理由があるのでしょうか。
パスフレーズ的なものを許容するため、最低50文字程度の入力は許容するルールがあっても良いと考えています。
私は、ソルト付ハッシュ化に加えてパスワードの文字数制限を大きくとるというのも常識になって欲しいと考えています。
Reply all
Reply to author
Forward
0 new messages