56

ログインシステムにsaltを実装したいのですが、これがどのように機能するかについて少し混乱しています。その背後にある論理が理解できません。md5は一方向のアルゴリズムであり、私が遭遇したすべての関数はすべてを一緒にハッシュしているように見えることを理解しています。この場合、比較のためにパスワードを元に戻すにはどうすればよいですか?私の最大の質問は、単にパスワードをハッシュするよりも、ユーザーのパスワードをソルトする方が安全なのかということです。データベースが危険にさらされた場合、ソルトとともにハッシュがデータベースにあります。ハッカーが必要とするのはこれだけではありませんか?

私はまた、別の開発者が言ったSOに関する別の投稿を見つけました:

「ソルトとアルゴリズムがデータベースとは別に保存されていることを確認してください」

ソルトをデータベースに保存したいのですが。私がそうするなら、これは本当に問題ですか?

これがどのように機能するか、またベストプラクティスが何であるかを理解するための助けを探しています。どんな助けでも大歓迎です。


編集:私は皆の反応とアイデアに感謝したいと思います。今はもっと混乱しているかもしれませんが、それは確かに私にとって学習体験でした。みんなありがとう。

4

8 に答える 8

34

ソルトのポイントは、事前計算されたレインボー テーブルを使用して、攻撃者がサイト間でブルート フォース攻撃のコストを償却するのを防ぐことです (または、ユーザーごとに異なるソルトを使用する場合: サイトのすべてのユーザー) 。

単純なハッシュを使用すると、攻撃者はそのようなテーブルを 1 回 (非常に時間とコストのかかる操作) 計算し、それを使用して任意のサイトのパスワードをすばやく見つけることができます。サイトが 1 つの固定ソルトを使用する場合、攻撃者はそのサイト専用の新しいテーブルを計算する必要があります。サイトがユーザーごとに異なるソルトを使用している場合、攻撃者はレインボー テーブルに煩わされるのをやめることができます。攻撃者は、個々のパスワードを個別にブルート フォースする必要があります。

この利点を得るために、塩を別々に保管する必要はありません。理論的には、辞書や短いパスワードの弱点を中和するため、さらに安全になります. 実際には、一日の終わりに、パスワードをチェックするためにどこかでソルトにアクセスする必要があるため、気にする価値はありません。また、それらを分離しようとすると、システムがより複雑になり、システムが複雑になればなるほど、セキュリティ ホールが発生する可能性が高くなります。

編集:私の具体的な推奨事項:

于 2010-02-02T23:57:51.230 に答える
20

ハッシュ関数は、同じ入力文字列に対して常に同じ値を返します。私のユーザー (Alice) がパスワードを持っているとしましょうsecretsecretを使用したハッシュmd5()は、次のハッシュにつながります

5ebe2294ecd0e0f08eab7690d2a6ee69

辞書 (一般的な単語とパスワードのリスト) またはそのサービスを提供するさまざまなサイトの 1 つを使用して、攻撃者 (Mallory) は自分の辞書に5ebe2294ecd0e0f08eab7690d2a6ee69 = secret.

ハッシュする前にソルトするプロセスにより、ソルトを知らずに辞書攻撃を使用することが難しくなります。次の点を考慮してください。

<?php
$salt = '@!#%$@#$@SADLkwod,sdaDwqksjaoidjwq@#@!';
$hash = md5($salt . 'secret');

結果のハッシュは nowb58ad809eece17322de5024d79299f8aですが、Alice のパスワードはまだsecretです。マロリーがソルトハッシュを手に入れたとしても、彼女の辞書に答えが見つからない可能性があります. もしそうなら、辞書は彼女に間違った答えを与えるでしょう.

データベースに静的ソルトを保存しないでください。アプリケーションの構成とともに保存することをお勧めします (ちなみに、Web からは使用できません)。

動的ソルトを使用する場合は、データベースを使用する必要があります。既存の有効なデータの null 以外の列を使用してソルトを構築します (秘密の暗号化キーに基づくフグ暗号化されたユーザー名の文字列は、通常、暗号的に安全です)。塩には別のカラムを使用しないでください。既存の列を使用できない場合は、ソルトをハッシュと同じ列に組み込みます。たとえば、最初の 32 文字を 128 ビットのソルトに使用し、最後の 40 文字を 160 ビットのハッシュに使用します。次の関数は、そのようなハッシュを生成します。

function seeded_sha1($string, $seed_bits) {
    if(($seed_bits % 8) != 0) {
        throw new Exception('bits must be divisible by 8');
    }

    $salt = '';
    for($i = 0; $i < $seed_bits; $i+=8) {
        $salt .= pack('c', mt_rand());
    }

    $hexsalt = unpack('h*hex', $salt);

    return $hexsalt['hex'] . sha1($salt . $string);
}

function compare_seeded_sha1($plain, $hash) {
    $sha1 = substr($hash, -40);
    $salt = pack('h*', substr($hash, 0, -40));

    $plain_hash = sha1($salt . $plain);
    return ($plain_hash == $sha1);
}

攻撃者が SQL インジェクションを使用してデータベースに侵入した場合、攻撃者はアプリケーション構成にアクセスできないため、少なくとも取得したハッシュは役に立ちません。サーバーがルート化されると、何をしてもほとんどゲームオーバーです。

注:md5()たとえば、より安全なハッシュ アルゴリズムを使用する理由として、他の種類の攻撃が考えられsha1()ます。または、さらに良いのは、セキュリティを考慮して設計され、ほぼすべての PHP バージョンと下位互換性があるポータブル PHP パスワード ハッシュ フレームワークを使用することです。

require('PasswordHash.php');

$pwdHasher = new PasswordHash(8, FALSE);

