web-dev-qa-db-ja.com

アンチCSRFフォームトークンを実装する正しい方法は何ですか?

私は [〜#〜] csrf [〜#〜] を完全に認識しており、すでにいくつかの安全なフォームを実装していますが、結果に満足していません。

ユーザー名、フォーム情報、および salt のmd5としてトークンを作成し、セッションに格納しました。これには、タブ付きブラウジング(アクティブなハッシュの配列を保持することで修正できます)とタイミングに問題があります。私のハッシュは、例えばだけのために働きたいです。 10分ですが、時間関連の変数をハッシュに入れるにはどうすればよいですか?

CSRFセキュリティを適切に作成する方法を説明している優れたリソースを誰かに教えてもらえますか?

34
naugtur

CSRF保護を適切に構築する最良の方法:

しないでください。

ほとんどの一般的なフレームワークにはこの保護機能がすでに組み込まれています(ASP.NET、Struts、Rubyだと思います)、またはすでに吟味された既存のライブラリがあります(たとえば OWASPのCSRFGuard )。

別のオプションは、状況に応じて、ユーザーの再認証を強制することですが、特定の機密性の高い操作に対してのみです。


あなたのコメントのとおり、これを自分で実装する必要がある場合、ソリューションはそれほど悪くありませんが、私はそれを簡略化します。
暗号ランダムナンス(十分な長さ)を生成し、それをセッションメモリに格納し、X分ごとに変更できます(セッションにも有効期限を格納します)。各フォームで、非表示のフォームフィールドにノンスを含め、フォームが投稿されるときにその値を比較します。
フォームトークンが一致すれば、問題ありません。そうでない場合は、受け入れることができます。前のトークンも同様に、Edgeケースを処理します。

これを自分で実装しようとして失敗したことが多すぎたので、このパスを実際に推奨することはできません。これを行うための最小限のパッケージを見つけることをお勧めします。

25
AviD

OWASPには良い説明があります: OWASP CSRF防止に関するチートシート

要するに、彼らは2つの方法があると言います:

  1. 各ユーザーセッションにランダムトークンを追加します。このトークンが存在し、正しい場合のみ、変更が適用されます。それ以外の場合、要求は拒否されます。 GETリクエストはトークンを別の場所(ブラウザの履歴、ログファイルなど)にリークする可能性があるため、トークンはPOSTリクエストでのみ送信されることが重要です。

    リクエストごとにトークンを生成することも可能ですが、これによりユーザビリティの問題が発生します。たとえば、[戻る]ボタンは正常に機能しなくなります。もちろん、セキュリティは強化されます。

    また、(セキュリティをさらに強化するために)トークンがTLS経由でのみ送信されることを確認してください。そうすれば、中間の問題に誰も出会うことはありません。

  2. もう1つのオプションは、ある種のチャレンジ-応答(CAPTCHAやワンタイムトークンなど)を使用することです。

OWASP-Pageには、機能しないいくつかの対策もリストされています。これらは

  • (秘密の)Cookieの使用
  • GETリクエストを使用しない
  • マルチステップトランザクション
  • URL書き換え
27
Andreas Arnold

@Andreas Arnoldの回答に加えて、別の方法があります。 OWaspからEncrypted Token Patternを実装しました。

Csrf攻撃の防止とは別に、オブジェクトセキュリティを実装するという追加の利点があります。

オブジェクトの変更を許可されている人だけが変更できます。他の人は、正しい/有効な暗号テキストまたはキーを持っていません。通常、sessionIdtimestampuserId、および/またはrecordIdを暗号化します。

timestampはreplayAttacksを防ぎます。 sessionidは、このセッションへの変更のみを分離しますuserIdは、このユーザーへの変更のみを分離します。 recordIdを含めると、追加の処理を犠牲にして、セキュリティを強化できます。

3
Nasir