この文書は2016年以降更新されていません

パスワードの保存に関するチートシート

OWASP 作成
ジャンプ先: 移動検索
Cheatsheets-header.jpg

最終改訂日 (yy/mm/dd): 2015/11/16

はじめに

マスコミでは毎日のようにパスワードの大量盗難が報じられています。パスワード盗難に関するマスコミ報道では、パスワードの保存方式とその弱点、および大量の資格情報の漏えいが指摘されており、これは多数の Web サイトやさまざまなアプリケーションに影響する深刻な問題です。この資料では、パスワード、秘密の質問の回答、および類似の資格情報を適切に保存するためのガイダンスを提供します。適切な保存は、資格情報の盗難、漏えい、悪用の防止に役立ちます。 情報システムでは、パスワードやその他の資格情報がさまざまな保護形式で保存されます。しかし、一般的な脆弱性が原因で、SQL インジェクションなどの攻撃ベクトルによる、保護されたパスワードの盗犯が発生しています。また、ログ、ダンプ、バックアップなどから、保護されたパスワードが盗まれることもあります。

ここに示すガイダンスの中には、保存された資格情報を盗難から守るためのものも含まれていますが、ガイダンス全体としては資格情報の漏えい防止を主眼としています。つまり、このガイダンスでは、保護された資格情報が脅威による盗難にあった場合に、ユーザーの資格情報が漏えいしたり、システムアクセスを許したりしないような設計づくりを支援します。このトピックの詳細については、「Secure Password Storage Threat Model」(http://goo.gl/Spvzs) を参照してください。

ガイダンス

資格情報の文字セットを制限しない、資格情報の最大長を長く設定する

一部の組織では、SQL インジェクション、クロスサイトスクリプティング、コマンドインジェクション、その他の形式のインジェクション攻撃を阻止できないために、システムで許容する 1) 特殊文字の種類と 2) 資格情報の長さを制限しています。これらの制限は、意図は正しいものの、ブルートフォースのような単純な攻撃を助長してしまいます。

短いパスワードや長さゼロのパスワードを許可しないでください。また、資格情報の入力または保存に対して文字セット (エンコード) の制限を適用しないでください。インジェクション攻撃のリスクを排除するために、エンコード、エスケープ、マスク、完全な省略などのベストプラクティスを引き続き適用してください。

長いパスワードの適度な長さは 160 文字です。非常に長いパスワードのポリシーは、場合によっては DoS 攻撃を招くおそれがあります [1]

暗号強度の高い資格情報固有の salt を使用する

salt とは、固定長で暗号強度の高いランダム値です。salt の後ろに資格情報データを追加し、これを保護関数の入力として使用します。次のように、 salt に追加された保護形式で保存します。

[保護形式] = [ salt ] + protect([保護関数], [ salt ] + [資格情報]);

資格情報固有の salt を適切に実装するには、以下の慣行に従ってください。

  • 保存する資格情報の作成時に資格情報ごとに固有の salt を生成します (ユーザーごとやシステムごとではなく)。
  • 暗号強度の高いランダムな [*3] データを使用します。
  • ストレージが許す限り、32 ビットまたは 64 ビットの salt を使用します (実際のサイズは保護関数に依存します)。
  • 暗号化スキームのセキュリティは、salt の秘匿や分割、あるいは隠蔽には依存しません。

salt には次の 2 つの目的があります。1) 保護形式から 2 つの同一の資格情報が暴かれないように防止する、2) 資格情報の複雑度に頼ることなく、保護関数に与えるエントロピーを高める。この 2 番目の目的は、個別の資格情報に対する事前計算ルックアップ攻撃 [*2] と、母集団に対する時間ベース攻撃とを困難にすることを意図しています。

実行不可能な検証を攻撃者に課す

保存された資格情報の防護に使用する関数は、攻撃者と防御者の検証のバランスをとる必要があります。防御者は、ピーク使用時におけるユーザーの資格情報の検証に妥当な応答時間を必要とします。しかし、<資格情報> → <保護形式> のマッピングに要する時間は、脅威のハードウェア性能 (GPU、FPGA) と技術能力 (ディクショナリベース、ブルートフォースなど) に勝っていることが不可欠です。

これには次の 2 つの手法が役立ちますが、どちらも完全ではありません。

適応型の一方向性関数を使用する

適応型の一方向性関数は、一方向 (不可逆) の変換を計算します。それぞれの関数で "ワークファクター" を設定できます。不可逆性の実現とワークファクター (時間、スペース、並列処理など) の調整に使用される基礎メカニズムは関数によって異なりますが、ここでは重要でありません。

次のいずれかを選択します。

  • PBKDF2 [*4]: 多くのプラットフォームで FIPS 認証またはエンタープライズサポートが必要な場合はこれを選択します。
  • scrypt [*5]: ハードウェアで加速されたあらゆる攻撃を阻止する必要があるが、サポートが不要な場合はこれを選択します。
  • bcrypt: PBKDF2 または scrypt をサポートできない場合はこれを選択します。

