CSRFの問題全体とそれを防ぐための適切な方法を理解しようとしています。(私が読み、理解し、同意したリソース:OWASP CSRF防止に関するチートシート、CSRFに関する質問)
私が理解しているように、CSRFに関連する脆弱性は、(Webサーバーの観点から)着信HTTPリクエストの有効なセッションCookieが認証済みユーザーの希望を反映しているという仮定によって導入されています。ただし、オリジンドメインのすべてのCookieはブラウザーによってリクエストに魔法のようにアタッチされているため、実際のサーバーは、リクエスト内の有効なセッションCookieの存在から、認証されたセッションを持つブラウザーからのリクエストであると推測できます。それはコードについて何も仮定することはできませんそのブラウザで実行している、またはそれが本当にユーザーの希望を反映しているかどうか。これを防ぐ方法は、リクエストに追加の認証情報(「CSRFトークン」)を含めることです。これは、ブラウザの自動Cookie処理以外の方法で行われます。大まかに言えば、セッションCookieはユーザー/ブラウザーを認証し、CSRFトークンはブラウザーで実行されているコードを認証します。
つまり、簡単に言うと、セッションCookieを使用してWebアプリケーションのユーザーを認証している場合は、各応答にCSRFトークンを追加し、各(変更)リクエストで一致するCSRFトークンを要求する必要があります。次に、CSRFトークンはサーバーからブラウザーへとサーバーからサーバーへの往復を行い、要求を行っているページがそのサーバーによって承認されている(生成されている)ことをサーバーに証明します。
私の質問に戻ります。これは、その往復でそのCSRFトークンに使用される特定の転送方法についてです。
(AngularJS、Django、Railsなどで)CSRFトークンをサーバーからクライアントにCookieとして(つまり、Set-Cookieヘッダーで)送信し、クライアントのJavascriptでCookieから削ってそれを添付するのが一般的ですサーバーに送り返す別のXSRF-TOKENヘッダーとして。
(別の方法は、たとえばExpressによって推奨される方法です。サーバーによって生成されたCSRFトークンは、サーバー側のテンプレート拡張を介して応答本文に含まれ、サーバーに戻すコード/マークアップに直接添付されます。非表示のフォーム入力として。この例は、よりWeb 1.0風の方法ですが、より一般的なJSの重いクライアントに一般化されます。
CSRFトークンのダウンストリームトランスポートとしてSet-Cookieを使用するのはなぜそれほど一般的ですか。なぜこれが良いアイデアなのでしょうか。これらすべてのフレームワークの作成者がオプションを慎重に検討し、これを間違えなかったと思います。しかし、一見したところ、基本的にCookieの設計上の制限を回避するためにCookieを使用することは、お粗末なようです。実際、ラウンドトリップトランスポートとしてCookie(サーバーの下流にSet-Cookie:ヘッダーがブラウザにCSRFトークンを通知し、ブラウザにそれをサーバーに返すようにCookie:ヘッダーを上流に送信する)を使用した場合、脆弱性が再導入されます。修正しようとしています。
上記のフレームワークは、CSRFトークンのラウンドトリップ全体でCookieを使用しないことに気づきました。彼らはSet-Cookieダウンストリームを使用し、次に他の何か(X-CSRF-Tokenヘッダーなど)をアップストリームに使用します。これにより、脆弱性が排除されます。ただし、ダウンストリームトランスポートとしてSet-Cookieを使用しても、誤解を招く可能性があり、危険です。これで、ブラウザはCSRFトークンをすべての要求に添付し、本物の悪意のあるXSRF要求を含みます。せいぜい要求が必要以上に大きくなり、最悪の場合でも意味のあるサーバーコードの一部が実際にそれを使用しようとする可能性があり、これは本当に悪いことです。さらに、CSRFトークンの実際の受信者はクライアント側のJavascriptであるため、このCookieをhttpのみで保護することはできません。