web-dev-qa-db-ja.com

ソルトとハッシュを使用した基本的なユーザー認証の理解に役立ちます

何らかの理由で、ユーザーのクライアントとサーバー間で安全な認証を実行する方法がわかりません。私は多くのリソースを読みましたが、ハッシュおよびソルトツールの使用方法を理解していますが、最終的な画像を取得していません。

ユーザーは、サーバーにリクエストを送信するモバイルアプリケーションからログインします。これが私の理解です:

  1. 目的は、認証のためにユーザーのパスワードをサーバーに送信することですが、クリアテキストでは送信されません。ログインごとに一意のランダムソルトを生成します。次に、次の2つのアイテムをサーバーに送信します。

    • ハッシュ(塩+パスワード)
  2. サーバー側では、...これは私が完全に混乱しているところです。ここで何をしますか?データベースのパスワードはどのように保存する必要がありますか-hash(password)?そして塩は別々に保管されていますか?パスワードを確認するにはどうすればよいですか?誰がソルトを生成する必要がありますか-サーバーまたはクライアント?厄介な悪夢です!

更新

答えを読んだ後、今はもっと理にかなっています。私はSSLを使用しますが、SSLなしでどのように機能するか知りたいだけでした。さて、問題は、セッションIDがこれにどこで関係しているのですか?

A.ユーザーがログインして認証されると、サーバーは新しいランダムセッションIDを作成し、このセッションIDはそのユーザーのテーブルに保存され、クライアントに送り返されてそこに保存されます。ユーザーが行う以降のすべてのリクエストでは、毎回パスワードを送信するのではなく、セッションIDを送信して、それがユーザーのアカウントのセッションIDと一致することを確認します。これに対してハッシュや暗号化を行う必要がありますか、それともクリアテキストのセッションIDを送信して一致するかどうかを確認するのと同じくらい基本的なことですか?

B.そして、これは皆さんにとってもう1つの非常に常識的な質問ですが、POST urlはいくつかのことを行い、userId = self.request.get( ' userId ')。この値は、リクエストの送信時にクライアントによって割り当てられます。問題は、攻撃者がそのURLへの独自のリクエストを生成し、そのリクエストのuserIdに独自の値を入力して、リクエストを通過させることですか?Iそれがどのように機能するか本当にわかりません。

8
Snowman

あなたのタイトルでは、基本認証について話していると思います HTTP基本認証 について話していると思います。これは、ブラウザーがパスワードの入力を求め、エンコードして、ネットワーク経由で送信するときです。ただし、その方法ではメカニズムと暗号化を実際に制御するわけではありません。安全性が低く、SALT、1回限りのピン、キャプチャなどを追加できないため、通常は使用されません。

おそらく、POSTでフォームデータを送信するHTMLフォームを使用して、フォームベースの認証を実装する必要があります。 SSL/TLSを使用してこのフォームの送信をセキュリティで保護し、一般向けに証明書を使用する必要があります。これは、攻撃者がユーザー名とパスワードを盗聴してキャプチャできる中間者攻撃(MiTM)の機能を制限するのに役立ちます。 JavaScriptを使用してクライアント側で暗号化を行うことはできますが、初期パスワードを事前に保存しておく必要があります。私はこの実装をいくつかのペンテストでしか見ていませんが、そのようなJavaScriptでそれを行うことはあまり一般的ではありません。

さて、ソルティングとハッシュ、そしてそのようなすべてに関して。これは、データベースに資格情報を格納することと関係があります。通常、SSLで保護されたフォーム送信を通じて、暗号化なしでパスワードを受け取ります。実際のパスワードをデータベースに保存したくないので、それをハッシュし、ハッシュアルゴリズム(例: bcrypt )を使用してソルトします。 salt + hashを使用すると、直接保存せずにパスワードを保存できます。ハッシュは一方向であるため、 Rainbow tables と呼ばれる手法を使用しない限り、アルゴリズムを実行して同じ結果が得られるまで、あらゆる可能性をブルートフォースにする必要があります。レインボーテーブルはソルトを考慮に入れる必要があり、単に「標準」のレインボーテーブルにすることはできないため、ソルトを使用するとレインボーテーブルの使用が困難になります。

ユーザーごとのソルトまたは普遍的に使用するソルトを使用できます。ユーザーごとのソルトの方が安全です。データベースのユーザーテーブルには、次のものを格納します。

  1. ユーザー名
  2. ハッシュ(塩+パスワード)
  3. このユーザーのソルト

ここで、ユーザーが再度ログインするときに、フォームにユーザー名とパスワードを送信します。次に、それらがテーブルにあるかどうかを確認したいので、次のようにします。

  1. 指定されたユーザー名をデータベースで検索し、ハッシュとソルトを返します
  2. 提供されたユーザー名を取得し、1で取得したソルトを使用してハッシュ関数を再実行し、ハッシュ(salt + password submit on form)のような処理を行います。
  3. 2で生成されたハッシュが1のデータベースから取得されたonと一致する場合、正しいパスワードを提供したことがわかります。

