ログインにパスワードが必要なシステムがある場合、平文のパスワードではなく、必要なパスワードのハッシュ化およびソルト処理されたコピーを保存する必要があることを誰もが知っています。
今日私が疑問に思い始めたのは、ユーザーIDも同様のハッシュ化およびソルト化されたパスワードに保存しないのはなぜですか?
私にとっては、欠点が見当たらないため、これは理にかなっているように思われます。dbが侵害された場合、攻撃者はそのアカウントを侵害する前にパスワードとユーザー名のハッシュを「解読」する必要があります。また、ユーザー名がハッシュ化され、電子メールアドレスがソルト化されている場合、SPAMmerに販売されないように保護されます。
Terryの発言は真実ですが、ログインシステムは実際にユーザー名をハッシュします(ただし、saltは使用しません)。ログイン名と表示名を選択してもらいます。ログイン名はハッシュされて保存され(検索できるようにするためにソルトなしで)、パスワードはソルトされます。表示名はログイン名とは異なり(これも秘密にしておく必要があるため)、必要に応じて表示されます。
攻撃者があなたの名前を見た場合でも、それをログイン名に添付することはできません。塩漬けできると言いますが、実際にはこれは必要ありません。最も重要な部分は、それを秘密にしておくことです。データベースが危険にさらされても、攻撃者が他のアカウントに新たな攻撃を仕掛けようとする場合、電子メールアドレスや名前などが引き続き使用されます。
そこにあなたのユーザー名が表示されているのがわかりますか?ユーザー名がハッシュされて保存されている場合、彼らはそれを行うことができませんか?
一言、使いやすさ。
通常、ユーザー名は安全であるとは見なされず、認証ではなくIDです。どのユーザー名が有効であるかを明らかにしないのは良いことですが、たまたま衝突があった場合はさらに悪くなります。一致するすべてのユーザー名を調べて、一致するパスワードハッシュを探すことで、これを回避することもできますが、これはちょっと面倒です。
現実的には、パスワードのセキュリティが良好で、ログイン試行が制限されている場合、ユーザー名の完全なリストは攻撃者にとって実用的な価値がほとんどありません。主な利点はフィッシングですが、公式な通信に情報が含まれている場合、その情報をハッシュすることはできません。
また、テリーのような使いやすさも語った。ユーザー名が表示されていれば、アカウントを見つけやすくなります。ほとんどのコンテキストでそれを正当化するために識別子を確保しようとしても十分ではありません。
他の人からは利点がほとんどない(あるとしても)とよく指摘されていますが、欠点がないというあなたの主張に異議を唱えます。ハッシュされたユーザー名のみを保存すると、ユーザー名の検索が簡単になります。ハッシュ化されたユーザー名を保存すると、検索が少し難しくなります。
ユーザー名と(ハッシュされた)パスワードを含むSQLテーブルを作成し、SQLサーバーにユーザー名列にインデックスを付けるように指示すると、何らかのバイナリ検索やその他の魔法が実行されると仮定しましょう。次のようなテーブルを作成できます。
Username | Password
test | j9lnvqjAuhNJs
(これは、単純さと簡潔さのために、昔ながらのunix crypt(3)ハッシュです。)
ユーザー名をプレーンテキストで保存する場合、ユーザーの(ハッシュされた)パスワードを取得するのは簡単なSQL呼び出しです。ユーザー名test
を入力したユーザーの認証情報を検証するとします。
SELECT password FROM users WHERE username='test`;
十分に単純です。ユーザー名をパスワードと同じ形式で保存すると、テーブルは次のようになります。
Username | Password
M1CAtvzDdJDGU | j9lnvqjAuhNJs
ここで、ユーザーがtest
のユーザー名を入力すると、パスワードをどのように検証しますか?ユーザー名の保存に使用したソルトさえ知らないため、ここではバイナリ検索は役に立ちません。代わりに、データベース内の各ユーザー名を反復処理し、指定されたユーザー名をそのユーザー名のソルトでcrypt
ingし、格納されている(ハッシュされた)ユーザー名と比較して、一致するかどうかを確認する必要があります。ユーッチ!
良い予防策を講じて、古き良きUnix cryptの代わりにbcrypt
のようなナイススローハッシュを使用したとしましょう。ダブルユーッチ!
ご想像のとおり、プレーンテキストだけでなく、ソルトハッシュされたユーザー名を格納することには、いくつかの重大な欠点があります。
あなたのアイデアは高貴で、質問は興味深いものです。さて、あなたはどちらかがユーザビリティについてまったく考えなかったと思いますorあなたはハッシュ(または多分あなたのポイントを逃しました「暗号化」のスペルを間違えただけです)。
強力な処理を行うスーパーコンピューターや、ハッシュを検索するレインボーテーブルがない限り、ハッシュは元に戻せません。したがって、ログインに使用するユーザー名/電子メールをハッシュすると、使いやすさが低下します。ただし、プログラム(ユーザー名をチェックするもの)自体に事前定義されたキーを使用して同じものを「暗号化」する場合は、少し安全な場合があります。ただし、繰り返しになりますが、プログラムに直接格納されている暗号化キーは、キーがまったくない場合と同じくらい優れています。これらが、ユーザー名がハッシュ化または暗号化されない主な理由です。
最も可能性の高い理由は、ユーザー名とパスワードをハッシュしても実際には特別な保護が提供されないためだと思います。
私たちは、ユーザーに解読しにくいように難しく複雑なパスワードを作成することをお勧めします。ハッシュされたユーザー名のデータベースは、基本的な辞書を使って数分で解読される可能性があります...ユーザー名に少なくとも6文字の英数字が必要でない限り;)
ユーザー名をハッシュしてソルトした場合、システムは、既存のすべてのレコードを繰り返し処理することなく、新しいユーザー名をすべての既存のソルトでハッシュせずに、新しいアカウントが一意のユーザー名を持っていることをどのようにして知るでしょうか?
この考え方は、1)あいまいさによるセキュリティ、2)タイミング攻撃の追加の緩和(タイミングセーフな比較機能を使用する場合)の2つの戦術と一致しています。独自のソルトを使用してこれを効果的に行うことはできませんが、それは良い考えです。これにより、ログイン情報を保持するテーブルと「個人」情報を保持するテーブルを分離できます。次に、2つのテーブル、person(プレーンテキストの電子メールアドレスを保持できる)とuser(ハッシュされたユーザー名{site wide salted}とハッシュされ、一意にソルトされたパスワードを保持できる)を示します。ハッシュされたユーザー名でユーザーを検索することは問題ありません。
これは素晴らしいアイデアだと思います。アンソニー・ラトリッジが表明したように;これにより、あいまい化/難読化によってセキュリティを提供できます。また、PBKDF2などの鍵導出関数を使用すると、盗まれたデータベースを侵害しようとする攻撃者にとって、桁違いに困難さが増すと思います。
たとえば、盗まれたデータベースに対してオフラインのブルートフォース攻撃を行おうとすると、前述のようにメソッド内でのユーザー名のソルティングによって特定されたユーザー名の衝突が疑われるにもかかわらず、ユーザー名とパスワードの両方でハッシュの衝突を見つける必要があります。 。
つまり、ソルトはデータベース内のどこにも存在しないため、攻撃者はマシンを指揮し、ソースコードを特定して理解する必要があります。 Webアプリケーションの計算負荷を大幅に増加させることなく、多層防御を追加します。
ハッシュに関する問題:ユーザー名は、実際のユーザー名/メールに基づいて、独自のサーバー側ハッシュでソルトできます。
これは、プログラム上ではありますが、塩が既知であることを意味します。また、ソルトを計算して返すスクリプトは、Webサービスと比較して、帯域外の方法でマシンに常駐できます。これにより、ソルトを生成するためのどのメソッドにも、任意のWeb向けエントリポイントからアクセスできなくなります。