protect() の疑似コードの例を次に示します。

return [ salt ] + pbkdf2([ salt ], [資格情報], c=10000);

設計者は、適応型の一方向性関数を選択して protect() を実装します。これらの関数は、実行するハッシュ関数ではなくコストに応じて (直線的または指数関数的に) 設定できます。防御者は、脅威のハードウェア性能の向上に合わせてワークファクターを調整します。攻撃を妨げると同時に、許容できるユーザーエクスペリエンスとスケールを提供するためには、実装するこれらの適応型一方向性関数でワークファクターを調整する必要があります。

また、適応型一方向性関数は、ユーザー数の規模や salt の使用にかかわらず、一般的なディクショナリベースの資格情報 (パスワードが 'password' のユーザー) の逆転を効果的に防止できません。

ワークファクター

リソースには通常限りがあると考えられるので、ワークファクター (コスト) を調整するための一般的な経験則は、ユーザーエクスペリエンスを損ねず、かつ予算を上回るようなハードウェアの追加が必要にならない範囲内で、protect() をできる限り低速で実行するというものです。したがって、登録と認証のケースで protect() の所要時間を最大 1 秒まで許容できるとすれば、ハードウェアでの実行に 1 秒かかるようにコストを調整できます。ユーザーが悪影響を受けるほど遅くてはいけませんが、このように、攻撃者による試行に対してはできる限り悪影響を及ぼすことが必要です。

データの安全性を確保するために推奨される最小の繰り返し回数がありますが、この値は技術の進歩に連れて毎年変わります。有名企業が選んだ繰り返し回数の例として、Apple 社では iTunes パスワードに 10,000 回を使用しています (PBKDF2 を使用) [2](PDF ファイル)。ただし、1 つのワークファクターがあらゆる設計に適合するわけではないと理解することが大切です。重要なのは実際に試してみることです。[*6]

鍵付き関数を使用する

鍵付き関数 (HMAC など) は、プライベート鍵と与えられた入力を使用して一方向の (不可逆な) 変換を計算します。たとえば、HMAC はハッシュ関数の特性 (その速度など) を引き継いでおり、ほぼ瞬時の検証を可能にします。鍵のサイズによって、一般的な資格情報 (つまり、パスワード = 'password') についても、実行不可能なサイズとスペース (またはその一方) の要件が課されます。 保存する資格情報を鍵付き関数で保護する設計者は、次の点に注意します。

  • "サイト全体" で単一の鍵を使用する。
  • ベストプラクティスに基づいて、この鍵をプライベート鍵として保護する。
  • 鍵を資格情報ストアの外に保管する (つまり、データベースに格納しない)。
  • 暗号強度の高い疑似ランダムデータを使用して鍵を生成する。
  • 出力ブロックサイズは気にしない (SHA-256 対 SHA-512)。

protect() の疑似コードの例を次に示します。

return [ salt ] + HMAC-SHA-256([鍵], [ salt ] + [資格情報]);

salt だけを使用した方式よりもセキュリティが向上するかどうかは、適切な鍵の管理にかかっています。

偶発的な漏えいを想定してパスワードの保存を設計する

保護された資格情報が脅威によって頻繁に簡単に盗まれている現状から "Design for failure" (障害の発生を前提とした設計) が求められています。盗難が検知されたら、次のように、漏えいした資格情報データにマーキングし、代替の資格情報検証ワークフローに切り替えることで、オペレーションの継続を資格情報保存スキームでサポートする必要があります。

  1. ユーザーのアカウントを保護します。
    1. 2 要素認証や秘密の質問なしのログインを禁止することで、認証のショートカットを無効にします。
    2. ユーザーアカウントの変更 (秘密の質問の編集、アカウントの多要素認証設定の変更など) を禁止します。
  2. 新しい保護スキームをロードして使用します。
    1. 新しい (より強度の高い) protect(credential) 関数をロードします。
    2. バージョン情報をフォームに含めて保存します。
    3. ユーザーが資格情報をリセットするまで、'汚染' / '漏えい' ビットを設定しておきます。
    4. 鍵をローテーションするか、保護関数のパラメーター (繰り返し回数) を調整するか、この両方を行います。
    5. スキームのバージョン番号を上げます。
  3. ユーザーがログインしたら、次のことを行います。
    1. 資格情報を、保存されている (古いまたは新しい) バージョンに基づいて検証します。古いバージョンの場合は、第 2 の要素か秘密の回答を要求します。
    2. ユーザーに資格情報の変更を促し、謝罪し、アウトオブバウンド方式の確認を行います。
    3. ユーザーが正常にログインしたら、保存されている資格情報を新しいスキームに変換します。

参考資料

Authors and Primary Editors

John Steven - john.steven[at]owasp.org (author)
Jim Manico - jim[at]owasp.org (editor)

Other Cheatsheets

Developer Cheat Sheets (Builder)

Assessment Cheat Sheets (Breaker)

Mobile Cheat Sheets

OpSec Cheat Sheets (Defender)

Draft Cheat Sheets