web-dev-qa-db-ja.com

クライアント側が信頼できない場合、ASP.NETフォーム認証Cookieがクライアント側でのみ削除されるのはなぜですか?

ASP.NETドキュメントは言う:

FormsAuthentication.SignOut()

ブラウザからフォーム認証チケットを削除します

なぜサーバーでもCookieが無効にならないのですか?実装は簡単です。結局、このコードはサーバーで実行されます。実際、サーバーはサーバー自体を信頼するため、サーバーに実装する方が簡単ですが、クライアントのCookieをクリアするにはクライアントの協力が必要です。クライアントがエラーまたは悪意により協力に失敗した場合はどうなりますか?それで?

私はこのコードをテストしました、そしてそれはそれが言うことをします。ブラウザ上のCookieを削除し、サーバー側のCookieを有効なままにします。サインアウトする前にCookieのコピーを取り、ユーザー名とパスワードを入力せずに、そのCookieでサインインし直しました。

それで、起こり得る悪いことは何ですか?この:

  1. ボブはログインし、自分のセッションCookieをメモ帳に保存します
  2. 管理者はBobのアクセスをすぐに取り消す必要があり、Bobからの次のWebリクエストでFormsAuthentication.SignOut()をトリガーするフラグを設定します。管理者はボブのパスワードも変更します。
  3. Bobのブラウザは、CookieをクリアすることでSignOut()に反応し、すぐにログアウトされます。 「ログアウトしました」というメッセージが表示されたボブは、[戻る]ボタンをクリックしようとしましたが、実際にはログアウトしています。彼は元に戻せません。彼は自分のユーザー名とパスワードでログインしようとしましたが、パスワードが無効であると表示されています。
  4. 管理者はサーバーログを監視し、SignOut()が正常に実行されたことを確認します。
  5. Bobは保存されたセッションCookieを使用して再度ログインします(許可されています)。彼は無期限にシステムに取り組んでいます。

これは悪いことではないですか?これは単なるASP.NETですか、それとも他のフレームワークはこのようにしていますか?

2
user3280964

まず、誤解を解消しましょう。 「サーバー側のCookie」などはありません。サーバーはHTTP応答でCookieを送信できますが、有効なCookieのサーバー側キャッシュはありません。これは、それをサポートするユーザーエージェント(ブラウザなど)のクライアント側にのみ存在する構造です。これにより、Cookieが強力になります。数千、数十万(またはそれ以上)のユーザーの状態を維持できます。必要なリソースは、各クライアントマシンのわずかなメモリとストレージだけで、サーバー側にはまったくありません。サーバーがCookieについて持っている必要がある唯一の知識は、要求からそれを解析する方法と、それを(必要に応じて)応答に設定する方法です。

次に、フォーム認証について具体的に説明します。フォーム認証は、純粋にCookieベースの認証メカニズムです。 (簡単にするために、そして当面の質問に焦点を合わせるために、私はcookieless-FormsAuthを省略します。)これは、単純で軽量で構成が簡単な認証メカニズムがあり、邪魔にならないことを意味します。サーバーリソースの共有とサーバー側の状態管理プロセスとオーバーヘッドの共有はありません。

つまり、元の認証チケットをクライアントに送信すると、そのチケットが有効である限り、それを使用して将来の要求を認証できます。変更を加えないでください(Cookieの期限切れ、新しいチケットでの有効期限情報の追加、Cookieの置き換え、追加の「ログアウト」Cookieの追加)は、元のCookieが有効である限り使用できなくなります。

これは問題ですか?実際には、通常はありません。ほとんどのアプリケーションでは、これは緩和する必要のある特定の脅威を作成するものではなく、サーバー側のリソース投資要件に縛られずにユーザーを認証する機能は非常に魅力的です。アプリケーションのサーバー側セッション無効化の緩和策を追加することの価値を定量化できない場合、それを実装することは純損失であり、望ましい結果ではありません。

アプリケーションの脅威モデルdoesがセッションを安全に認証解除する必要がある特定の理由を示している場合、フォーム認証はそのままではなく、サーバー側のセッション検証メカニズムを実装する必要があります。フォーム認証Cookieで送信された認証チケットの名目上の有効性に関係なく、認証状態を追跡して、有効な認証済みユーザーを特定し、他のすべてのユーザーからの要求を破棄します。

最後に、他のフレームワークはこのように機能しますか?確かに多くの人がします。これは、クライアントから送信されたチケットに依存して認証状態を決定するステートレス認証システムの必須のプロパティであり、おそらくそれよりも多くの認証メカニズムです。サーバー側のセッション管理コンポーネントを持つ認証システムは、サーバー側の認証状態を追跡することでこれを回避できます。特定のシステムが正しくそれを実行するかどうかは、テストするリーダー次第です。密接な関係はありませんが、言及する価値があります...すべての認証システムに、最初からサインアウトするという概念があるわけではありません。たとえば、証明書認証または統合認証を使用している場合、「サインアウト」して認証済み状態から非認証状態に戻すという概念は実際にはなく、これらの場合、問題は無関係です。

3
Xander

これは 既知のセッションリプレイの脆弱性いくつかの回避策 を使用したASP.NETのようです。

1
user3280964

これは悪用される可能性がありますか?

はい、攻撃はあなたが説明したとおりです。トークンを盗む攻撃者は、ユーザーがログアウトした後でも有効です。これがどれほど実用的かは議論の余地がありますが、これはベストプラクティスではありません。

なぜASP.NETはこれを行うのですか?

背後にある設計の考え方が分からないため、これは答えるのが難しいことです。これはセキュリティ上の欠陥であり、クライアントの動作に依存するべきではないことは明らかです。

どうすればこれを回避できますか?

基本的に、クライアントのCookieがクリアされた後、Cookieを無効にする必要があります。 この質問 のStack Overflowでは、まったく同じ問題を扱い、さまざまなソリューションを提供しています。

他のフレームワークはこれを行いますか?

確かには言えない。ドキュメントを確認することは理にかなっています。一般的な経験則として、セキュリティのクライアント側の動作(多層防御対策を除く)に応じて、真っ赤なフラグと見なす必要があります。

1
MechMK1