ユーザーのオフラインでの切り替えをサポートする必要があるWebアプリを構築しています。ユーザーを認証するためにbcryptハッシュを公開しても安全かどうか疑問に思っています。
基本的な流れ:
アプリケーション自体はかなりリスクが低く、ユーザーが同僚になりすまそうとするような多くのシナリオはありませんが、私はこれを正しく行いたいと思います。
洞察をお寄せいただきありがとうございます。
(フォローアップの質問は、サーバーと同期するときに、レコードを作成する前に他のユーザーが実際にオフライン認証を行ったことをサーバーに証明する方法ですが、自分の投稿としてはより良いかもしれません。)
いいえ、大丈夫ではありませんが、bcryptハッシュの問題ではありませんが、認証を信頼できるサーバーから(サーバーであるため)ユーザーのデバイス(信頼できない)に移動したためです。 「このパスワードは有効ですか?」の結果を変更するには、簡単なデバッガーが必要です。 「いいえ」から「はい」にチェックします。
また、攻撃者がハッシュのリストに永続的にアクセスできるようにします。したがって、攻撃者は、使用したい任意のコンピューターで必要な限り、そのリストを総当たりにすることができます。
簡単に言えば、それは非常に悪い考えです。
正しいことは、認証されたユーザーの同僚になるclaimsであるユーザーのアクションをキャッシュし、実際にオンラインに戻ったらすぐにその同僚にサーバーで適切に認証させることです。彼らがサーバーにしたことは何でもコミットする。これを行う1つの方法は、ユーザーが入力したパスワードを保存し、「通常の」ログイン時に使用する形式でサーバーに送信することです。それが機能する場合は、ユーザーが自分自身を認証し、保存されているアクションを実行できます。正しくない場合は、ユーザーに間違ったパスワードを入力したことを伝え、正しいパスワードを入力しないとアクションをコミットできないことを伝えます。
パスワードハッシュをクライアントにプッシュすることで、それらをオフラインのブルートフォース攻撃にさらすことになります。パスワードが十分に強力であれば、それは完全に受け入れられます。しかし、これは危険な仮定です。
各ユーザーに、(リスクを説明した後で)自分のハッシュを公開することを確認するよう依頼することができます。しかし、実際に選択したのはpassword12345!!!
でしたが、リスクを理解し、十分に強力なパスワードを選択したと喜んで言うユーザーはたくさんいます。
この時点で、ユーザーが自分で足を撃つことを許可することによるリスクと比較して、この機能がどれほど重要であるかを評価する必要があります。
ただし、設計には、オフラインで行われた更新を認証するというもう1つの欠点があります。ユーザーの検証をクライアントに依存するだけでは十分ではありません。
ユーザーのパスワードを更新と共に保存し、両方をオンラインにしてからサーバーに送信すると、クライアント側の検証のみを実行するという問題に対処できます。しかし、3つの新しい問題を導入します。
更新が入力されたときにパスワードの検証を許可しながら、パスワードのオフライン総当たり攻撃を防ぐ方法はありません。その検証は、使いやすさの理由から必要です。
したがって、私がとるアプローチは、ユーザーのパスワードとソルトに基づいて公開鍵のペアを作成し、対応する秘密鍵を使用して更新に署名することです。つまり、更新プログラムは改ざんできなくなり、パスワードを保存して送信する必要がなくなり、署名を保存して送信するだけです。
もちろん、クライアントは、適切に署名されたトランザクションを生成するために、saltとユーザー名を知る必要があります。また、公開鍵またはハッシュのいずれかを最初に確認する必要があるため、オフラインのブルートフォース攻撃が可能になります。
ハッシュ検証済みのクライアント側を1バイトだけに切り捨てることができます。これにより、オフラインのブルートフォース攻撃が実行できなくなり、クライアント側で99%の確率で不正なパスワードを検出できます。
サーバー側では、ソルトハッシュを使用して送信された公開鍵を検証し、有効なトランザクションのみを受信するようにする必要があります。
明らかに、設計しているアプリケーションの設計には間違いの余地がたくさんあります。そのため、最終的な設計とコードを複数のセキュリティ専門家がレビューすることは、最終結果が安全であることを保証するために必要です。