web-dev-qa-db-ja.com

time()は良い塩ですか?

自分で書いたことがないコードを見ています。コードはSHA512でパスワードをハッシュしようとし、ソルトとしてtime()だけを使用します。 time()はこれには単純すぎますか、それともこのコードは安全ですか?

回答とコメントをありがとう。新しい読者のために、ここで要約します。

  • ソルトはユーザーごとに異なる必要があるため、2人のユーザーが同時に登録した場合、ソルトは一意ではありません。これは問題ですが、大きな問題ではありません。
  • ただし、saltはユーザーとはまったく関係がないため、time()は適切なsaltではありません。
  • "ランダムで均等に分散された高エントロピーソルトを使用します。"-これは一口です。どのコードがrandom, evenly distributed, high entropyソルトを生成する可能性がありますか?

では、time()を32文字のランダムな文字列に置き換えてみませんか。ランダムな文字列は、アルファベット文字のセットを32回ループすることで生成できます。それはいいですね。

57
zmol

短い答え:

いいえ、time()は良い塩ではありません。

長い答え:

私の答えからコピー 塩の生成とオープンソースソフトウェア

塩とは何ですか?

ソルトは、ハッシュアルゴリズムの入力に追加されるrandom固定長のバイトのセットです。


ハッシュのソルティング(またはシード)が役立つのはなぜですか?

ハッシュにランダムソルトを追加すると、同じパスワードで多くの異なるハッシュが生成されます。ソルトは通常、ハッシュ関数の結果とともにデータベースに保存されます。ハッシュのソルトは、いくつかの理由で適しています。

  1. 塩漬けは、事前に計算された攻撃の難易度/コストを大幅に増加させます( レインボーテーブル を含む)
  2. ソルトは、同じパスワードが同じハッシュにならないようにします。これにより、2人のユーザーが同じパスワードを持っているかどうかを判断できなくなります。また、さらに重要の場合、同じ人が異なるシステム間で同じパスワードを使用しているかどうかを判断することはできません。
  3. ソルトはパスワードの複雑さを増し、それによって両方の有効性を大幅に低下させます辞書- そして誕生日攻撃 (これは、ソルトisがハッシュとは別に保存されている場合にのみ当てはまります)。
  4. 適切なソルティングgreatlyは、事前計算攻撃のストレージの必要性を、実用的でなくなるまで増加させます。 (16ビットソルトを使用して128ビット値にハッシュされた8文字の大文字と小文字を区別する英数字のパスワードは、Rainbow削減なしで 200未満exabytes を使用します)。


塩を秘密にする必要はありません。

