web-dev-qa-db-ja.com

Web認証の謎を解く(ステートレスセッションCookie)

現在、開発中のWebサイトのユーザー認証プロトコルを研究しています。ユーザーがページ間でログインを維持できるように、認証Cookieを作成したいと考えています。

これが私の最初のbashです:

_cookie = user_id|expiry_date|HMAC(user_id|expiry_date, k)
_

ここで、kHMAC(user_id|expiry_date, sk)であり、skはサーバーだけが知っている256ビットのキーです。 HMACはSHA-256ハッシュです。 '|'に注意してください単なる連結ではなく、区切り文字です。

これは、PHPのようになります(注、この質問は言語に依存しません。PHPは単なる例です):

_$key = hash_hmac('sha256', $user_id . '|' . $expiry_time, SECRET_KEY);
$digest = hash_hmac('sha256', $user_id . '|' . $expiry_time, $key);
$cookie = $user_id . '|' . $expiry_time . '|' . $digest;
_

A Secure Cookie Protocolに記載されているように、リプレイ攻撃に対して脆弱であることがわかりますが、ボリューム攻撃および暗号スプライシングに対して耐性があるはずです。

質問:私はここの正しい行にいますか、それとも見逃した大きな脆弱性はありますか?動的に割り当てられたIPアドレスで動作し、セッションを使用しないリプレイ攻撃を防ぐ方法はありますか?この作業を行うためにサーバー側に何も保存したくない。

また、私は自分で計画を立てたり、計画を立てたりしていません。私はこれを私がどの解決策を選択すべきかをよりよく判断するように求めています。したがって、なんらかの説明がなければ「Xソリューションを使用する」という答えはありません。

ノート

私が読んだ最新の資料:
Webでのクライアント認証の推奨事項と禁止事項別名Fu et al。
https://pdos.csail.mit.edu/papers/webauth:sec10.pdf

安全なCookieプロトコル別名Liu et al。
http://www.cse.msu.edu/~alexliu/publications/Cookie/cookie.pdf
以前の方法を拡張

強化されたステートレスセッションCookie
http://www.lightbluetouchpaper.org/2008/05/16/hardened-stateless-session-cookies/
これも前の方法を拡張したものです。

テーマは非常に複雑なので、認証スキームの作成と解読に関する実世界での経験を持つセキュリティ専門家からの回答を探しています。

42
Joony

「リプレイ攻撃」は実際にはCookieには適用されません。Cookieは定義によりリプレイされることを意味するものです。つまり、ユーザーのブラウザが同じCookieの値を送り返します。サーバーが同じユーザーであることをサーバーが認識する方法です。