// $hash is what you would store in your database
$hash = $pwdHasher->HashPassword( $password );

// $hash would be the $hashed stored in your database for this user
$checked = $pwdHasher->CheckPassword($password, $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}
于 2010-02-02T23:24:52.370 に答える
15

ソルトの使用を忘れて(一部はあなたが言及した理由で)、代わりに bcrypt を使用してください:

詳しい説明については、http: //codahale.com/how-to-safely-store-a-password/を参照してください。

于 2010-02-02T23:22:13.953 に答える
7

他の答えは良いので、他の誰も言及していない小さな点を入れておきます。すべてのパスワードに同じソルトを使用したくない場合は、2 人のユーザーが同じパスワードを使用すると、同じハッシュを持つことになります。これは、攻撃者が悪用できる情報を公開しています。

すべてのユーザーに同じソルトを使用し、パスワードを他の変更されないデータベース フィールド (ユーザーに固有) と組み合わせるという Juraj の優れたアイデアと共に使用できます。ただし、この情報はパスワードに関連付けられているため、注意してください。一意のハッシュを保証するためにユーザー名とパスワードを一緒にハッシュする場合、新しいユーザーを作成して新しいパスワードを設定することを要求しない限り、ユーザー名を変更することはできません。

ユーザーごとに固有のソルトを持ち、それをパスワード ハッシュと一緒に保存する例として、一般的な Linux システムの/etc/shadowを指摘します。

root@linux:/root# cat /etc/shadow | grep root
root:$1$oL5TTZxL$RhfGUZSbFwQN6jnX5D.Ck/:12139:0:99999:7:::

ここで、oL5TTZxLはソルトで、RhfGUZSbFwQN6jnX5D.Ck/はハッシュです。この場合、プレーンテキストのパスワードはrootであり、私のシステムが使用するハッシュ アルゴリズムは MD5 ベースの BSD パスワード アルゴリズムです。(私のシステムよりも新しいシステムは、より優れたハッシュ アルゴリズムを備えています)

于 2010-02-03T00:41:48.283 に答える
5

比較のためにパスワードを取得することはありません。ログインを試みるときにパスワードを暗号化し、保存されている値を新しく暗号化された値と比較します。

于 2010-02-02T23:19:01.430 に答える
2

パスワードのハッシュは、これらのパスワードを自分の管理者から秘密にしておくことを目的としています。

1) データベースに平文のパスワードを保持することは問題ありませんが、パスワードが管理者によって他のシステムへのアクセスに使用される可能性がある場合を除きます。

2) 単一のグローバル ソルトを使用できます。このソルトは、パスワードと組み合わせて (先頭に追加するか XOR することによって)、データベースに格納するためにハッシュします。しかし、それは悪意のある管理者と、その 1 つのソルト用に設計されたレインボー テーブルに対して脆弱です。

3) 各ユーザーに個別のソルトを設定できます。データベースはソルトを格納するために使用され、パスワードとソルトの組み合わせから派生したハッシュが使用されます。これによりレインボー アタックを防ぐことができますが、ブルート フォース アタックは依然として可能です。

4) 最後に、速度制限のあるハードウェア ハッシュ ソリューションを使用して、ハッシュ関数を秘密に保つことができます。

それはあなたができるのと同じくらい良いことです。人間の性質上、パスワードのドメインは限定されており、ブルート フォース攻撃に対して脆弱です。私たちは、管理者がユーザーのパスワードを入手し、アクセスしてはならない他のシステムでそれらを使用することを防止しようとしています。

その他の注意事項:

a) パスワードとソルトの組み合わせで bcrypt を使用して、攻撃者のブルート フォース攻撃を遅くすることができます。ただし、管理者を想定しているため、管理者は辛抱強く待つことができます。

b) ソルトをパスワード ハッシュから分離しておくことは有効な防御策ではありません。結局のところ、管理者を想定しています。

c) 既存のデータをソルトとして使用するのは少し良いですが、既存のデータがランダムなソルトほどエントロピーを持っているとは思えません。

于 2010-02-03T01:04:58.673 に答える
2

あなたが言ったように、ハッシュアルゴリズムは一方向にしか機能しません (または、十分に強力な場合にのみ:-D)

ソルトに関する質問については、静的なソルト文字列データベースからの動的データを使用してパスワードをハッシュすることをお勧めします。これは、作成後に変更されるべきではありません

これは、パスワードを保存するための非常に安全な方法です。データベースが侵害された場合でも、ハッカー/クラッカーは静的文字列ハッシュを取得する必要があり、すべてのソルティングをどのように適用したかを推測する必要があります..

たとえばusers、次の列を持つテーブルがあるとします。

id
username
password
created_at

idおよびcreated_atは、一度入力された後は決して変更されるべきではありません..

したがって、ユーザーのパスワードをハッシュするときは、次のように簡単に実行できます。

<?php
    $staticSalt = '!241@kadl;ap][';
    $userPass = 'my new pass';
    // assuming $user variable is already populated with DB data
    // we will generate new hash from columns and static salt:
    $genPass = sha1($user['id'] . $userPass . $user['created_at'] . $staticSalt);
?>

これが役立つことを願っています:)乾杯

于 2010-02-02T23:28:24.870 に答える
1

ユーザーのパスワードをソルトすることは、事前計算攻撃から保護できるため、パスワードを単にハッシュするよりもおそらく安全です。

たとえば、ハッカーがデータベースにアクセスし、パスワードがソルト化されていない場合、ハッシュのデータベース ( http://en.wikipedia.org/wiki/Rainbow_tableを参照) でハッシュを検索して、元のパスワード。

于 2010-02-02T23:27:25.703 に答える