ソルトは秘密鍵ではなく、ハッシュ関数を各インスタンスに固有にすることで「機能」します。ソルトハッシュでは、oneハッシュ関数はありませんが、可能なソルト値ごとに1つあります。これにより、攻撃者が[〜#〜] n [〜#〜]ハッシュされたパスワードを[〜#〜]未満で攻撃するのを防ぎます。 n [〜#〜]1つのパスワードを攻撃するコストの1倍。これが塩のポイントです。
「シークレットソルト」はソルトではなく、「キー」と呼ばれ、ハッシュを計算しなくなったことを意味しますが、 メッセージ認証コード (MAC) 。 MACの計算はトリッキーなビジネスであり(キーと値をハッシュ関数に単純に打ち込むよりもはるかにトリッキーです)、まったく異なるテーマです。

ソルトは、それが使用されるすべてのインスタンスに対してランダムである必要があります。これにより、攻撃者はすべてのソルトハッシュを個別に攻撃する必要があります。
ソルト(またはソルティングアルゴリズム)が秘密であることに依存している場合は、 隠すことによるセキュリティ (機能しません)の領域に入ります。おそらく、あなたは塩の秘密から追加のセキュリティを得ることはありません。暖かくファジーな安心感が得られます。したがって、システムをより安全にする代わりに、現実から気をそらすだけです。


では、なぜ塩はランダムでなければならないのですか?

技術的には、ソルトはuniqueである必要があります。ソルトのポイントは、ハッシュされたパスワードごとに区別することです。これはworldwideを意味します。独自のソルトをオンデマンドで配布する中央組織がないため、次善の策に頼る必要があります。これは、予測できないランダムジェネレーターを使用したランダム選択であり、衝突を起こりにくくするのに十分な大きさのソルトスペース内で行うことが望ましいです(同じものを使用する2つのインスタンス塩分値)。

ユーザーIDなど、「おそらく一意」であるデータからソルトを導き出そうとするのは魅力的ですが、そのようなスキームは、いくつかの厄介な詳細のために失敗することがよくあります。

  1. たとえばユーザーID を使用すると、別のシステムを攻撃する悪意のあるユーザーが、リソースをプールして、ユーザーID 1〜50の事前計算されたテーブルを作成する場合があります。ユーザーIDは一意ですsystem-wideただしworldwideではありません。

  2. 同じことが username にも当てはまります。Unixシステムごとに1つの「ルート」がありますが、世界には多くのルートがあります。 「ルート」のレインボーテーブルは、何百万ものシステムに適用できるため、努力する価値があります。さらに悪いことに、そこには多くの「ボブ」もあり、多くはシステム管理者のトレーニングを受けていません。パスワードが非常に弱い可能性があります。

  3. 一意性も一時的なものです。ユーザーがパスワードを変更することがあります。 新しいパスワードごとに、新しいソルトを選択する必要があります。そうしないと、攻撃者が古いパスワードのハッシュを取得し、新しいパスワードのハッシュが両方を同時に攻撃しようとする可能性があります。

暗号的に安全で予測不可能なPRNGはある種のやり過ぎかもしれませんが、少なくともおそらくから取得したランダムソルトを使用すると、これは、攻撃者がpersonalソルトとは何かを知るのを妨げることではなく、かなりの数で使用される大きな太いターゲットを攻撃者に与えないことです。ランダムな選択により、ターゲットは実用的な範囲で薄くなります。


結論として:

ランダムで均等に分布した高エントロピーの塩を使用します。新しいパスワードを作成したり、パスワードを変更したりするときは、常に新しいソルトを使用してください。ハッシュされたパスワードと一緒にソルトを保存します。大きな塩(少なくとも10バイト、できれば16以上)を優先します。

ソルトは悪いパスワードを良いパスワードに変えません。攻撃者が少なくともeach不正なパスワードに対して辞書攻撃の代償を払うことを確認するだけです。


有用な情報源:
stackoverflow.com:パスワードハッシュの非ランダムソルト
ブルース・シュナイアー:実用的な暗号化 (本)
Matasano Security:レインボーテーブルで十分
senix.org:Unixcryptは1976年以来saltを使用しています
owasp.orgソルトを追加する理由
openwall.comSalts

免責事項:
私はセキュリティの専門家ではありません。 (この回答は Thomas Pornin によってレビューされましたが)
そこにいるセキュリティ専門家のいずれかが何か問題を見つけた場合は、コメントするか、このwikiの回答を編集してください。


あなたのランダムソルトの良い情報源と思われるものについて
また読む: 乱数生成のための最も安全なシードは何ですか?
専用のハードウェアベースのランダムジェネレーターがない場合、ランダムデータを取得する最良の方法は、オペレーティングシステムに問い合わせることです(Linuxでは、これは_/dev/random_または_/dev/urandom_と呼ばれます[両方利点と問題がある場合は、毒を選択してください]; Windowsでは、CryptGenRandom())を呼び出します。

何らかの理由で上記のランダムなソースにアクセスできない場合は、PHPで、次の関数を使用できます。
phpass v0. のソースから

_<?php
/**
 * Generate pseudo random bits
 * @copyright: public domain
 * @link http://www.openwall.com/phpass/
 * @param int $length number of bits to generate
 * @return string A string with the hexadecimal number
 * @note don't try to improve this, you will likely just ruin it
 */
function random_bits($entropy) {
    $entropy /= 8;
    $state = uniqid();
    $str = '';
    for ($i = 0; $i < $entropy; $i += 16) {
        $state = md5(microtime().$state);
        $str .= md5($state, true);
    }
    $str = unpack('H*', substr($str, 0, $entropy));
    // for some weird reason, on some machines 32 bits binary data comes out as 65! hex characters!?
    // so, added the substr
    return substr(str_pad($str[1], $entropy*2, '0'), 0, $entropy*2);
}
?>
_
83
Jacco

この投稿は、元の質問から少し離れすぎている可能性がありますが、お役に立てば幸いです。

セキュリティとは、障壁やハードルを上げることです。多層防御。真に安全なハッシュソリューションはありません。壊れにくいものだけです。それはあなたの家に盗難警報器と窓の鍵をかけるようなものです-あなたのサイトを他の誰かよりも侵入するのを魅力的にしません。

暗号化アルゴリズムのソルトは、セキュリティ問題のごく一部にすぎません。単一のソルトは、複数のユーザーのパスワードを破ろうとするときに理解することが1つ少ないことを意味します。低エントロピーソルト(サーバーの時間など)は少し難しくなり、高エントロピーソルトはさらに難しくなります。これらのどれを使用するか、そしてそれがあなたが心配する必要があるものであるかどうかは、主にあなたが保護しているデータの機密性だけでなく、あなたが実施している他のセキュリティ対策の両方に依存します。選択した都市のパーソナライズされた天気予報を提供するだけのサイトは、自宅の住所、母親の旧姓、生年月日、その他の識別目的で使用できる情報を含むサイトよりも、明らかに機密性の低いデータを持っています。

だからここにこすりがあります。高エントロピーの塩は、簡単に入手できるのであれば、それでも悪い塩です。

現実の世界では、データベースにソルトを保存することは(ランダムかどうかにかかわらず)、一定のソルトを使用して、Webブラウザーからアクセスできないファイルに個人の目からそれを埋めるよりもおそらく安全性が低くなります。ユニークで高いエントロピーソルトを推測するのは難しいですが、MySql上の任意のサーバーからのrootログインを許可し、パスワードを「password」に設定した場合、それは実際には問題ではありません。サーバーへの有効なログインを取得するのと比べて、データベースをクラックするのがいかに簡単かを比較してください。セットアップによっては、fail2banやその他の攻撃ベクトルウォッチャーを配置できるため、個別に行うのはおそらく難しいでしょう。

ソルト自体ではなく、ユーザー固有のソルトを含むファイルの場所をデータベースに保存することで、2つのアプローチを組み合わせることができます。ファイルシステムとデータベースの両方をクラックする必要があるかどうかは、保護しようとしているデータの機密性がこのオーバーヘッドを保証するかどうかによって異なります。

セキュリティの専門家からの別の代替の推奨事項は、ユーザー名を別のデータベース(理想的には異なるテクノロジー)にパスワードとは別に保存し、UUIDを使用して2つの間を参照することです。例えば。 MySQLとSQLiteの両方を使用します。これは、両方のデータベースをクラックする必要があることを意味します(また、例のために別のウサギの穴を掘り下げるために、ユーザーの詳細とクレジットカード番号を同じデータベースに保存しないでください。他)。

SHA-512やBlowfishな​​どのアルゴリズムは、ハッシュの一部としてソルトを返すことができることに注意してください。アルゴリズムを提供する完全なハッシュを保存するかのようにこれらに注意してください。つまり、ハッカーが理解することが2つ少なくなります(ソルトもアルゴリズムを提供します)。

辞書攻撃が失敗するように、強力なパスワードとユーザー名を適用するようにしてください。 MD5のユーザー名/パスワードエントリの6文字の英数字の組み合わせすべての辞書を知っていますが、あらゆる種類のアルゴリズムでこれ以上のものがあると思います。低コストのクラウドとCPGPUコンピューティングの爆発的な増加に伴い、利用可能な辞書のサイズと複雑さが爆発的に増加します。

最終的に、最も安全な方法は、プログラムでソルトを生成することは決してありませんが、SSLリンクを介してユーザー名とパスワードとともにソルトを入力する必要があります(したがって、スヌープすることはできません)が、保存しないでください。これはクレジットカード会社が採用しているアプローチです。つまり、クレジットカードの3桁のCSVセキュリティキー。オンラインで購入するたびに入力する必要があります。これは、データベースに保存してはならないためです。本当にソルトを生成したい場合は、別々に送信し(たとえば、SMSメッセージまたはEメール))、毎回手動で入力させます。このアプローチでは、より安全ですが、複雑さを、ユーザーがサイトに煩わされるのを難しくしすぎたためにユーザーがサイトの使用をやめるかどうかと対比する必要があります。

