ベストプラクティス:パスワードをソルトアンドペパーリングしますか?


145

私が行っていることは、実際にはパスワードをソルト処理するのではなく、それらをペパーリングすることであることがわかったディスカッションに出会い、それ以来、次のような関数で両方を実行し始めました。

hash_function($salt.hash_function($pepper.$password)) [multiple iterations]

選択したハッシュアルゴリズムを無視します(これはソルト&ペッパーの説明であり、特定のアルゴリズムではありませんが、安全なアルゴリズムを使用しています)、これは安全なオプションですか、それとも何か別のことをする必要がありますか?用語に不慣れな方のために:

  • 塩は、通常、それが不可能なパスワードをクラックするハッシュテーブルを使用するようにするために設計されたデータベース内の文字列を格納し、ランダムに生成された値です。各パスワードには独自のソルトがあるため、パスワードを解読するためにすべて個別にブルートフォースする必要があります。ただし、ソルトはパスワードハッシュとともにデータベースに格納されるため、データベースのセキュリティが侵害されると、両方が失われます。

  • 唐辛子は秘密であることが意図されている(通常は、アプリケーションのソースコードにハードコードされた)データベースとは別に格納されているサイト全体の静的な値です。これは、データベースが侵害されてもアプリケーション全体のパスワードテーブルがブルートフォース可能にならないようにするために使用されます。

不足しているものはありますか?ユーザーのセキュリティを保護するために、パスワードをソルト&ペッパーリングするのが最良のオプションですか?この方法で行うことには、潜在的なセキュリティ上の欠陥はありますか?

注:説明のために、アプリケーションとデータベースは別々のマシンに格納されていると仮定します。パスワードは共有しないでください。したがって、データベースサーバーの違反が、アプリケーションサーバーの違反を自動的に意味するわけではありません。


3
ないかなり重複しますが、非常に関連:stackoverflow.com/questions/16594613/...は
ircmaxell

2
クロスサイト複製:security.stackexchange.com/q/3272/2113
Jacco

回答:


306

OK。私はこれについて何度何度も書く必要があるので、コショウだけで最後の標準的な回答をします。

ピーマンの見かけのアップサイド

コショウはハッシュ関数をより安全にするべきであることは非常に明白です。つまり、攻撃者がデータベースのみを取得する場合、ユーザーのパスワードは安全でなければなりません。論理的に見えますか?

だからこそ、ピーマンは良いアイデアだと信じる人がたくさんいます。それは理にかなっている"。

コショウの現実

セキュリティと暗号化の領域では、「理にかなっている」だけでは十分ではありません。安全であると見なされるには、証明可能意味のあるものが必要です。さらに、保守可能な方法で実装できる必要があります。維持できない最も安全なシステムは安全でないと見なされます(そのセキュリティのいずれかの部分が故障すると、システム全体が崩壊するため)。

そして、ピーマンは証明可能なモデルにも維持可能なモデルにも適合しません...

コショウの理論的な問題

準備が整ったので、唐辛子のどこが悪いのか見てみましょう。

  • ハッシュを別のハッシュにフィードすることは危険な場合があります。

    あなたの例では、あなたはそうしますhash_function($salt . hash_function($pepper . $password))

    過去の経験から、1つのハッシュ結果を別のハッシュ関数に「供給する」だけで全体的なセキュリティが低下する可能性があることがわかっています。その理由は、両方のハッシュ関数が攻撃の対象になる可能性があるためです。

    そのため、PBKDF2などのアルゴリズムは、特別な演算を使用してそれらを結合します(その場合はhmac)。

    重要なことは、大したことではありませんが、ただ捨てるのは簡単なことではありません。暗号システムは、「機能するはずの」ケースを回避するように設計されており、代わりに「機能するように設計された」ケースに焦点を当てています。

    これは純粋に理論的に見えるかもしれませんが、実際にはそうではありません。たとえば、Bcryptは任意のパスワードを受け入れることができません。そのbcrypt(hash(pw), salt)ため、渡すと実際にバイナリ文字列を返すbcrypt(pw, salt)場合よりもはるかに弱いハッシュになる可能性hash()があります。

  • 設計に対する取り組み

    bcrypt(およびその他のパスワードハッシュアルゴリズム)の設計方法は、saltを操作することです。コショウの概念は導入されませんでした。これは些細なことのように思えるかもしれませんが、そうではありません。その理由は、塩は秘密ではないからです。これは、攻撃者が知ることができる単なる値です。一方、ペッパーは、まさに暗号の秘密です。

    現在のパスワードハッシュアルゴリズム(bcrypt、pbkdf2など)はすべて、1つの秘密値(パスワード)のみを取り込むように設計されています。アルゴリズムに別の秘密を追加することはまったく研究されていません。

    それが安全ではないという意味ではありません。安全かどうかはわかりません。また、セキュリティと暗号化に関する一般的な推奨事項は、わからない場合はそうではないということです。

    したがって、アルゴリズムが暗号化者によって設計され、秘密の値(ペッパー)で使用できるように吟味されるまで、現在のアルゴリズムをそれらで使用することはできません。

  • 複雑さはセキュリティの敵です

    信じられないかもしれませんが、複雑さはセキュリティの敵です。複雑に見えるアルゴリズムを作ることは安全かもしれませんし、そうでないかもしれません。しかし、それが安全でない可能性は非常に重要です。

