小さなWebアプリケーションを作成していて、ログインパスワードをクリアテキストとして送信したくありません。 SSLが利用できないので、ログインフォームでランダムな文字列を送信するワンタイムチャレンジシステムを作成しました。これは、クライアント側でHMAC-SHA256を使用してパスワードをハッシュするために使用されます。メッセージとしてランダムチャレンジ文字列を使用し、HMACの秘密鍵としてユーザーのパスワードを使用します。
自作のソリューションは一般的に悪い考えであることを知っているので、ここで間違いを犯していないかどうか尋ねたかった。
編集:誤解があるようです。パスワードの保存やチャレンジ/レスポンスシステムについてではなく、HMACとパスワードの送信について質問しています。少し明確にするために:私の最初のバージョンはHMAC(msg=password, key=challenge)
でした。なぜなら、messageサーバーに送信したいと思ったからです。ユーザーのパスワードです。しかし、後でチャレンジ文字列が秘密鍵ではないことに気付いたので、切り替えましたが、何か完全に間違っているのではないかと考えたので、それについて質問した方がいいと思いました。
自発的なスキームであることに加えて、あなたの提案には少なくとも以下の問題が見られます。
実際のデータとの関連付けはありません。ユーザーを認証する場合、実際には「ユーザー」のみを認証する必要はありません。セッションを認証したい、つまり、リンクで続くものがそのユーザーからのものであることを保証し、リンクで送信するものは表示されるだけであることを確認します意図したユーザーによって。アクティブな攻撃者は接続をハイジャックでき、パッシブな盗聴者でさえ、後で送信するものをスパイできます。
このスキームは、オフライン辞書攻撃に対して脆弱です。パスワードは人間の脳に収まるため脆弱であり、人間の脳は長いパスワードを覚えるのが得意ではありません(そして人間のユーザーは長いパスワードを入力する忍耐力がありません)。それは負けた戦いです。コンピュータは定期的により多くの力を手に入れますが、人間には得ません。潜在的なパスワードを試すことは成功する傾向があり、スキームを観察するとパスワードを試すのに十分な情報が得られます(攻撃者は推測されたパスワードごとに1つのHMACを計算し、それが観察されたものと一致するかどうかを確認するだけです)。このような攻撃は、低速の派生プロセス(例 bcrypt )を使用することで大幅に軽減できますが、単一のHMACでは不十分です。オフラインの辞書攻撃を許可することさえ、まだ悪い考えです。
サーバーは、ユーザーが認証するのに十分な情報を保存する必要があります。つまり、サーバーのストレージへの一時的な読み取りアクセス権(たとえば、SQLインジェクションによるデータベースダンプ)を取得した攻撃者は、パスワード(またはパスワードと同等のデータ)を取得して、ほとんどコストをかけずにユーザーになりすますことができます。より良いパスワードスキームは、サーバーにパスワードを検証するのに十分なデータを保存しますが、それ以上は保存しません。
データ転送のための適切で安全な認証済みメディアを作成することは簡単な作業ではありません。 SSL/TLSライブラリを使用するのではなく、自分で何かを本当に再実装する必要がある場合は、自分自身を支持して、そのための標準プロトコルを実装してください。 SSL/TLS 。証明書に不満がある場合は、 SRPを使用したTLS を検討してください(証明書なし、クライアント/サーバーのパスワードベースの相互認証、オフライン辞書攻撃に対して脆弱ではありません)。
編集:独自の編集での説明について:HMACのキーとして秘密データ(パスワード)を使用し、既知のデータ(チャレンジ)HMACのデータとして、理論的にはその逆(HMACはキーが秘密になるように設計されています)よりも優れています。実際には、HMACの構造を考えると、セキュリティはそれほど変化しないでしょう。それでも、上記で触れた私の指摘は適用されます。
チャレンジ/レスポンス方式には、少なくとも2つの大きな欠点があります。
プレーンテキストのパスワード(またはプレーンテキストと同等のもの)をサーバー側に保存する必要があります。
クライアント側でパスワード処理を行う必要があります。つまり、クライアントが「有効な」コードを実行してパスワードクッキングを処理するという保証はありません。たとえば、「パスワードクッキング」の処理にJavaScriptが使用された場合、クライアントが悪意のあるJavaScriptを実行しているかどうかはわかりません。たとえば、プレーンテキストのパスワードを攻撃者に直接送信します。これはXSSによって発生した可能性があります。または、攻撃者がHTTPトラフィックをクライアントに到達する前に変更できた可能性があります。
その結果、チャレンジ/レスポンススキームを強化できます。見てください http://openwall.info/wiki/people/solar/algorithms/challenge-response-authentication これらのアルゴリズムは、「プレーンテキストのパスワードストレージの問題」に対処します。
しかし、これらの「強化されたチャレンジ/レスポンス認証アルゴリズム」を使用しても、2番目の欠点は残ります。そして、それを処理するためのポータブル/信頼できる方法はありません(「SSL」を除く)。ブラウザー拡張機能は、JavaScriptベースの「パスワードクッキング」操作(クライアント側)に関連するいくつかの問題を軽減するのに役立つ可能性がありますが、安全なHTTPS接続ほど良くありません。
質問はそれが防御している脅威モデルが何であるかを特定していませんが、私がそれが提案するスキームは実際には十分ではないのではないかと思います。私の考えでは、実際には、プレーンテキストのパスワードが問題となる脅威モデルでは、チャレンジ/レスポンスの提案も適切ではありません。
実際には、攻撃者が通信を盗聴できるほとんどの状況では、攻撃者は通信を改ざんし、中間者攻撃を仕掛けることもできます。この最も顕著な例は、オープンワイヤレスネットワークを介した通信ですが、DNSスプーフィング、クライアント側のマルウェア、悪意のあるHTTPプロキシなども含まれます。そして、攻撃者が中間者攻撃を仕掛けることができる場合、チャレンジは応答の提案は安全ではありません。攻撃者は、パスワードを盗んだり、他の厄介なことをしたりする悪意のあるJavascriptを挿入できます。
したがって、チャレンジ/レスポンスの提案は、サーバーが提供するコンテンツとコードを認証しないため、誤った安心感をもたらすと思います。ソリューションを展開する代わりに、SSL/TLS(つまりHTTPS)を使用する必要があると思います。クリアテキストで送信されたパスワードに問題がある場合は、おそらくSSL/TLSが必要です。
クライアントを認証するには、あなたのアプローチはほぼ正しいように聞こえます。ただし、サーバーにプレーンテキストのパスワードを保存する必要があります。これに対する小さな調整は、パスワード自体ではなく、パスワードから派生したものを格納することです。次に、クライアント側で同じ情報を取得してHMACにフィードします。
ただし、これは[〜#〜] not [〜#〜]相互認証です。クライアントはあなたのウェブサイトを認証しません、そして、彼/彼女のパスワードを与えるためにだまされます/なりすまされるかもしれません。
そして、あなたはリプレイ攻撃を考えましたか?
オフラインの総当たり攻撃はどうですか?
私がしていることは、あなたの最後の文の最初の部分を非常に強調することです。