web-dev-qa-db-ja.com

パスワードソルトは、レインボーテーブル攻撃に対してどのように役立ちますか?

パスワードへのソルトの目的を理解するのに苦労しています。私の理解では、主な用途はレインボーテーブル攻撃を妨げることです。ただし、これを実装するために見た方法では、実際に問題が難しくなるわけではありません。

ソルトを次のように使用することを提案する多くのチュートリアルを見てきました。

$hash =  md5($salt.$password)

理由は、ハッシュが元のパスワードではなく、パスワードとソルトの組み合わせにマッピングされるからです。しかし、$salt=foo$password=bar$hash=3858f62230ac3c915f300c664312c63fと言います。これで、Rainbowテーブルを持つ誰かがハッシュを逆にして、入力「foobar」を思い付くことができます。その後、パスワードのすべての組み合わせ(f、fo、foo、... oobar、obar、bar、ar、ar)を試すことができます。パスワードを取得するのにさらに数ミリ秒かかりますが、それ以外の時間はかかりません。

私が見た他の使用法は、私のLinuxシステム上です。/etc/shadowには、ハッシュ化されたパスワードが実際にwithsaltとともに保存されます。たとえば、「foo」のソルトと「bar」のパスワードは、$1$foo$te5SBM.7C25fFDu6bIRbX1にハッシュされます。ハッカーが何らかの形でこのファイルを手に入れることができた場合、te5SBM.7C25fFDu6bIRbXの逆ハッシュには "foo"が含まれていることがわかっているため、saltの目的はわかりません。

誰もがこれを当てることができる光をありがとう。

EDIT:助けてくれてありがとう。私が理解していることを要約すると、ソルトはハッシュされたパスワードをより複雑にし、事前計算済みのレインボーテーブルに存在する可能性をはるかに低くします。以前誤解していたのは、すべてのハッシュに対してRainbowテーブルが存在すると想定していたことです。

215
Rich

公開ソルトは、単一のパスワードを解読するときに辞書攻撃を難しくしますnot。あなたが指摘したように、攻撃者はハッシュ化されたパスワードとソルトの両方にアクセスできるため、辞書攻撃を実行するとき、パスワードを解読しようとするときに既知のソルトを使用できます。

公開ソルトは2つのことを行います。パスワードの大きなリストを解読するのに時間がかかり、Rainbowテーブルを使用できないようにします。

最初のものを理解するために、数百のユーザー名とパスワードを含む単一のパスワードファイルを想像してください。ソルトがなければ、「md5(attempt [0])」を計算し、ファイルをスキャンして、そのハッシュがどこかに現れるかどうかを確認できます。塩が存在する場合、「md5(salt [a] .attempt [0])」を計算し、エントリAと比較し、次に「md5(salt [b] .attempt [0])」、エントリBと比較する必要があります、など。今、n倍の作業があります。nは、ファイルに含まれるユーザー名とパスワードの数です。

2番目のものを理解するには、Rainbowテーブルとは何かを理解する必要があります。レインボーテーブルは、一般的に使用されるパスワードの事前に計算されたハッシュの大きなリストです。塩のないパスワードファイルをもう一度想像してください。私がしなければならないのは、ファイルの各行を調べて、ハッシュされたパスワードを引き出し、Rainbowテーブルで調べることだけです。単一のハッシュを計算する必要はありません。ルックアップがハッシュ関数(おそらくそれ)よりもかなり速い場合、これはファイルのクラッキングをかなりスピードアップします。

ただし、パスワードファイルがソルトされている場合、Rainbowテーブルには事前にハッシュされた「salt。password」が含まれている必要があります。塩が十分にランダムである場合、これはほとんどありません。よく使用される、事前にハッシュされたパスワードのリスト(Rainbowテーブル)に「hello」、「foobar」、「qwerty」などが含まれている可能性がありますが、「jX95psDZhello」や「LPgB0sdgxfoobar」または「dZVUABJtqwerty」は事前に計算されています。これにより、Rainbowテーブルが非常に大きくなります。

したがって、ソルトは攻撃者を試行ごとに1行あたり1回の計算に戻します。これは、十分に長く、十分にランダムなパスワードと組み合わせると、(一般的には)解読不能です。

234
Ross

他の答えはあなたのトピックの誤解に対処していないようですので、ここに行きます:

塩の2つの異なる用途

ソルトを次のように使用することを提案する多くのチュートリアルを見てきました。

$hash = md5($salt.$password)

[...]

私が見た他の使用法は、私のLinuxシステム上です。/etc/shadowには、ハッシュされたパスワードが実際にソルトと共に保存されます。

alwaysパスワードとともにソルトを保存する必要があります。ユーザーがパスワードデータベースに対して入力した内容を検証するには、入力をソルトと結合し、ハッシュして保存済みと比較する必要があるためです。ハッシュ。

ハッシュのセキュリティ

これで、Rainbowテーブルを持つ誰かがハッシュを逆にして、入力「foobar」を思い付くことができます。

[...]

