サーバーに送信する前にユーザーのパスワードをハッシュするWebサイトはほとんどありません。 JavaScriptは、SHAまたはその他のアルゴリズムをサポートしていません。
しかし、SSLにはないクロスサイトリークや悪意のある管理者に対する保護など、かなりの数の利点を考えることができます。
それでは、なぜこの方法がWebサイトでそれほど一般的ではないのでしょうか。
ここでJavaScriptパスワードハッシュの発明者
1998年に私はWikiを構築していました。これは、ログインシステムを使用して構築した最初のWebサイトです。 SSLでホスティングできる余裕はありませんでしたが、インターネットを介して送信されるプレーンテキストのパスワードが心配でした。 CHAP(チャレンジハッシュ認証プロトコル)について読んだところ、JavaScriptで実装できることに気付きました。結局、スタンドアロンプロジェクトとして JavaScript MD5 を公開し、私が開発した最も人気のあるオープンソースになりました。 Wikiがアルファを超えることはありません。
SSLと比較すると、SSLには多くの弱点があります。
私は常にこれらの制限を前もって述べてきました。私は定期的に彼らに火をつけていました。しかし、私は元の原則を今日まで維持しています。何らかの理由でSSLを取得していない場合は、プレーンテキストのパスワードよりも優れています。 2000年代の初めには、多数の大手プロバイダー(特にYahoo!)がこれをログインに使用していました。ログインだけのSSLでもオーバーヘッドが多すぎると彼らは信じていました。 2006年にログインのためだけにSSLに切り替えたと思います。Firesheepがリリースされた2011年頃に、ほとんどのプロバイダーが完全なSSLに切り替えました。
つまり、人々が代わりにSSLを使用するため、クライアント側のハッシュはまれです。
クライアント側のハッシュには、まだいくつかの潜在的な利点があります。
結局のところ、これらの利点はわずかであり、多くの複雑さが追加されます-セキュリティを改善しようとする試みに、より深刻な脆弱性を導入するという実際のリスクがあります。また、パスワードよりも高いセキュリティが必要な場合は、多要素認証の方が適しています。
したがって、2番目の短い答えは次のとおりです:多要素認証は、クライアント側のパスワードハッシュよりも高いセキュリティを提供するためです
この問題を理解するには、まずパスワードをハッシュする理由を理解する必要があります。パスワードをプレーンテキストでサーバーに保存し、送信したパスワードと受信したパスワードを比較することは完全に可能です。パスワードが転送中に保護されている限り、これは安全な認証手段(共有シークレット)です。
パスワードがハッシュ化される理由は、問題が認証ではなくストレージであるためです。サーバーが侵害された場合、攻撃者はユーザーの認証に使用されるシークレットを知っているため、すべてのユーザーアカウントにすぐにアクセスできます。
ハッシュはこれに対する障壁として機能します。サーバーは認証に必要な実際の入力を認識していないため、DBへの侵害があったとしても、攻撃者はユーザーアカウントにアクセスできません。それでも、アプリケーションがチェックするハッシュ値に到達するための入力を把握する必要があります。確かに、すべての値を知っているものに変更することはできますが、これにより急速に疑惑が生じ、システムがシャットダウンして保護されます。
したがって、クライアント側のハッシュの問題は、ハッシュの結果がパスワードではなくパスワードになるということです。攻撃者が公式クライアントを迂回して、完成したハッシュを直接サーバーに送信するのを阻止する方法はありません。認証中にセキュリティの追加(または喪失)はありませんが、ハッシュが保護されるように設計されている状況では、DBに格納されたハッシュは実際にはサーバーに送信される共有シークレットであるため、何も提供されません。
とはいえ、クライアント側のハッシュによって得られる注目すべきことが2つあります。システムの保護にはまったく役立ちませんが、ユーザーの保護に役立つ場合があります。安全にパスワードを送信していない場合、またはクライアントコードが危険にさらされることなく送信が危険にさらされた場合でも、ユーザーのパスワード(他のサイトで再利用される可能性があります)が漏洩するのを防ぎます。
もう1つは、サーバーサイクルを使用せずに(「クライアントが送信する中間パスワード」の長さを延長しながら)、ハッシュの反復を追加してDBに対するオフライン攻撃をより困難にすることができることです。不正なクライアントから長いパスワードを保護するのに十分なサーバーサイクル。繰り返しになりますが、これが提供する主要な保護は、元のパスワードの発見を防ぐことですが、サイトの認証メカニズムの保護には役立ちません。
別の言い方をすれば、多少の保護は提供しますが、サーバーの観点からは、クライアント側のハッシュは、ユーザーの直接パスワードであるかのように処理する必要があります。 これはセキュリティを提供しますサーバー上ユーザーが自分のパスワードを直接指定しており、そのように保護する必要がある場合よりも安全です。
その追加レベルのセキュリティを提供できるようにしたい場合は、2つのハッシュをお勧めします。クライアント側で1回ハッシュして新しい一意のパスワードを作成し、そのパスワードをサーバーでハッシュして、DBに保存する値を作成します。このようにして、両方の世界のベストを得ることができます。
ほとんどの場合、SSLは十分に信頼されており、送信前の初期ハッシュが不要であると見なされる交換を保護します。また、侵害されたサーバーは、クライアントに送信されるコードを常に変更して、初期ハッシュが実行されないようにすることができます。これは単にSSLの効果的な代替手段ではなく、コストと複雑さに見合うだけの十分な追加の利点はありません。
かなりの数の利点がある場合は、それらを質問にリストして、人々がそれらが本当に役立つかどうかを見つけられるようにする必要があります(そうすると有名になるかもしれません;)
人々はユーザー側の個人情報を保護するより良い方法を持っているので、クライアント側のハッシュを好みません。情報漏えいの可能性がある場所について考えてみましょう。そのうち3つがあります。
次に、クライアント側のハッシュがこれらの場所で役立つ理由とそうでない理由を見てみましょう。
クライアント。
ブラウザーが危険にさらされている場合や、コンピューターにキーロギングソフトウェアが埋め込まれている場合など、自分のコンピューターにマルウェアがある場合、クライアント側のハッシュはハッカーによるパスワードの取得を妨げません。その理由は明白です。
クライアントとサーバーの間。
クライアントとサーバーの間に通信チャネルがあります。通信を傍受する盗聴者がいる場合、盗聴者はハッシュから元のパスワードを回復する必要があるため、クライアント側のハッシュによりパスワードの漏洩がさらに困難になる可能性があります。ここで本当に便利です。
ただし、この脆弱性は、安全でない通信チャネルの前提に基づいています。実際には、この問題を正確に解決しようとするプロトコルがあります。彼らの主な仕事は、安全でないチャネル上に安全なチャネルを確立することです。最も有名で広く展開されている例はSSL/TLSであり、クライアント側のハッシュよりも多くの機能と優れたセキュリティを提供します。
結論として、クライアント側のハッシュはチャネルで役立ちますが、より優れたツールがあります。
サーバー。
サーバーがハッカーによって侵害された場合、ユーザー情報がサーバー上で漏洩する可能性があります。ハッカーは、プレーンテキストで保存されているユーザーパスワードをデータベースから取得できます。そのため、現在ほとんどのサーバーはこれを実行していません。代わりに、ハッカーが手元の情報(つまり、ハッシュ)から元のパスワードを簡単に復元できないように、パスワードのハッシュを保存します。
サーバーがクライアント側で計算したハッシュを保存するだけの場合は、うまく機能すると信じたくなるかもしれません。しかし、これはひどく間違っています。そのような状況では、ハッシュ自体が同等のパスワードになります。ハッカーは、ハッシュを元に戻すことなく、単に渡すだけで認証を通過できます。ハッカーの目標は、ハッシュを元に戻すことではなく、アカウントに侵入することです。重要なのは、データがハッシュ値であるという事実ではなく、クライアントデータに対するサーバーの検証プロセスにあります。したがって、ここではclient-sideハッシュの利点は取るに足らないものであり、サーバーはとにかく再ハッシュする必要があります。
要約すると、クライアント側のハッシュはユーザー情報の保護に役立ちますが、保護は主に通信チャネルに適用されます。そこではより良いアプローチ(SSL/TLS)があるため、クライアント側のハッシュのアプリケーションは大幅に抑制されています。これは単に、目前のタスクに最適なツールではありません。
クライアント側のパスワードハッシュにはどのような利点がありますか?
まあ、パスワードは平文でネットを介して送信されません。ただし、ログイン時には実際にTLS暗号化を使用する必要があるため、パスワードスニッフィングは問題になりません。
別の理由としては、サーバーにeverをマイクロ秒単位でなくてもユーザーのパスワードを知らせたくない場合があります。つまり、登録時にサーバーにパスワードハッシュを与え、そのパスワードハッシュを使用してログインします。残念ながら、これでは何も解決されません。アカウントにログインするための共有秘密は、パスワードではなくハッシュになりました。ハッシュの情報を取得すると、実際のパスワードを知らなくてもログインできます(サーバーもそれを知らないため)。
クライアント側でハッシュしてから、パスワードをソルトしてサーバー側でもう一度ハッシュすることをお勧めします。これは、中間者攻撃に対する追加の保護レイヤーです。 SSLは最初のレイヤーですが、Snowdenの啓示により、SSLはNSAなどの組織によって比較的簡単に侵害される可能性があることが明らかになりました。
あなたはウェブアプリケーションについて話しているので...
データベースには、dbo.useraccというテーブルコールがあり、これらのハッシュパスワードを保存しています。
User Password
-------- ----------
user1 5f4dcc3b5aa765d61d8327deb882cf99
user2 202cb962ac59075b964b07152d234b70
user3 098f6bcd4621d373cade4e832627b4f6
そして、Webアプリケーションのログイン機能は次のようなものです
if (user == $user and password == $pass) {
return auth.token
}
攻撃者がデータベースのハッキングと盗用に成功し、dbo.useraccデータを保存したとしましょう。彼は今私たちのハッシュされたパスワードを持っています。
ログインハッシュプロセスがクライアントに保存されている場合でも、攻撃者はHTTP POSTメソッドを接続してパスワードフィールドを変更し、ハッシュされたパスワードを送信するだけで、ハッシュされたパスワードを使用してアカウントにアクセスできます。はまだログインできます。アプリケーションデータは、POSTメソッドを介して、最終的にはハッシュされてからチェックされます。
ただし、ハッシュプロセスがサーバー内にある場合は、別の話になります。
$pass = md5.hash($pass);
if (user == $user and password == $pass) {
return auth.token;
}
ハッカーがハッシュされたパスワードを使用してログインする場合、ハッシュされたパスワードに対してチェックするハッシュ「ハッシュされたパスワード」になります。
この場合、攻撃者の投稿としましょう
$ user = user1 $ pass = 5f4dcc3b5aa765d61d8327deb882cf99
サーバー側が$ pass = md5.hash(5f4dcc3b5aa765d61d8327deb882cf99)を実行した後、誤ったステートメントを返す「696d29e0940a4957748fe3fc9efd22a3」を返します。
これは、データベースデータの盗難に成功し、ハッシュされたパスワードを使用してWebアプリケーションからアクセスしようとする攻撃者を隔離するためです。そしてもちろん、辞書攻撃などでブルートフォースやハッシュのクラックに成功した場合でも、攻撃者はアカウントにハッキングすることができます。ただし、システムが危険にさらされた後にパスワードが適切なパスワードであり、サーバー管理者がパスワードをリセットしてユーザーにメールを送信するだけの場合、ハッカーはより長い時間を必要とします。
また、企業の従業員などの内部の脅威にも使用されます。企業には、データベース管理者と開発者がいます。それらは異なる役割です。従業員ユーザーが機密データにアクセスできないようにするには、データにアクセスするためにアプリケーションとDBの両方にアクセスできる必要があります。もちろん、DBAはデータベース自体を介してデータベースデータを変更できると主張するかもしれませんが、開発者はこのデータにアクセスできず、攻撃元を特定するのが簡単です。それは、アクセス制御権とリスクと脅威の最小化についてです。
@Cykerによって指摘されたように、トピックにはいくつかの具体的なリークポイントがありますが、ここでの議論は少し活発です...私が言及しなかった1つのポイントを追加したいと思います。
できるだけ早くハッシュすれば、誤ってクリアテキストのパスワードをどこかに渡してはならない場所に誤って渡してしまうというプログラミングのリスクを軽減できるというだけです。セキュアテキストやセキュアアレイなどの対策を講じて、クリアテキストをできるだけ早く破棄しようとしています。パスワードを取得した時点でのハッシュは、そのような別の手段です...コードが進化するなどして、リスクはまだ減少しているようです。
SecureStringのクリアテキストを受け取り、すぐにハッシュする小さなC#の「ボックス」を書いたところです。この方法では、ログに記録されたり、予期しないライブラリに渡されたりすることはありません。これはプロトコルに関するものではなく、単にプログラマが座ってパスワードを確認しているだけです---触れたくありません! (一部の側面では依然としてパスワードと同等ですが、チェーンされたメソッド呼び出しで閉じ括弧を移動したり、クリアテキストを間違った場所に渡したりするなど、愚かさから少なくとも即座に隠されます。安全な配列は隠されません。)
ここでは、クライアント側のハッシュメカニズムを優先して比較検討するという明確な目的を持って、ここに飛び込みます。これがどのように私たちに利益をもたらすか見てみましょう:
クライアント側:改善なし。
転送中:パスワードがクリアテキストで送信されるSSLstripの場合にパスワードを保護します。ただし、HSTSが実装されている場合、ほとんどの人はSSLStripは効果がないと言うでしょう。正しい? 番号
サーバーへの入り口:最後に、主要な利点がわかります。サーバーが侵害された場合はどうなりますか? Wireshark/TCPDumpを起動してサーバーの秘密鍵をエクスポートするだけで、平文のパスワードの継続的なフローを取得します。数か月間ネットワークに留まることができ、大容量サーバー(月あたり数百万のユーザー登録)の場合、大規模なプレーンテキスト違反が発生します。もちろん、サーバーにRCEを置くよりも、サービスの利用者のパスワードを取得する方が価値があると想定しています。
サーバー:すべての着信パスワードでbcryptを実行する必要がない場合のパフォーマンス上の利点。これにより、新しい脆弱性を導入することなく、計算コストをクライアントにオフロードします。これは、サーバーの管理者にとっても、ハードウェアコストにとっても良いことのようです。
それでも、ユーザーにとって耐え難いページの読み込み時間が作成されない限り、パスワードハッシュをクライアント側に組み込むのがベストプラクティスのようです。
SSL/TLSが利用可能な場合、認証プロセスを保護するためのクライアント側のハッシュの利点が制限されることに同意します。ただし、SSL/TLSは、攻撃者が保存されたハッシュにアクセスできる場合(プロセス後)には、カスタムハードウェア攻撃に対する脆弱性を解決しません。単純なソルトハッシュやPBKDF2のようなスキームなどの関数は、メモリ要件が低いため、これらの攻撃に対して非常に脆弱です。これらのスキームで保護されたパスワードのクラッキングは安価で高速です。そしてそれは、パスワードハッシュの主要な問題の少なくとも1つです。
一見、これはクライアント側のハッシュとSSL/TLSとの関係はありませんが、サーバーがShard、Argon2、Catenaなどのメモリハードパスワードハッシュスキームを実装してカスタムハードウェア攻撃を保護する場合、サーバーのハードウェア要件は劇的に増加します。したがって、実際には、サービスはメモリの硬度を下げるか、脆弱なスキームに切り替えます。クライアント側のハッシュは、この問題を少し回避するのに役立ちます。クライアントがこれらの高価な(メモリハード)関数を計算するとき、サービスはより良いハードウェアを必要とせずにそれらを使用できます。
したがって、最新のパスワードハッシュスキームは、関数の最も高価な(メモリが難しい)部分をクライアントに委任する可能性を提供します。この機能はサーバーの救済と呼ばれ、Argon2とCatenaによって提供されます。
結論:カスタムハードウェア攻撃に対する脆弱性がはるかに少ない最新のパスワードハッシュスキームを使用すると、将来的にはもちろん、SSL/TLSとともに、クライアント側ハッシュの使用が増えるか、少なくとも増えるはずです。