更新:ソルトとは何か、レインボーテーブルとは何か、辞書攻撃とは何か、またはソルトの目的については尋ねていません。質問しています:ユーザーがソルトとハッシュを知っている場合、パスワードを計算するのは簡単ではありませんか?
私はそのプロセスを理解し、自分のプロジェクトのいくつかで自分で実装しています。
s = random salt
storedPassword = sha1(password + s)
保存するデータベースに:
username | hashed_password | salt
私が見たソルティングのすべての実装は、パスワードの最後または最初にソルトを追加します。
hashed_Password = sha1(s + password )
hashed_Password = sha1(password + s)
したがって、彼のソルト(ハハ)に値するハッカーからの辞書攻撃は、上記の一般的な組み合わせで格納されているソルトに対して各キーワードを実行するだけです。
確かに、上記の実装は、根本的な問題を実際に解決することなく、ハッカーに別のステップを追加するだけですか?この問題を回避するための代替手段はありますか、それとも問題を誤解していますか?
私ができると思う唯一のことは、ランダムなパターンでソルトとパスワードをひもで結ぶ秘密のブレンドアルゴリズムを持っているか、ハッシングプロセスに他のユーザーフィールドを追加して、ハッカーがデータベースとコードにアクセスしてひもを付ける必要があることです辞書攻撃が実り多いことを証明するために。 (更新、コメントで指摘されているように、ハッカーがすべての情報にアクセスできると想定するのが最善であるため、これはおそらく最善ではありません)。
ハッカーがパスワードとハッシュのリストでユーザーデータベースをハッキングする方法を提案する例を挙げましょう。
ハッキングされたデータベースのデータ:
RawPassword (not stored) | Hashed | Salt
--------------------------------------------------------
letmein WEFLS... WEFOJFOFO...
一般的なパスワード辞書:
Common Password
--------------
letmein
12345
...
ユーザーレコードごとに、共通のパスワードをループしてハッシュします。
for each user in hacked_DB
salt = users_salt
hashed_pw = users_hashed_password
for each common_password
testhash = sha1(common_password + salt)
if testhash = hashed_pw then
//Match! Users password = common_password
//Lets visit the webpage and login now.
end if
next
next
これが私のポイントをよりよく説明してくれることを願っています。
10,000の一般的なパスワードと10,000のユーザーレコードがある場合、できるだけ多くのユーザーパスワードを検出するには、100,000,000のハッシュを計算する必要があります。数時間かかる場合がありますが、実際には問題ありません。
クラッキング理論の更新
SHA1ハッシュとソルトのデータベース、およびそれらをブレンドするアルゴリズムにアクセスできる破損したWebホストであると想定します。データベースには10,000のユーザーレコードがあります。
このサイト GPUを使用して毎秒2,300,000,000のSHA1ハッシュを計算できると主張しています。 (実際の状況ではおそらく遅くなりますが、今のところ、その引用された図を使用します)。
(((95 ^ 4)/ 2300000000)/ 2)* 10000 = 177秒
印刷可能な95の全範囲を指定した場合ASCII文字、最大長4文字、計算速度(変数)で除算、2で除算(パスワードの検出にかかる平均時間を想定)平均で順列の50%が必要です)10,000ユーザーの場合、長さが4以下のすべてのユーザーのパスワードを計算するには177秒かかります。
リアリズムのために少し調整してみましょう。
(((36 ^ 7)/ 1000000000)/ 2)* 10000 = 2日
大文字と小文字を区別せず、パスワードの長さが<= 7で英数字のみの場合、10,000ユーザーレコードを解決するには4日かかります。オーバーヘッドと理想的でない状況を反映するために、アルゴリズムの速度を半分にしました。
これは線形総当たり攻撃であり、すべての計算は互いに独立しているため、複数のシステムが解決するのに最適なタスクであることを認識することが重要です。 (つまり、実行時間が半分になる、異なる端から攻撃を実行する2台のコンピューターを簡単にセットアップできます)。
このタスクをより計算負荷の高いものにするためにパスワードを1,000回再帰的にハッシュする場合を考えます。
(((36 ^ 7)/ 1000 000 000)/ 2)* 1000秒= 10.8839117時間
これは、最大長7文字の英数字を表し、1人のユーザーの引用図から半分の速度で実行されます。
1,000回再帰的にハッシュすることで、全面的な攻撃を効果的にブロックできますが、ユーザーデータに対する標的型攻撃は依然として脆弱です。
はい、sha1(salt | password)に必要なのはわずか3日です。これが、優れたパスワードストレージアルゴリズムが1000回の反復ハッシュを使用する理由です。8年必要です。
辞書攻撃を阻止するものではありません。
これは、パスワードファイルのコピーを取得したユーザーが Rainbow table を使用してハッシュからパスワードが何であるかを理解できないようにすることです。
ただし、最終的には、総当たり攻撃になる可能性があります。その部分に対する答えは、ユーザーが辞書の単語をパスワードとして使用しないように強制することです(たとえば、少なくとも1つの数字または特殊文字の最小要件)。
更新:
私はこれについて前に述べたはずですが、一部の(ほとんど?)パスワードシステムは、パスワードごとに異なるソルトを使用します。これにより、1つのRainbowテーブルが役に立たなくなります。これがUNIX crypt ライブラリのしくみであり、最近のUNIXライクなOSは、このライブラリを新しいハッシュアルゴリズムで拡張しています。
SHA-256とSHA-512のサポートがGNU cryptの新しいバージョンで追加されたことを知っています。
より正確に言うと、 辞書攻撃 、つまり、完全なリスト内のすべての単語が試行される攻撃は、「不可能」ではありませんが、非実用的です: saltの各ビットにより、必要なストレージと計算の量が2倍になります 。
これは、塩が秘密であるかどうかに関係なく、レインボーテーブルを含む攻撃のような事前に計算された辞書攻撃とは異なります。
例:64ビットのソルト(つまり8バイト)では、2をチェックする必要があります。64 辞書攻撃における追加のパスワードの組み合わせ。 200,000語を含む辞書を作成する必要があります
200,000 * 264 = 3.69 * 1024
最悪の場合のテスト-塩なしの200,000テストの代わりに。
Saltを使用するもう1つの利点は、攻撃者が辞書からパスワードハッシュを事前に計算できないことです。単に時間がかかりすぎたり、スペースがかかりすぎたりするだけです。
更新
この更新では、攻撃者がすでにソルトを知っている(またはソルトを盗んだ)と想定しています。これはもちろん別の状況です。それでも、攻撃者が事前に計算されたRainbowテーブルを使用することはできません。ここで重要なのは、ハッシュ関数の速度です。攻撃を非現実的にするには、ハッシュ関数を低速にする必要があります。 MD5またはSHAは高速に設計されているため、ここでは適切な候補ではありません。ハッシュアルゴリズムのより適切な候補は、Blowfishまたはそのバリエーションです。
更新2
一般的にパスワードハッシュを保護することについての良い読み物(元の質問をはるかに超えていますが、それでも興味深い):
記事の結果:bcrypt(Blowfishに基づく)またはEksblowfishで作成したソルトハッシュを使用して、構成可能な設定を使用できるようにするハッシュを遅くする時間。
ディクショナリは、値がキーによってインデックス付けされる構造です。事前に計算された辞書攻撃の場合、各キーはハッシュであり、対応する値はハッシュとなるパスワードです。事前に計算された辞書を使用すると、攻撃者はログインに必要なハッシュを生成するパスワードを「瞬時に」検索できます。
Saltを使用すると、ディクショナリを格納するために必要なスペースが急速に増大します。非常に急速に、パスワードディクショナリを事前に計算しようとしても無意味になります。
最良のソルトは、暗号化乱数ジェネレータからランダムに選択されます。 8バイトは実用的なサイズであり、16バイトを超えると意味がありません。
ソルトは、単に「攻撃者の仕事をいらいらさせる」だけではありません。攻撃のクラス全体、つまり事前に計算された辞書の使用を排除します。
パスワードを完全に保護するには、もう1つの要素が必要です。それが「キー強化」です。 SHA-1の1ラウンドでは十分ではありません:安全なパスワードハッシュアルゴリズムはvery計算が遅い。
多くの人々は、キー導出関数であるPBKDF2を使用して、結果をハッシュ関数数千回回フィードバックします。 「bcrypt」アルゴリズムも同様で、低速の反復鍵導出を使用します。
ハッシュ操作が非常に遅い場合、事前計算されたテーブルは攻撃者にとってますます望ましいものになります。しかし、適切な塩はそのアプローチを無効にします。
以下は、私が質問に対して行ったコメントです。
ソルトなしでは、攻撃者は「アップデート2」で説明されている方法を使用しません。彼は単純に、事前に計算されたテーブルで検索を行い、O(1)またはO(log n)時間でパスワードを取得します(nは候補パスワードの数です)。何がそれを防ぎ、彼にO(n) "Update 2"に示されたアプローチを使用することを強いる。
O(n)攻撃に減ったら、各試行にかかる時間を考慮する必要があります。キーを強化すると、ループ内の各試行に1秒かかります。つまり、必要な時間が1万人のユーザーで1万個のパスワードをテストするには、3日から3年に伸びます...そして、1万個のパスワードだけでは、パスワードをクラックしない可能性があります時間。
攻撃者はPHPではなく、可能な限り最速のツールを使用することを考慮する必要があるため、100回ではなく数千回の反復がキー強化の適切なパラメータになるでしょう。単一のパスワードのハッシュを計算するには、ほんの一瞬で完了するはずです。
キー強化は、PKCS#5の標準のキー派生アルゴリズムPBKDF1およびPBKDF2の一部であり、優れたパスワード難読化アルゴリズムを作成します(「派生キー」は「ハッシュ」です)。
StackOverflowの多くのユーザーが この記事 を参照しています。これは、Rainbowテーブルの危険性に関するJeff Atwoodの投稿への返答だったからです。これは私のお気に入りの記事ではありませんが、これらの概念について詳しく説明しています。
もちろん、攻撃者がすべてのものを持っていると想定します:ソルト、ハッシュ、ユーザー名。攻撃者が、myprettypony.comのファンサイトにユーザーテーブルをダンプした、破損したホスティング会社の従業員であると想定します。彼は振り向いて、ポニーファンがcitibank.comアカウントで同じパスワードを使用したかどうかを確認するため、これらのパスワードを回復しようとしています。
適切に設計されたパスワードスキームでは、この男がパスワードを回復するのは不可能です。
ソルトのポイントは、攻撃者の努力の償却を防ぐことです。
ソルトがない場合、事前に計算されたハッシュパスワードエントリの単一のテーブル(たとえば、すべての英数字5文字列のMD5、オンラインで簡単に見つけることができます)は、世界中のすべてのデータベースのすべてのユーザーで使用できます。
サイト固有のソルトを使用すると、攻撃者は自分でテーブルを計算する必要があり、サイトのすべてのユーザーでそれを使用できます。
ユーザーごとのソルトを使用する場合、攻撃者はこの努力をすべてのユーザーに個別に費やさなければなりません。
もちろん、これは本当に弱いパスワードを辞書から直接保護するためにはあまり効果がありませんが、この償却に対してかなり強力なパスワードを保護します。
また、もう1つ重要な点として、USER固有のソルトを使用すると、同じパスワードを持つ2人のユーザーが検出されなくなり、ハッシュが一致します。それがハッシュがハッシュである理由です(塩+ユーザー名+パスワード)
ハッシュを秘密にしようとすると、攻撃者はハッシュを検証することもできません。
編集-要点が上のコメントで行われたことに気づきました。
レインボーテーブル攻撃を防ぐためにソルトが実装されています。レインボーテーブルは、事前に計算されたハッシュのリストであり、ハッシュからフレーズへの変換がはるかに簡単になります。現代のハッシュアルゴリズムがない限り、ソルトはパスワードを解読する現代の防止策としては効果的ではないことを理解する必要があります。
したがって、このアルゴで発見された最近のエクスプロイトを利用して、SHA1で作業しているとしましょう。また、1,000,000ハッシュ/秒で実行しているコンピューターがあるとしましょう 衝突を見つけるのに530万万年かかるでしょう) なので、ええphpは300秒/秒で動作しますが、大きな問題ではありません。私たちがソルトを使用するのは、誰かがすべての一般的な辞書フレーズを生成するのに面倒だった場合(2 ^ 160人、2007年のエクスプロイトへようこそ)のためです。
これが実際のデータベースで、テストと管理の目的で2人のユーザーを使用しています。
_RegistrationTime UserName UserPass
1280185359.365591 briang a50b63e927b3aebfc20cd783e0fc5321b0e5e8b5
1281546174.065087 test 5872548f2abfef8cb729cac14bc979462798d023
_
実際、ソルトスキームは、sha1(登録時間+ユーザー名)です。どうぞ、私のパスワードを教えてください。これらは本番のパスワードです。そこに座って、phpでWordリストをハッシュ化することもできます。ワイルドに。
私は狂っていません、これが安全であることを知っています。面白くするために、テストのパスワードはtest
です。 sha1(sha1(1281546174.065087 + test) + test) = 5872548f2abfef8cb729cac14bc979462798d023
このユーザーのjustには、_27662aee8eee1cb5ab4917b09bdba31d091ab732
_が付加されたRainbowテーブル全体を生成する必要があります。つまり、1つのRainbowテーブルによってすべてのパスワードが危険にさらされるのを防ぐことができます。ハッカーは、テストのために27662aee8eee1cb5ab4917b09bdba31d091ab732のRainbowテーブル全体を生成し、再度briangのためにf3f7735311217529f2e020468004a2aa5b3dee7fを生成する必要があります。すべてのハッシュについて530万万年を思い出してください。 2 ^ 80ハッシュ(20をはるかに超える yottabytes )を格納するだけのサイズを考えてみてください。
ソルトを、デコードできないものにするハッシュの手段と混同しないでください。これは、Rainbowテーブルがallを変換しないようにする手段ですユーザーパスワード。このレベルのテクノロジーでは不可能です。
辞書攻撃の背後にある考え方は、ハッシュを取得して、このハッシュが計算されたパスワードを見つけるというものですなしハッシュ計算。ソルトパスワードでも同じことをしてください-できません。
Saltを使用しないと、データベースでの検索と同じくらい簡単にパスワードを検索できます。 saltを追加すると、攻撃者は可能なすべてのパスワードのハッシュ計算を実行します(ディクショナリのアタッチの場合でも、これにより攻撃時間が大幅に増加します)。
単純にソルティングを使用しても、ハッシュ(ブルートフォースまたはディクショナリ)からのハッシュを防ぐことはできません。攻撃者は、ソルティングアルゴリズムを見つける必要があります(適切に実装されている場合、より多くの反復を使用します)またはアルゴをブルートフォースしますが、非常に単純な場合を除き、ほとんど不可能です。ソルティングは、レインボーテーブルルックアップのオプションもほぼ完全に破棄します...
簡単に言えば、ソルトを使用せずに、各候補パスワードを1回ハッシュするだけで、「既知のユニバース」(侵害されたデータベースのコレクション)内のすべてのユーザーに対して、同じアルゴリズムでパスワードがハッシュされます。ソルトでは、可能なソルト値の数が「既知のユニバース」内のユーザー数を大幅に超える場合、候補となる各パスワードを、テスト対象のユーザーごとに個別にハッシュする必要があります。
Saltは Rainbow table 攻撃をはるかに困難にします。単一のパスワードハッシュを解読するのがはるかに難しくなるからです。 1という数字の恐ろしいパスワードを想像してみてください。Rainbowテーブル攻撃はこれをすぐに解読します。
ここで、dbの各パスワードが、多くのランダムな文字の長いランダムな値でソルトされていると想像してください。これで、お粗末なパスワード「1」は、1のハッシュとランダムな文字の束(ソルト)としてdbに格納されるため、この例では、Rainbowテーブルに次のようなハッシュが必要です。1。
したがって、ソルトが安全でランダムなものであると想定すると、()%ISLDGHASKLU(%#%#とすると、ハッカーのレインボーテーブルには、 1 *()%ISLDGHASKLU(*%#%#。この単純なパスワードでもレインボーテーブルを使用することは、もはや実用的ではありません。