上記のすべては、セッションハイジャック、クロスサイトスクリプティングなどに対する保護も実施されているという事実に依然依存しています。私が行う必要があるのが有効なPHPSESSIDを計算することだけである場合、世界最強のパスワードアルゴリズムは関係ありません。ログインしたユーザーをハイジャックしてください!

私はセキュリティの専門家ではありませんが、合理的にできる限りこれを読んでいます。このテーマに関する本がたくさんあるという事実は、あなたの質問に対する答えが本当にどれほど大きいかを示しています。

私が非常に貴重だと思った、あなたが試してみたいと思うかもしれない本当に素晴らしい本がいくつかあります。

Webアプリケーションの脆弱性の検出、悪用、防止-ISBN-13:978-1-59749-209-6

ApacheによるWeb攻撃の防止-ISBN-13:978-0-321-32128-2

2
Matt

更新

それは本当に良い塩ではありませんが、おそらく最も断固とした機知に富んだ攻撃者を除いてすべてを倒すのに十分です。良い塩の要件は次のとおりです。

  • ユーザーごとに異なります
  • ソルトと(潜在的に弱い)パスワードの連結をブルートフォース攻撃には長すぎるようにするのに十分な長さ(少なくとも英数字の8文字)。

time()値は10文字であるため、実際には十分な長さではありませんが、数字のみです。