te5SBM.7C25fFDu6bIRbXの逆ハッシュは「foo」を含むことがわかっているためです。

(少なくとも理論的には)ハッシュをそのまま逆にすることはできません。 「foo」のハッシュと「saltfoo」のハッシュには、共通してnothingがあります。暗号化ハッシュ関数の入力の1ビットでも変更すると、出力が完全に変更されます。

これは、一般的なパスワードを使用してRainbowテーブルを作成し、後で塩で「更新」できないことを意味します。あなたは最初から塩を考慮に入れなければなりません。

これが、そもそもRainbowテーブルが必要な理由です。ハッシュからパスワードを取得できないため、使用される可能性が最も高いパスワードのすべてのハッシュを事前計算し、ハッシュとハッシュを比較します。

塩の品質

しかし、$salt=fooと言う

「foo」は、極端に塩の選択が不適切です。通常、ASCIIでエンコードされたランダムな値を使用します。

また、各パスワードには独自のソルトがあり、システム上の他のすべてのソルトとは(できれば)異なっています。つまり、攻撃者はハッシュのoneがデータベース内の値の1つと一致することを期待するのではなく、各パスワードを個別に攻撃する必要があります。

攻撃

ハッカーがなんとかしてこのファイルを手に入れることができた場合、塩がどんな目的に役立つかわかりませんが、

レインボーテーブル攻撃常に/etc/passwd(または使用されるパスワードデータベース)を必要としますが、レインボーテーブルのハッシュと実際のパスワードのハッシュをどのように比較しますか?

目的については、攻撃者が一般的に使用される100,000の英語の単語と典型的なパスワード用のRainbowテーブルを作成したいとします(「秘密」と考えてください)。塩がなければ、彼女は100,000ハッシュを事前計算する必要があります。 2文字の従来のUNIXソルト(それぞれが64の選択肢の1つである[a–zA–Z0–9./])でさえ、4,096,000,000ハッシュを計算して保存する必要があります...かなり改善されました。

119
user3850

Saltのアイデアは、通常の文字ベースのパスワードよりもブルートフォースで推測するのをはるかに困難にすることです。多くの場合、レインボーテーブルは特別な文字セットを念頭に置いて構築され、常にall可能な組み合わせを含める必要はありません(可能ですが)。

したがって、適切なソルト値は、ランダムな128ビット以上の整数になります。これがレインボーテーブル攻撃を失敗させるものです。保存されたパスワードごとに異なるソルト値を使用することにより、特定のソルト値用に構築されたRainbowテーブル(単一のソルト値を持つ一般的なシステムの場合など)がすべてにアクセスできないことも保証します一度にパスワード。

87
Carl Seleborg

さらに別の素晴らしい質問で、多くの非常に思慮深い答えがあります-+1 to SO!

私が明示的に言及していない小さな点は、各パスワードにランダムなソルトを追加することにより、同じパスワードを選択した2人のユーザーが異なるハッシュを生成することを事実上保証していることです。

何でこれが大切ですか?

米国北西部の大規模なソフトウェア会社のパスワードデータベースを想像してください。 30,000個のエントリがあり、そのうち500個がパスワードbluescreenを持っているとします。さらに、ハッカーが、ユーザーからIT部門への電子メールでパスワードを読むことにより、このパスワードを取得することに成功したとします。パスワードが無塩である場合、ハッカーはデータベースでハッシュ値を見つけ、それを単純にパターンマッチングして他の499アカウントにアクセスできます。

パスワードをソルト化することにより、500個のアカウントのそれぞれに一意の(salt + password)が確保され、それぞれに異なるハッシュが生成されるため、単一のアカウントへの侵害が減少します。そして、すべての確率に対して、プレーンテキストのパスワードを電子メールメッセージに書き込むのに十分な素朴なユーザーが、次のOSの文書化されていないAPIにアクセスできないことを期待しましょう。

35
Adam Liss

私は塩を適用するための良い方法を探していましたが、サンプルコードでこの素晴らしい記事を見つけました:

http://crackstation.net/hashing-security.htm

著者は、ユーザーごとにランダムなソルトを使用することをお勧めします。そのため、ソルトにアクセスしても、ハッシュのリスト全体が簡単に解読されることはありません。

パスワードを保存するには:

  • CSPRNGを使用して長いランダムソルトを生成します。
  • パスワードの前にソルトを追加し、SHA256などの標準の暗号化ハッシュ関数でハッシュします。
  • ユーザーのデータベースレコードにソルトとハッシュの両方を保存します。

パスワードを検証するには:

  • データベースからユーザーのソルトとハッシュを取得します。
  • 指定されたパスワードにソルトを付加し、同じハッシュ関数を使用してハッシュします。
  • 指定されたパスワードのハッシュとデータベースのハッシュを比較します。一致する場合、パスワードは正しいです。それ以外の場合、パスワードは正しくありません。
15
MytyMyky

ソルトがレインボーテーブル攻撃を失敗させる理由は、nビットのソルトでは、レインボーテーブルがソルトなしのテーブルサイズの2 ^ n倍大きくなければならないためです。

