8

REST API を設計していますが、ユーザー認証のセキュリティに関して問題があります。認証のために、パスワードをネットワーク経由でプレーンテキストで送信したくありません。

この問題を回避するために、パスワードの SHA-256 ハッシュ (ユーザー名をソルトとして) を送信できるので、パスワードがプレーン テキストで送信されることはありません。私のデータベースでは、次のハッシュを保存します: SHA256(パスワード + ソルト) 両方のハッシュが一致するかどうかを比較します。

このオプションの問題は、高速ハッシュ アルゴリズムで計算されたハッシュがあり、ソルトがランダムではないことです。

セキュリティのベスト プラクティスは、ランダムなソルト (bcrypt など) を使用した低速の署名アルゴリズムを使用することです。

遅いアルゴリズムは問題ではありません。クライアント側で bcrypt を使用できますが、salt の場合はどうすればよいかわかりません。

  • Bcryptには定義されたサイズのソルトが必要なので、ユーザー名を入れることができません
  • ランダムなソルトを使用している場合、クライアントはパスワードのハッシュを計算する前にこのソルトの値をどのように知るのでしょうか?

だから私は3つのオプションを見ることができますが、満足できるものはありません:

  • パスワードをプレーンテキストで送信し(SSLを使用しています)、bcryptをdbに保存します=>まだ中間者に対して脆弱です
  • 私はSHA256を使用し、ソルトがユーザー名であるハッシュを送信します(まだSSLを使用しています)=>データベースのハッシュは安全性が低くなります
  • 私はbcryptを使用しており、2段階のプロセスがあります。特定のユーザーのソルトを要求し、このユーザーのハッシュを送信します(まだsslを使用しています)=>他のユーザー名でログインしようとすることで、彼のソルトを取得できます。驚くばかり

誰かがより良い解決策やアドバイスを持っていますか?

4

4 に答える 4

5

ここでいくつかの問題を混同/混乱させている可能性があると思います:

  • ハッシュ (パスワード + ユーザー名) をサーバーに保存していて、認証にハッシュ (パスワード + ユーザー名) の送信が含まれている場合、パスワードをサーバーに保存するだけで、実際には何も達成していません。ハッシュのみを長期的に保存する目的は、データ侵害 (つまり、攻撃者がデータベースへのアクセス権を取得した場合) が発生した場合でも、認証するための正しい値を生成できないことです。しかし、単純な比較をしている場合、これはまだ問題です。
  • ハッシュ + ソルティングの正しい使用法は次のとおりです: (1) サーバーは (ソルト、ハッシュ (パスワード + ソルト) のタプルを保存します; (2) ユーザーは (要求されたパスワード) を送信します; (3) サーバーはハッシュ (要求されたパスワード + ソルト) を計算します; ( 4) if hash(claimed Password + Salt) == hash(Password + Salt), then they are Authentic. このようにして、たとえ攻撃者がデータベースへのアクセスを取得したとしても、主張されたパスワードを生成することはできません。ハッシュ (要求されたパスワード + ソルト) は有効です。
  • SSL 経由でプレーンテキストのパスワードを送信することは、「平文」ではありません。@NullUserException のコメントによると、攻撃者が SSL を破っていない限り。サーバーのみがパスワードの値を取得できます (サーバーの公開鍵が有効であると仮定すると、これはまったく別の話です)。

お役に立てれば!

于 2012-10-24T15:43:40.367 に答える
2

クライアント側でのハッシュのアプローチには、いくつかの利点があります。そのうちの 1 つは、サーバーが実際のパスワードを取得しないことです。そのため、サーバーが何らかの方法で侵害された場合でも、実際のパスワードを取得することはできません。もう 1 つは、低速ハッシュの使用を計画している場合に、サーバー側の負荷を軽減できることです。

ただし、パスワードのハッシュは、データベースが侵害されてハッシュが盗まれた場合に備えてユーザーを保護するように設計されています。これは、誰かがハッシュ化されたパスワードを入手した場合でも、ハッシュを送信することでユーザーになりすます可能性があることを意味します. つまり、クライアント側でハッシュしても、サーバーで再ハッシュする必要があります。

もう 1 つの潜在的な欠点は、これにより、JavaScript が有効になっていないユーザーベースの一部が疎外される可能性があることです。


ポイントに対処するには:

Bcryptには定義されたサイズのソルトが必要なので、ユーザー名を入れることができません

ユーザー名をソルトとして使用しないでください。ソルトは一意である必要があり、ユーザー名 (およびその派生) は確かに一意ではありません。固有とは、サーバーに固有という意味ではなく、どこでも固有という意味です。代わりに暗号ナンスを使用してください。

ランダムなソルトを使用している場合、クライアントはパスワードのハッシュを計算する前にこのソルトの値をどのように知るのでしょうか?

事前にサーバーにソルト (ノンス) を送信させるだけです。クライアントでもこれを行うことができますが、私の知る限り Javascript には CSPRNG がなく、サーバーにナンスを送り返す必要があります。

パスワードをプレーンテキストで送信し(SSLを使用しています)、bcryptをdbに保存します=>中間者に対して依然として脆弱です

SSL は中間者攻撃を防ぐように設計されています。なんらかの形で壊れていない限り、それは問題になりません。

私はSHA256を使用し、ソルトがユーザー名であるハッシュを送信します(まだSSLを使用しています)=>データベースのハッシュは安全性が低くなります

ユーザー名をソルトとして使用しないでください。前に言ったように、クライアント側でハッシュ化したかどうかに関係なく、サーバー側でハッシュ化する必要があります。

私はbcryptを使用しており、2段階のプロセスがあります。特定のユーザーのソルトを要求し、このユーザーのハッシュを送信します(まだsslを使用しています)=>別のユーザー名でログインしようとすると、彼のソルトを取得できます。すごいじゃない

本当に素晴らしいことではありません。

于 2012-10-24T16:21:02.407 に答える
1
  1. ソルトを一定にします。たとえば、ユーザー名のハッシュにします。したがってhash_val = HASH(HASH('username') + 'password')、サーバー側に保存されます。
  2. 認証のために、サーバーは使い捨てのランダムな値を送信します。nonce = HASH(RAND())
  3. クライアントは、入力されたクレデンシャルに基づいて以下を計算client_hash = HASH( nonce + HASH(HASH('username') + 'password'))し、サーバーに送り返します。
  4. サーバーは同じ操作を実行し、結果のハッシュを比較して、ナンスを破棄します。

このようにして、ネットワークを介して送信されたハッシュは1回だけ使用され、「リプレイ」およびMITM攻撃から保護されます。

また、ハッシュだけでなくパスワードを保存するためにPBKDFのようなものを調べてください。これにより、ブルートフォーシングとレインボーテーブルの両方が完全に非実用的になります。これは、まだPHPに含まれていないため、私が使用しているPHPの実装です

于 2012-10-24T15:48:23.840 に答える
0

可能であれば、API を使用するための API キーと秘密鍵 (API ユーザー名/パスワード、明らかに各ユーザーに固有のもの) を作成します。API アクセスをアクティブ化/非アクティブ化するオプションと、API キーと秘密鍵を再生成するオプションをサイト インターフェイスに提供する必要があります。ここでは、このインターフェイスで、ユーザーは API の API/シークレット キーを確認できます。

于 2012-10-24T16:01:58.630 に答える