重要な点は、実際のパスワードを保存せず、このランダムな文字セットのマッピング先を計算するのに計算コストをかけることです(つまり、実際のパスワードを判別するのは困難です)。

さらに読む

UpdateOP SSL経由で送信しないことについて尋ねます:

ここでは、(1)送信中のデータの保護と(2)保管中のデータの保護を実現する必要があります。ハッシュについて話したことで、安静時のセキュリティが確保されます。転送中のデータを保護するには、ネットワークを経由するデータが何らかの方法で暗号化されていることを確認する必要があります。 SSL証明書を取得したくない、または取得できないようです。これは一般的に最も一般的な方法です。それ以外の場合は、独自の秘密鍵と公開鍵を持つ、はるかに複雑なプログラム的な方法を実装できます。 PGPなどのJavaScript実装を使用して、データを秘密鍵で送信する前に多かれ少なかれ暗号化します。簡単に失敗する可能性があり、ユーザーが有効にしていないJavaScriptが必要になるため、これはお勧めできません。上記のソルティングを引き続き使用し、クライアントで公開鍵を使用して暗号化し、サーバー側で秘密鍵を使用して復号化し、SSLで転送されたかのように続行します。

アルゴリズム(警告-JavaScriptまたはその他のクライアント側言語が必要)

  1. フォームにログインを作成し、フォームに送信アクションを設定しないでください-機密情報であり、SSLを使用していないため、通常の方法で情報を送信したくない
  2. フォームの送信に使用されるJavaScriptハンドラーを作成し、処理の一環として、パスワードフィールドを秘密鍵で暗号化してから、HTTPポストを使用して送信します。
  3. サーバーで受信したら、公開鍵で復号化します
  4. これで、暗号化されたネットワークを介して実際のパスワードが転送されました
  5. 秘密鍵と公開鍵のペアを頻繁に変更して、侵害や逆転を減らします。
  6. 上記の詳細に従って安静時の保護を続行します。

Update 2OPは、セッション変数の保護について詳しく知るための質問を続けます。

盗聴を防ぐために、すべての送信をSSL経由で行うことが常に最善です。あなたがすべてのクッキーデータをハッシュしたとしても、私が傍受できて、あなたにそのハッシュを送り返す必要があるだけなら、まあ、私がMiTMになれるなら、すでに持っています。複数の要素を使用して、セッションハイジャックとCSRF攻撃を制限する必要があります。ここで詳しく説明するのではなく、 OWASP Top 1 を確認して、さまざまなセキュリティ上の懸念事項とその軽減方法を確認してください。 OWASPは、Webアプリを保護する方法を学習するための主要なリソースの1つです。

あなたが尋ねている2番目の質問は、サーバーサイドアプリが渡されたユーザーIDに基づいて基本的なロジックを実行しているかどうかであり、これは偽ることができますか?はい、セッション管理を使用して現在のユーザーを判別します。認証後にクライアントが誰であるかをクライアントに通知しないでください。

この記事 、あなたが尋ねる質問にも関連していて、あなたにとって役立つかもしれません。

8
Eric G

(HTTPSではなく)プレーンHTTPを介した認証が適切であることはほとんどありません。実際、認証とは何ですか?これは、一部のコマンドが実際に要求した人からのものであることを保証するものです。アクセスを許可するサーバーは、GETおよびPOSTコマンドを受け入れ、それらに応答するサーバーです。たとえば、機密文書を送り返します。送信されたパスワードをスパイする悪意のある盗聴者が心配な場合は、次に、サーバー応答をスパイできる、つまり機密文書自体を直接見ることができる、まったく同じ悪意のある盗聴者について心配する必要があります。データそのもの」と海賊は言います。

したがって、ほとんどの実用的なセキュリティモデルでは、データ自体の実際の保護システムが必要です。そのために広く使用されているプロトコルがあり、SSL(HTTPのラップに使用される場合はHTTPS)と呼ばれています。 SSLは転送されたデータを保護するだけでなく、サーバーも認証します。サーバー証明書の検証により、クライアントは適切なサーバーと通信することが保証されます。その場合、クライアントはSSLトンネルを介して「そのまま」パスワードを送信できます。パスワードはAegis of SSLの下で転送されるため、パスワードは危険にさらされません。

SSLを使用しない場合、実際の攻撃シナリオでは認証の効果がなくなります。

あなたはまだハッシュとソルティングを使いたいでしょうが、クライアントではなくサーバー上で。これは、深刻な違反が壊滅的となるリスクを軽減するための緩和策です(詳細については このブログ投稿 を参照してください)。これはサーバー側のストレージ専用であるため、クライアントはそれがどのように行われるかを意識する必要がなく、通信プロトコルは影響を受けません。

編集:明確にします:リンク上で悪いことをしている悪い人々から保護するためだけにクライアントでハッシュやwhatnotsを行う必要があります。送信されたものをスパイしたり、送信されたものを変更したりする。 HTTPSではなくHTTPを使用することで、これが発生しないことをすでに想定しています(または、想定しない場合assumeは、ある時点で残酷な幻滅に陥っています)。したがって、クライアントで何かをハッシュする必要はありません。

6
Thomas Pornin