回避したいのは、誰かが回線をスパイし、Cookieの値を監視し、自分の接続で同じCookieを送信することです。そのための唯一知られている実用的な解決策は、転送中のデータの機密性と整合性を保証するトンネル全体でプロトコル全体を実行することです。これは「SSL」として知られています(別名 [〜#〜] https [〜#〜] )。

次に、サーバーでCookie値を生成および検証する方法は2つあります。

  • 十分なサイズ(つまり、16バイト程度)のランダムな値を生成するだけでよいので、攻撃者が運からその値を推測することはほとんどありません。サーバーは、各ユーザーの現在の「セッショントークン」を「ユーザー」データベースの追加の列として記憶します。

  • トークンは、ユーザー識別子から決定的に計算された偽造できない値として生成されます。それがあなたがすることであり、それは合理的な概念です。基本的に、サーバーに追加の状態を保存する代わりに、クライアントにオフロードし、サーバー側のキーで [〜#〜] mac [〜#〜] を使用して、クライアントが「有効な」Cookie値を偽造することはできません。

コードは2つのネストされたHMAC呼び出しを記述していますが、これは奇妙で保証されていません。 1回の呼び出しで十分です。一般的な構成では、Cookieには値vとMACmが含まれ、vクライアントに保存する状態をエンコードし、mvで計算されます。保存する状態は、次のとおりです。「このクライアントにはユーザーIDiがあり、時刻にログオンしていますt 」明確にデコードできる場合は、任意のエンコーディングを使用できます。

まとめると:MACでCookie値を生成することは、セッション管理を行うための有効な方法であり、HMAC/SHA-256がそれに適しています。しかし、それを最適化として考える必要があります。サーバーに値を格納しないように、値をクライアントに格納します。これは、クライアントが制御不能なデータを忘れるか(クライアントがCookieを破壊する可能性がある)、またはタイムワープを実行できる(クライアントがブラウザに保存されている値を古いCookieの値に変更する可能性がある)という不幸な結果をもたらします。 MACの制御下で、Cookieに日付を含めることで軽減されます。

状態サーバー側を維持し、ランダムなCookie値を使用できる場合は、それを実行します。これは、よりシンプルで、サーバーにより多くの制御を提供します。

35
Thomas Pornin

Webアプリケーションを保護する最初のステップは、SSLを使用することです。これにより、Cookieの機密が保持され、リプレイ攻撃が防止され、ユーザーが適切なサーバーと通信していること、MitMが防止され、攻撃者がネットワーク上のデータを変更することが防止されます...

次に、Cookieにsecureフラグを設定して、SSL経由でのみ送信されるようにします。 _http-only_フラグを設定して、JavaScriptが読み取らないようにしても問題ありません。

最後にあなたのクッキースキームについて:

  • ネストされたHMACは何も得ません。 user_id|expiry_date|HMAC(user_id|expiry_date, SECRET_KEY)を使用するだけです
  • _SECRET_KEY_を定期的に変更する
  • _user_id_は決して変更してはなりません。つまり、ユーザー名やメールではなく、数値のuser_idを使用します
  • _user_id_と_expiry_date_のどちらにも_|_を含めないでください。
  • 偏執狂の場合は、CookieをMAC処理する代わりに署名する専用のログインサーバーを使用してください。そのため、ログインサーバーはCookieの作成に必要なキーを持つ唯一のサーバーであり、通常のWebサーバーはそれを検証することしかできません。 =>攻撃対象を減らす
  • サーバーは、すべてのユーザーに対して有効なCookieを作成できます。それは望ましくないかもしれません。
13
CodesInChaos

何よりもまず:

独自のセキュリティプロトコルを発明しないでください。間違っている可能性が非常に高いです。

じゃあ、これで終わりです。これを見てみましょう。ログインしたり、そのユーザーとして認証されたりせずにHMAC(userid|expiry_date, k)を取得できる場合は、このシステムのセキュリティが壊れています。これは、セッション固定攻撃やセッション乗っ取り攻撃(SSL/TLSを使用していない、または誤って使用していることが多い)など、あらゆる種類の問題にまで及びます。

セッションCookieをチェックしているときに、タイミングサイドチャネルから情報を漏らしていますか?間違いなくHMACを正しく使用していますか?あなたのHMACはSHA-256だと言っていましたが、実際にはHMAC-SHA-256を意味していますか?ランダムな文字列を生成してそれをサーバー上のユーザー(データベースなど)に関連付けることができるのに、なぜ複雑なHMAC手順を実行するのですか? user_id|expiry_date|HMAC-SHA-256(user_id|expiry_date, sk)(_|_は連結であり、リテラルパイプ文字ではない)を使用しないのはなぜですか?

Webベースの環境でのリプレイ攻撃に対する防御については、 OWASPのCSRFGuardプロジェクト を調べてください。あなたはそれを直接統合することはできませんが、PHP同等のものがどこかにあるかもしれません。しかし、あなたのサイトがXSS攻撃に対して脆弱であるなら、それはすべての問題です。

セキュリティは、臨機応変に行わず、尊敬され、バトルテスト済みのフレームワークに渡す必要があります

編集、セッション固定攻撃に関する簡単な単語:

十分にテストされたフレームワークにセキュリティを渡さない場合、おそらく脆弱であると思いました。基本的には、ユーザーが認証するときに、ユーザーが別個のセッションキーを発行していることを確認する必要があります(つまり、ユーザーが最初に使用したものとは異なります)。上記の戦略では、user_id|expiry_date|HMAC(user_id|expiry_date, k)はユーザーが認証されても変更されず、セッション固定攻撃に対して脆弱になります。

8
Tinned_Tuna

テーマは非常に複雑なので、認証スキームの作成と解読に関する実世界での経験を持つセキュリティ専門家からの回答のみを探しています。

主題が非常に複雑であるとあなたは正しい。

フレームワークが提供するセッション関数を使用し、独自の関数をロールバックしないでください。単純なPHPをフレームワークの代わりに使用している場合... shudders

3
user10211