セッションのCSRF保護トークンを公開しても安全ですか?
質問
Djangoには CSRF保護ミドルウェアが付属しています。フォームで使用するための一意のセッションごとのトークンを生成します。すべての着信POST
要求をスキャンして正しいトークンを探し、トークンが欠落しているか無効である場合は要求を拒否します。
一部のPOSTリクエストにAJAXを使用したいのですが、リクエストにはCSRFトークンが含まれていません。ページにはフックする<form>
要素がなく、トークンを非表示の値として挿入してマークアップを濁らせたくないです。これを行う良い方法は、/get-csrf-token/
のようなvewを公開してユーザーのトークンを返すことです。ブラウザのクロスサイトスクリプティングルールに依存して、悪意のあるサイトが要求しないようにします。
これは良い考えですか? AJAXリクエストを許可しながらCSRF攻撃から保護するより良い方法はありますか?
解決
AJAXリクエストにCSRFトークンが必要になることがわかっている場合は、いつでもどこかにHTMLに埋め込むことができます。次に、DOMをトラバースすることにより、Javascriptを介してそれを見つけることができます。この方法では、トークンにアクセスできますが、API経由で公開することはありません。
別の言い方をすると、URLディスパッチャではなく、Djangoのテンプレートを使用して実行します。この方法の方がはるかに安全です。
他のヒント
更新:以下は真であり、すべてのブラウザとプラグインが適切に実装されていれば真になります。残念ながら、これらはそうではなく、ブラウザプラグインとリダイレクトの特定の組み合わせにより、攻撃者がクロスドメインリクエストで任意のヘッダーを提供できることがわかりました。残念ながら、これは<!> quot; X-Requested-With:XMLHttpRequest <!> quot;を含むAJAXリクエストでさえも意味します。ヘッダーはCSRFで保護されている必要があります。その結果、Djangoは AjaxリクエストをCSRF保護から除外しなくなりました。
オリジナルの回答
ブラウザではクロスサイトAJAXリクエストが許可されていないため、CSRFからAJAXリクエストを保護する必要はないことに注意してください。実際、Django CSRFミドルウェアは AJAXリクエストをCSRFトークンスキャンから自動的に除外します。
これは、実際に<-> quot; XMLHttpRequest <!> quot;のサーバー側のX-Requested-Withヘッダーをチェックしている場合にのみ有効です。値(Djangoが行う)、およびCSRFスキャンからの実際のAJAXリクエストのみを除外します。
キャンセルしてください、私は間違っていました。 (コメントを参照してください。) JSONが仕様に従っていることを確認することにより、この悪用を防ぐことができます。常にオブジェクトリテラルをトップレベルオブジェクトとして返すようにしてください。 (これ以上のエクスプロイトが発生しないことは保証できません。window.onerrorイベントで失敗したコードへのアクセスを提供するブラウザを想像してください!)
AJAX応答をプライベートに保つためにクロスサイトスクリプティングルールに依存することはできません。たとえば、CSRFトークンをJSONとして返すと、悪意のあるサイトが StringまたはArrayコンストラクタを再定義して、リソースをリクエストします。
bigmattyhは正しい:マークアップのどこかにトークンを埋め込む必要があります。または、一致しないリファラーを持つ一致する POSTを拒否することもできます。そうすれば、熱心なソフトウェアファイアウォールを持っている人だけがCSRFに対して脆弱になります。