web-dev-qa-db-ja.com

認証にCookieを使用するだけで何が問題なのか理解できません。

私はアプリサーバーを書いていて、認証に安全なCookieを使用するオプションがあります。これがどのように機能するかです:

  1. サーバーで32バイトの秘密鍵を定義します
  2. ユーザーがログインするときに、データベースをチェックしてbcryptハッシュが一致するかどうかを確認し、一致する場合はrequest.remember(user_id)を呼び出します
  3. 認証(およびuser_id)を必要とするルートハンドラーでは、cookieを復号化してuser_idのラップを解除し、それが有効な場合は続行します。それ以外の場合は、Unauthorizedエラーを返します。
  4. ユーザーがログアウトハンドラーにヒットした場合は、request.forget()を呼び出すだけで、Cookieがクライアントで削除されます。

これはすべてうまくいくようです。だから私が気になるのは、なぜ誰もがこれをしないのですか?周りを見回すと、JWTについて多くの話があり、認証トークンUUIDを生成してRedis /データベースなどに格納しているようです。そのため、この方法は明らかに安全ではありませんか?そして、あなたはサーバーに状態を保存する必要がありますか?

私が推測すると、このアプローチの問題は、Cookieが何らかの方法で盗まれた場合(TLS全体でどのようにCookieがHTTPのみで安全であるかが重要であるため、方法がわからない)、ユーザーが攻撃者になりすまされる可能性があります。しかし、これは他のスキームにも当てはまると思いますか?

もう1つの問題は、ユーザーに一致するトークンが見つかるまで、ユーザーがランダムに認証トークンを生成できることです。しかし、認証ハンドラーをレート制限するだけなので、これが問題であるかどうかはわかりませんが、この種の処理にはしばらく時間がかかると思いますか?ああ、多分彼らは100個のアカウントを作成し、暗号化されたCookie認証トークンがどのように見えるかを確認し、サーバー側の秘密鍵を見つけるためにクライアント側にブルートフォースを適用できるでしょうか?そして、認証トークンを生成することで、ユーザーになりすますことができますか? 32バイトなので、キーを見つけるのに時間がかかりすぎると思いますが?

このアプローチではCookieが自動的に期限切れにならないと思います(これがあまり使用されないのはなぜですか?でも、Cookieに期限切れヘッダーを追加する方法はあると思いますか?うまくいくでしょうか?)期限切れが必要かどうかさえわかりませんこのアプリでは..ユーザーを困らせるようです。 Google/Facebookなどの場所でのセッションの継続時間はどれくらいですか?私はいつもそれらのサービスに永遠にログインしているような気がします。

知りません。ここには多くの情報が欠けているように感じます。これらのさまざまなアプローチすべての長所と短所のリストを見つけることができる場所はありますか?

10
Chron Bag

あなたが説明するスキームは、クロスサイトリクエストフォージェリ(CSRF)に対して潜在的に脆弱です。

ユーザーに代わって悪意のあるリクエストが行われる可能性があります。このリクエストは、認証チェックに合格するCookieを送信し、ユーザー自身が実行できるアクティビティを実行します。

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)

CSRFに関するOWASP記事への上記のリンクを見ると、シークレットCookieが無効な緩和手法として具体的にリストされています。

4
Daisetsu

Cookieをステートレス認証識別子として使用していると想定すると、Cookieを使用して作成されることを除いて、スキームは基本的にJWTに似ています。主な違いは次のとおりです。

  1. JWTは通常、暗号化されるのではなく署名されるだけです(ただし、暗号化することもできます)。これは、サードパーティのサービスにトークンを作成するよう依頼できることを意味します。これにより、アプリケーションを他の認証サービスに接続したり、他のアプリに認証サービスを自分で提供したりできます。
  2. モバイルネイティブアプリとCookieは問題を引き起こす可能性があります。一般的には克服できますが、リクエストヘッダーまたは本文にテキストとして添付するだけで簡単に格納できるトークンを使用するよりも、実装がかなり複雑になる可能性があります。
  3. JWTは、必要なメタデータをクレームにほとんど添付でき、通常のJSONと同じように読み取ることができるため、特にJavaScript環境での作業が簡単です。また、その人気により、より多くの最新フレームワーク向けの既成のソリューションを見つけることができます。
  4. Cookieはクロスサイトリクエストフォージェリ(CSRF)に対して脆弱ですが、トークンはそれらの格納方法に依存します(Webストレージの場合はクロスサイトスクリプティング(XSS)、ストレージCookieを決定した場合はCSRF)。

要約すると、あなたが提案していることは確かですが、基本的にはJWTがいくつかの利点を欠いているのと同じです。システムにサードパーティの統合が必要ない場合は、必ずCookieを使用してください。ただし、@ Daisetsuで述べられているように、CSRFから保護するようにしてください。

3
AlphaD

あなたはほとんど正しいです。 Cookieは暗号化されているため、コンテンツを表示したり、乱用したりすることはできません。 (暗号化が破られている場合を除きます。)CookieはTLS経由でのみ送信されるため、MITMが盗むことはできません。 (証明書がなんらかの危険にさらされている場合を除きます。)CookieはHTTPのみに設定されているため、悪意のあるJSによって盗まれることはありません。意味のあるあらゆる角度から、それは安全です。

私はあなたのセットアップに1つだけ不満を持っています。そのCookieでユーザーの永続的な識別子を使用しています。万が一何か問題が発生した場合、妥協はユーザーレコードの存続期間中続きます。ランダムな文字列を生成し、どこかに保存し、それを使用してユーザーを参照します。このようにして、ユーザーのIDを絶えずリサイクルし、セッションの存続期間に対する違反を含めます。

また、人気のあるフレームワークを開いて、それらの処理方法を検討することも検討してください。あなたは物事をより安全またはより効率的にするためにいくつかの有用なテクニックを選ぶかもしれません。

JWTなどについては、人々が使いたい新しい光沢と、ユーザーを認証する必要のあるシステムとは別のシステムに認証を存在させるための本当に便利な手法を組み合わせたものがあります。

編集:Laravelに少し飛び込んで、その方法を確認しました。ユーザーIDをセッションに保存するだけです。セッションはサーバー側なので安全です。これにより、セッション処理とは異なります。セッション識別子はランダムな40文字の文字列で、HTTPのみとして設定されます。

0
Wika