コショウの重大な問題

  • 維持できません

    ペッパーの実装では、ペッパーキーをローテーションする機能は使用できません。ペッパーは一方向関数への入力で使用されるため、値の存続期間中はペッパーを変更できません。これは、キーローテーションをサポートするために、いくつかの奇妙なハックを考え出す必要があることを意味します。

    これは、暗号シークレットを保存するときに必ず必要になるため、非常に重要です。キーをローテーションするメカニズムがない(定期的に、および違反の後で)ことは、セキュリティ上の大きな脆弱性です。

    そして、現在のペッパーアプローチでは、すべてのユーザーがローテーションによってパスワードを完全に無効にするか、次回のログインまでローテーションするまで待つ必要があります(これは決して行われない場合があります)...

    これは基本的に、あなたのアプローチを即座に立ち去らせます。

  • あなた自身の暗号を転がす必要があります

    現在のアルゴリズムではペッパーの概念をサポートしていないため、アルゴリズムを作成するか、ペッパーをサポートする新しいアルゴリズムを発明する必要があります。そして、それがなぜ本当に悪いことなのかすぐにわからない場合は、次のようにします。

    最も無知なアマチュアから最高の暗号学者まで、誰でも彼自身が破ることができないアルゴリズムを作成できます。

    自分の暗号を決してロールしないでください...

より良い方法

したがって、上記で詳述したすべての問題のうち、状況を処理するには2つの方法があります。

  • アルゴリズムをそのまま使用する

    bcryptまたはscryptを正しく(高コストで)使用する場合、最も弱い辞書パスワードを除くすべてが統計的に安全である必要があります。コスト5でbcryptをハッシュするための現在のレコードは、1秒あたり71,000ハッシュです。そのレートでは、6文字のランダムパスワードでも解読に数年かかります。そして、私の最小推奨コストが10であることを考慮すると、1秒あたりのハッシュが32分の1に削減されます。したがって、1秒あたり約2200ハッシュだけを話します。そのレートでは、一部の辞書のフレーズや変更でさえ安全である可能性があります。

    さらに、ドアでそれらの弱いクラスのパスワードをチェックし、それらを許可しないようにする必要があります。パスワードクラッキングがより高度になるにつれて、パスワードの品質要件も必要になります。それはまだ統計的なゲームですが、適切なストレージ技術と強力なパスワードがあれば、誰もが実質的に非常に安全でなければなりません...

  • ストレージの前に出力ハッシュを暗号化する

    セキュリティレルムには、上記で述べたすべてを処理するように設計されたアルゴリズムが存在します。それはブロック暗号です。リバーシブルなので、キーをローテーションできます(そうです!保守性!)。設計通りに使用されているので良いです。それはユーザーに情報を提供しないので良いです。

    その行をもう一度見てみましょう。攻撃者があなたのアルゴリズムを知っているとしましょう(これはセキュリティに必要ですが、そうでなければ、あいまいさによるセキュリティです)。伝統的なペッパーアプローチでは、攻撃者はセンチネルパスワードを作成でき、塩と出力を知っているので、ペッパーをブルートフォースで攻撃できます。OK、それはロングショットですが、それは可能です。暗号では、攻撃者は何も取得しません。また、ソルトはランダム化されているので、歩哨のパスワードは彼/彼女を助けさえしません。したがって、残された最善の方法は、暗号化されたフォームを攻撃することです。つまり、最初に暗号化されたハッシュを攻撃して暗号化キーを回復し、次にハッシュを攻撃する必要があります。しかし、暗号の攻撃については多くの研究があるので、それに頼りたいと思います。

