169

私が行っていたのは、実際にはパスワードをソルトするのではなく、パスワードをペッパー化することであることがわかったという議論に出くわしました。

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

選択したハッシュ アルゴリズムを無視する (特定のアルゴリズムではなく、塩とコショウについての議論にしたいのですが、安全なアルゴリズムを使用しています)、これは安全なオプションですか、それとも別のことをする必要がありますか? 用語に慣れていない人のために:

  • ソルトはランダムに生成された値で、通常はハッシュ テーブルを使用してパスワードをクラックできないように設計されたデータベースに文字列と共に格納されます。各パスワードには独自のソルトがあるため、解読するには、すべてのパスワードを個別に総当たり攻撃する必要があります。ただし、salt はパスワード ハッシュと共にデータベースに保存されるため、データベースの侵害は両方を失うことを意味します。

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

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

注: アプリケーションとデータベースは別々のマシンに保存され、パスワードなどを共有しないことを前提として説明します。したがって、データベース サーバーの侵害が自動的にアプリケーション サーバーの侵害を意味するわけではありません。

4

5 に答える 5

339

Ok。これについて何度書く必要があるので、ペッパーだけで最後の標準的な回答を1つ行います。

ピーマンの明らかな利点

ペッパーがハッシュ関数をより安全にするべきであることは明らかです。つまり、攻撃者があなたのデータベースだけを取得した場合、ユーザーのパスワードは安全であるはずですよね? 論理的に思えますよね?

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

ペッパーの現実

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

そして、ペッパーは、証明可能なモデルにも保守可能なモデルにも適合しません...

ペッパーの理論上の問題

準備が整ったので、ピーマンの何が問題なのかを見てみましょう.

  • あるハッシュを別のハッシュにフィードすることは危険です。

    あなたの例では、そうします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 だけになります。その場合、一部の辞書の語句や修飾語でさえ安全な場合があります。

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

  • 保存前に出力ハッシュを暗号化する

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

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

TL/DR

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

于 2013-06-03T11:59:06.143 に答える
27

最初に、コショウの正確な利点について説明する必要があります。

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

典型的なシナリオは、SQL インジェクション、破棄されたバックアップ、破棄されたサーバーなどです。これらの状況は、思ったほど珍しいことではなく、多くの場合、自分で制御できません (サーバー ホスティング)。あなたが使用する場合...

  • パスワードごとに一意のソルト
  • BCrypt のような遅いハッシュ アルゴリズム

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

2番目の質問は、コショウの適用方法です。

ペッパーを適用するためによく推奨される方法は、ハッシュ関数に渡す前にパスワードとペッパーを結合することです。

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

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

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

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

于 2013-06-03T09:05:14.103 に答える
3

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

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

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

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

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

于 2013-06-03T07:32:12.280 に答える
3

これは、特定のアルゴリズムではなく、塩とコショウの議論にしたいのですが、安全なアルゴリズムを使用しています

私が知っているすべての安全なパスワード ハッシュ関数は、パスワードとソルト (およびサポートされている場合はシークレット/ペッパー) を個別の引数として取り、すべての作業自体を行います。

文字列を連結していて、hash_function引数が 1 つしかないという事実だけで、よくテストされ、よく分析された標準アルゴリズムのいずれかを使用しておらず、代わりに独自のアルゴリズムをロールしようとしていることがわかります。そうしないでください。

Argon2は 2015 年のパスワード ハッシング コンペティションで優勝しましたが、私の知る限り、Argon2 は今でも新しいデザインに最適な選択肢です。Kパラメータ(「秘密の値」または「キー」と呼ばれる)を介してペッパーをサポートします。胡椒を使わない理由がないことを私は知っています。最悪の場合、ペッパーはデータベースと共に危険にさらされ、それを使用しなかった場合よりも悪いことはありません。

組み込みのペッパー サポートを使用できない場合は、このディスカッションから提案された 2 つの式のいずれかを使用できます。

Argon2(salt, HMAC(pepper, password))   or   HMAC(pepper, Argon2(salt, password))

重要な注意: HMAC (またはその他のハッシュ関数) の出力を Argon2 (またはその他のパスワード ハッシュ関数) に渡す場合は、パスワード ハッシュ関数が埋め込みゼロ バイトをサポートしていることを確認するか、ハッシュ値をエンコードします (たとえば、base64 で) ) ゼロバイトがないようにします。文字列がゼロバイトの埋め込みをサポートする言語を使用している場合、その言語が PHPでない限り、おそらく安全ですが、とにかくチェックします。

于 2020-08-03T01:28:30.260 に答える
1

ソース コードにハードコードされた値を保存しても、セキュリティ関連性があるとは考えられません。それはあいまいさによるセキュリティです。

ハッカーがデータベースを取得した場合、ユーザー パスワードのブルート フォース攻撃を開始できます。そのハッカーがいくつかのパスワードを解読できれば、あなたのコショウを特定するのにそれほど時間はかかりません.

于 2013-06-03T07:23:06.237 に答える