私は、誰かがセッション Cookie を盗み、それを使用してシステムにアクセスするセッション ハイジャックを防ぐ方法を検討してきました。
http://codebutler.com/firesheepなどのプログラムを使用すると、オープン ワイヤレス ネットワーク上のセッションを簡単に傍受できます。また、セッションを取得する他の方法には、クロスサイト スクリプティング攻撃や、被害者のコンピューターからセッションを物理的に持ち上げることが含まれます。
SSL を使用してすべてのセッション Cookie/サーバー通信を保護することは、Firesheep スニフを防ぐために重要です。Cookie に HTTPOnly を設定すると、JavaScript が XSS 攻撃でセッション Cookie を読み取ることができなくなりますが、AJAX ベースの攻撃に対しては依然として脆弱です。
もう 1 つのレイヤーは、リクエストごとに更新されるセッション cookie にセキュリティ トークンまたは nonce を含めることです。トークンをサーバー側のデータストアと Cookie に保存し、リクエストごとに、Cookie のトークンがデータストアのトークンと一致するかどうかを比較します。
トークンが一致しない場合は、誰かがセッションを盗んで使用しようとしている可能性があるため、リクエストを無視するか、セッションを無効にしてユーザーに再認証を要求することができます。ただし、トークンの不一致は、接続が遅い/不安定な場合にも発生する可能性があります。
たとえば、サーバーが実際のユーザーからリクエストを受信し、サーバー データストア内のセッション トークンを更新し、更新されたトークンを含むセッション Cookie でユーザーに応答する場合があります。ただし、接続が遅い/不安定なため、ユーザーは応答を受信しないため、新しいセッショントークンがサーバーに保存されている間、ユーザーは古いセッショントークンを保持しています。ユーザーがリクエストを再試行すると、トークンが一致しなくなります。
この問題を軽減する1つの方法は、サーバーが最後のいくつかのトークンの履歴を保持し、それらが一致するかどうかを確認することですが、保持するトークンの数の状況になり、接続がどれほど不安定であるかによって異なりますユーザーがどれだけクリックに満足しているかに関係なく、接続が戻ってユーザーのセッションがブラウザによって更新される前に、サーバーが履歴を循環する可能性があります。
トークンの履歴を保持する代わりに、各セッションにタイムスタンプを付けて、タイムスタンプが指定された短い範囲 (たとえば 30 秒) 内にあるかどうかを確認します。ユーザーのセッション Cookie タイムスタンプが、サーバーに保存されているセッション タイムスタンプから 30 秒以内の場合、そのセッションは認証済みと見なされます。
疑似コードの例
def authenticate_request():
if (stored_session.timestamp - session.timestamp > 30 seconds):
return False
return True
これにより、トークンの履歴を保持する必要がなくなります (タイムスタンプがトークンになります) が、攻撃者はセッションが盗まれた後、30 秒間ハイジャックする機会があります。これは事実ですが、トークン履歴の代替手段は、攻撃者により長い機会を与える可能性があるため、それほど優れているわけではありません.
IP アドレスと User-Agent の変更をチェックする他の方法にも問題があります。ユーザー エージェントは簡単にスプーフィングされます。攻撃者がユーザーのセッションを取得できた場合、同じ XSS コードまたはその他の手段を使用して、ユーザー エージェントを簡単に特定できます。
ユーザーがモバイル デバイスを使用している場合、IP アドレスが頻繁に変更される可能性があるため、多くの誤検知が発生する可能性があります。さらに、攻撃者は同じ会社のファイアウォールの背後にいる可能性があるため、ユーザーと攻撃者の IP は外部 Web サーバーに対して同じになります。
タイムスタンプトークンを使用するのは正しいアプローチですか、それともより良い方法がありますか? 30 秒のバッファーは適切ですか? 私が見逃しているエッジケースは何ですか?