TL / DR

ピーマンは使わないでください。それらには多くの問題があり、2つのより良い方法があります。サーバー側のシークレットを使用しない(はい、問題ありません)と、保存する前にブロック暗号を使用して出力ハッシュを暗号化します。


6
ハッシュ値の暗号化の最後の部分を含めてくれてありがとう、これは私が完全に同意できる答えです。暗号化がパスワードAPIの一部になる場合は、それを使用しない理由はないので、おそらく...(私はそのドキュメントを書きたいと
思い

2
@martinstoeckli:単純化されたハッシュAPIに暗号化ステップを追加することに同意しません。その理由は、秘密(鍵)の保管は、人々が理解するよりもはるかに困難であり、自分の足を撃つことは非常に簡単だからです。そこにいるユーザーの99.9%にとって、生のbcryptは最も単純なパスワードを除くすべてに対して十分以上です...
ircmaxell

7
@ircmaxell-反対側では、何も失うことはありません。最悪の場合、キーが判明しても、攻撃者はBCryptハッシュを解読する必要があります(暗号化なしの場合と同じ状況)。これは、データを暗号化するためのキーを保存することと同じではありません。これは、サーバー側のシークレットを追加することです。攻撃者がサーバー/コードを制御できない限り、ハードコードされたキーでもこれらの弱いパスワードを保護します。この状況は珍しいことではありません。SQLインジェクションのほかに、バックアップの破棄、サーバーの破棄などがこの状況につながる可能性があります。多くのPHPユーザーがホストサーバーで作業しています。
martinstoeckli 2013年

2
@martinstoeckli私はここでircmaxwellに同意する必要があります。暗号化はパスワードAPIに属しているとは思いません。ただし、最大限のセキュリティを確保するために、ハッシュを暗号化することは、使用できる追加のプロビジョニングであることに注意してください。
foochow 2013年

保存前の出力の暗号化について質問があります。私が間違っていない場合は、通常、暗号化キーを使用してメッセージを一意に、または一時的に暗号化します。ただし、200,000のユーザーパスワードがすべて同じキーで暗号化されて一緒に保存されている場合、キーを攻撃するのは簡単ではありませんか?1つまたは2つに比べて、メッセージは200,000になりました
AgmLauncher

24

コショウの正確な利点について話すべき拳:

  • ペッパーは、攻撃者がデータベース(ハッシュを含む)への読み取りアクセス権を持っているが、ペッパーによるソースコードへのアクセス権を持っていない特殊な場合に、弱いパスワードを辞書攻撃から保護できます。

典型的なシナリオは、SQLインジェクション、破棄されたバックアップ、破棄されたサーバーなどです。これらの状況は、それほど一般的ではなく、多くの場合、管理下にありません(サーバーホスティング)。あなたが使うなら...

  • パスワードごとに固有のソルト
  • BCryptのような低速ハッシュアルゴリズム

...強力なパスワードは十分に保護されています。ソルトがわかっている場合でも、これらの条件下で強力なパスワードを総当たりにすることはほぼ不可能です。問題は、ブルートフォース辞書の一部であるか、それらの派生物である弱いパスワードです。最も一般的なパスワードのみをテストするので、辞書攻撃はそれらを非常に速く明らかにします。

第二の質問は、コショウを適用する方法ですか?

コショウを適用するためにしばしば推奨される方法は、ハッシュ関数に渡す前にパスワードとコショウを結合することです:

$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);

ただし、別のより良い方法があります。

$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);

これにより、サーバー側のシークレットを追加できるだけでなく、必要に応じて$ serverSideKeyを交換することもできます。この方法にはもう少し手間がかかりますが、コードが存在する場合(ライブラリ)、それを使用しない理由はありません。


つまり、ペッパーは単に塩よりも安全性を高めると言えますか?実装方法のヘルプをありがとう。
グリッチの欲望2013

1
@LightningDust-はい、脆弱なパスワードの場合は、ペッパーが秘密のままである限り可能です。それはいくつかの明確に定義されたタイプの脅威を軽減します。
martinstoeckli 2013年

@martinstoeckliは間違いなくこれを実装する良い方法です。セキュリティの経験がある人がこの方法をサポートしていることを確認してください。MySQL AES_ENCRYPT($passwordHash, $serverSideKey)呼び出しもこれを実装する適切な方法でしょうか?
foochow 2013年