'foo'を塩として使用する例では、Rainbow-tableを1600万倍大きくすることができます。

Carlの128ビットソルトの例を考えると、これはテーブルを2 ^ 128倍大きくします-今ではそれが大きくなります-または別の言い方をすれば、誰かがその大きなポータブルストレージを持っている前にどれくらいですか?

12
quamrana

ハッシュベースの暗号化を破るほとんどの方法は、ブルートフォース攻撃に依存しています。レインボー攻撃は、本質的にはより効率的な辞書攻撃です。低コストのデジタルストレージを使用して、ハッシュへの可能なパスワードの実質的なサブセットのマップを作成し、逆マッピングを容易にするように設計されています。多くのパスワードはかなり短いか、Wordベースの形式のいくつかのパターンのいずれかを使用する傾向があるため、この種の攻撃は機能します。

このような攻撃は、パスワードにさらに多くの文字が含まれていて、一般的なWordベースの形式に準拠していない場合には効果がありません。最初から強力なパスワードを持っているユーザーは、このスタイルの攻撃に対して脆弱ではありません。残念ながら、多くの人々は良いパスワードを選びません。しかし、妥協点があります。ランダムなジャンクを追加することで、ユーザーのパスワードを改善できます。そのため、「hunter2」の代わりに、パスワードは事実上「hunter2908!fld2R75 {R7 /; 508PEzoz ^ U430」になります。これははるかに強力なパスワードです。ただし、この追加のパスワードコンポーネントを保存する必要があるため、強力な複合パスワードの有効性が低下します。結局のところ、このようなスキームには、脆弱なパスワードであっても、事前に計算された同じハッシュ/ Rainbowテーブルに対する脆弱性がなくなったため、依然として純益があります。代わりに、各パスワードハッシュエントリは、一意のハッシュテーブルに対してのみ脆弱です。

パスワード強度の要件が弱いサイトがあるとします。ハッシュが事前に計算されたハッシュテーブルに対して脆弱である場合、パスワードソルトを使用しない場合、ハッシュにアクセスできるユーザーは、ユーザーの大部分のパスワードにアクセスできます(ただし、多くの脆弱なパスワードは使用されますが、かなりの割合)。一定のパスワードソルトを使用する場合、事前に計算されたハッシュテーブルはもはや価値がないため、誰かがそのソルトのカスタムハッシュテーブルを計算するために時間を費やす必要がありますが、漸進的に行うことができ、より大きな順列をカバーするテーブルを計算します問題空間の。最も脆弱なパスワード(たとえば、単純なWordベースのパスワード、非常に短い英数字のパスワード)は数時間または数日で解読され、脆弱性の低いパスワードは数週間または数か月後に解読されます。時間が経つにつれて、攻撃者はますます増え続けるユーザーのパスワードにアクセスできるようになります。すべてのパスワードに一意のソルトを使用する場合、これらの脆弱なパスワードのそれぞれにアクセスするには数日または数か月かかります。

ご覧のとおり、ソルトなしからコンスタントなソルト、ユニークなソルトにステップアップすると、各ステップで脆弱なパスワードをクラックするための努力が数桁増加します。ソルトがなければ、ユーザーの最も弱いパスワードに簡単にアクセスできます。一定のソルトでは、特定の攻撃者が弱いパスワードにアクセスできます。ユニークなソルトでは、パスワードにアクセスするコストが非常に高くなります。脆弱なパスワードのごく一部に限定し、それから多大な費用をかけます。

まさにそのような状況です。パスワードの選択が悪いことからユーザーを完全に保護することはできませんが、ユーザーのパスワードを危険にさらすコストを、1人のユーザーのパスワードでさえ非常に高価になるレベルまで上げることができます。

10
Wedge

塩漬けの1つの目的は、事前計算されたハッシュテーブルを無効にすることです。事前に計算された数百万のハッシュのリストがある場合、ハッシュとソルトを知っていても、テーブルで$ 1 $ foo $ te5SBM.7C25fFDu6bIRbX1を検索することはできません。彼らはまだそれを総当たりする必要があります。

別の目的は、Carl Sが言及しているように、ハッシュのリストをブルートフォースすることをより高価にすることです。 (それらにすべて異なる塩を与えます)

塩が公開されている場合でも、これらの目的は両方ともまだ達成されています。

3
recursive

私の知る限り、ソルトは辞書攻撃をより困難にすることを目的としています。

多くの人が一見ランダムな文字列ではなく、パスワードに一般的な単語を使用することは周知の事実です。

そのため、ハッカーはブルートフォースを使用する代わりに、これを有利に使用できます。彼はaaa、aab、aacなどのパスワードを探しませんが、代わりに単語と一般的なパスワード(ロードオブザリングの名前など!;))を使用します

したがって、私のパスワードがレゴラスである場合、ハッカーはそれを試して、「数回」の試行で推測できます。ただし、パスワードをソルトしてfooLegolasになった場合、ハッシュが異なるため、辞書攻撃は失敗します。

お役に立てば幸いです!

1
rgargente