また、2人のユーザーが同じ秒内に作成されたときに、同じ値を取得する場合があります。しかし、それは、同じ秒内に多くのユーザーが自動的に作成される状況がある場合にのみ問題になります。

いずれにせよ、完璧なソルトよりもはるかに重要なのは、優れたハッシュ関数を使用することです。SHA512は、現在利用できる最高のものの1つです。

2

はい。
「Membersince」フィールドとしてユーザーデータベースに保存されているUNIXタイムスタンプは、まともな塩になるようです。

ただし、塩の質問は最も無視できるものです。あなたが注意を払わなければならないはるかに重要なことがあります:

  1. ほとんどの場合、パスワードもソルトまたはハッシュアルゴリズムも、サイトの最も弱い部分にはなりません。いくつかのラメファイルインジェクションまたはXSSまたはCSRFは確かにそうです。ですから、あまり大したことはしないでください。
    典型的なWebアプリケーションで32文字の真のランダムな文字列について話すことは、木造の納屋にある32インチの装甲ドアについて話すようなものです。

  2. パスワードについて言えば、これまでで最も重要重要なのはパスワードの複雑さパスワードが弱いと、ソルトもハッシュアルゴリズムも、非常に独創的で信じられないほど難しいものであっても、役に立ちません。複雑なパスワードを使用するようにユーザーに依頼するのは面倒ですが、それがないと、他のすべてががらくたになります。
    したがって、最初に懸念するのはパスワードの複雑さです。数字や句読点など、大文字と小文字が異なる12〜16文字が必要です。

  3. 塩は 他のユーザーデータと一緒に保存する必要があるため、時間を使用してもメリットはありません。電子メールを使用する方が良いです-それは十分にランダムであり、とにかくすでにそれを持っています。ユーザーがメールを変更した場合は、パスワードを再ハッシュすることを忘れないでください。 UNIXのtimstampはまともな塩になるようで、電子メールやその他のものを使用する必要はありません。

更新
私が見ることができるように、多くの人々はまだポイントを得ることができません。
コメントからその男のように言って

多くのユーザーは弱いパスワードを使用します(私たちはそれらを教育するか、少なくとも試み続けるべきです)が、それは言い訳にはなりません。彼らはまだ良いセキュリティに値する

間違いなく、彼らはそれに値する。しかし、弱いパスワードでは、使命は不可能である。

パスワードが弱い場合、ソルトはパスワードを保護しません。

塩はトピックに10キロバイトのテキストを費やすのにそれほど重要ではありませんが。

1

いいえ、time()は良い塩ではありません

認証に関しては、車輪の再発明をするのではなく、質問に答えるのが最善です、no。 time()の問題:

  • それは予測可能であり、潜在的に発見可能なものと相関しています。これらの問題により、さまざまなハッシュ結果のクロスマッチングが容易になります。
  • 可能な値はそれほど多くありません。上位ビットは変更されないため、最初に表示されるよりもさらに狭いソルトになります。
  • それを使用すると、以前の間違いが繰り返されます。このアプリがfirstの場合、time()を塩、少なくともnew攻撃が必要になります。
1
DigitalRoss

番号!現在の時刻をソルトとして使用しないでください。 Javaで 'SecureRandom'のようなものを使用して、安全なランダムソルトを生成できます。常に予測できない乱数をソルトとして使用してください。
時間をソルトとして使用すると、衝突をある程度まで除去するのに役立ちますが(2人のユーザーが同時に同じパスワードを入力できるため)、パスワードを回復可能にします。

0
Ashwin

メンバーがフォーラム/ウェブサイトに参加する日付は、一般的にオープンにアクセス可能であり、これはtime()と同じであるため、ソルトは役に立たなくなります。

0
Mr Coder

Saltは、パスワードと事前に計算されたハッシュの一致を破ることにより、Rainbow攻撃を防ぐために使用されます。したがって、ソルトの主なタスクは、ユーザー/パスワードレコードごとに異なることです。塩がユーザーごとに異なる限り、塩のランダム化の品質はそれほど重要ではありません。