1
@Foo_Chow-MySQL関数の実装はわかりませんが、IVベクトルを回避するためにEBCモードを使用しているようです。既知のプレーンテキスト(ハッシュ値は常に同じ文字で始まる)と一緒に使用すると、これが問題になる可能性があります。私のホームページで、この暗号化を処理する実装例を公開しました。
martinstoeckli 2013年

@martinstoeckliは興味深く、概念に精通していません。ただし、最も堅牢な結果を得るにはIVが望ましいようです。追加された利点のために多くのオーバーヘッドを追加しないようです。
foochow 2013年

2

ソルトアンドペッパーのポイントは、レインボーテーブルと呼ばれる、事前に計算されたパスワードルックアップのコストを増やすことです。

一般に、単一のハッシュの衝突を見つけようとすることは困難です(ハッシュが安全であると想定)。ただし、ハッシュが短い場合、コンピュータを使用して、可能なすべてのハッシュをハードディスク上のルックアップに生成することができます。これはレインボーテーブルと呼ばれます。レインボーテーブルを作成した場合、世界に出て、あらゆる(無塩でペッパーのない)ハッシュのもっともらしいパスワードをすばやく見つけることができます。

コショウのポイントは、パスワードリストをハッキングするために必要なレインボーテーブルを一意にすることです。したがって、レインボーテーブルを作成するために攻撃者に多くの時間を費やすことになります。

ただし、ソルトのポイントは、各ユーザーのレインボーテーブルをユーザーごとに一意にすることであり、攻撃の複雑さがさらに増します。

実際、コンピューターのセキュリティのポイントは、それを(数学的に)不可能にすることではなく、数学的にも物理的にも実用的ではありません(たとえば、安全なシステムでは、単一のユーザーのパスワードを計算するために宇宙(およびそれ以上)のすべてのエントロピーを必要とします)。


では、salt + pepperは単なる塩よりも高いセキュリティを提供しますか?または、私はコショウを落とし、scryptの反復をより多く実行する方が良いでしょうか?
グリッチの欲望

2
レインボーテーブルの主な点は、特定の攻撃用に作成するのではなく、既存の攻撃をダウンロードすることです。人気のあるハッシュアルゴリズムに利用できる長いレインボーテーブルがグーグル離れてあります!
Richard

1
@LightningDust自分には理由なんて考えられない。しかし、他のスレッドのリチャードはそれを思いついた。ソースコードのコショウを隠すことができます。これは、レインボーテーブルを取得するためだけに、攻撃者がアクセスする必要がある別の場所を意味します。
Aron

@Aron-まあ、それは私がデータベースサーバーとは別のアプリケーションサーバーを持っているので(つまり、root私たちのdbサーバーにアクセスしても、まだアプリケーションサーバーにアクセスできないので)、ソースコードのペッパーを隠す(私たちの設定ファイル)は、追加のセキュリティを提供します。
グリッチの欲望2013

1

セキュリティ関連性があるとハードコードされた値をソースコードに格納することはできません。あいまいさによるセキュリティです。

ハッカーがデータベースを取得した場合、ハッカーはユーザーパスワードの総当たりを開始することができます。そのハッカーがいくつかのパスワードを解読できれば、コショウがあなたのコショウを識別するのに時間がかかりません。


1
これにより、無塩のパスワードテーブル用に事前に計算されたレインボーテーブルが役に立たなくなります。つまり、攻撃者がコショウを知っていたとしても、新しいレインボーテーブルを作成する必要があります。
アロン

3
データベースで利用できないデータに基づくハッシュを強化します。これは良いことです。データベース内のものが脆弱性で明らかになる可能性があります-コード内の値が同じ方法でアクセスされる可能性は低くなります。
Richard

ソルトは一方向の機能であり、パスワードをブルートフォースで正常に実行しても、そのパスワードしか得られず、pepperの値自体を取得するのに役立ちません。
Glitch Desire 2013

1
@LightningDust「ハッシュはトラップドア関数です」という意味だと思います。はい、安全なハッシュ(実際には安全なハッシュの定義です)からソルトやペッパーを理解することは不可能です。
Aron

6
あいまいさによる@Aronのセキュリティは、防御層として使用される有効な手法です。重要なのは、それを防御として信頼してはなら、代わりに「攻撃者をスローダウンさせる」ために使用されるということです。そうでなければ、ハニーポットのようなものは使用されません。代わりに、アプリケーションのセキュリティを信頼していない限り、攻撃者の速度を落とすために、あいまいさを利用してセキュリティを効果的に利用できます。
ircmaxell 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.