2008-09-27 82 views
15

Django附帶CSRF protection middleware,它生成一個唯一的每個會話令牌以用於表單。它會掃描所有傳入的POST對正確標記的請求,並在標記丟失或無效時拒絕請求。暴露會話的CSRF保護令牌安全嗎?

我想爲某些POST請求使用AJAX,但表示請求沒有CSRF令牌可用。這些頁面沒有<form>元素可以插入,我寧願不要將標記插入作爲隱藏值的標記。我認爲這樣做的一個好方法就是公開像/get-csrf-token/這樣的一個vew來返回用戶的令牌,依靠瀏覽器的跨站點腳本規則來防止惡意站點請求它。

這是個好主意嗎?有更好的方法來防止CSRF攻擊,同時仍然允許AJAX請求?

回答

11

如果您知道您將需要CSRF令牌來處理AJAX請求,您可以隨時將其嵌入到HTML中;那麼你可以通過遍歷DOM來通過Javascript找到它。這樣,您仍然可以訪問該令牌,但不會通過API公開它。

換句話說:通過Django的模板來做 - 而不是通過URL調度器。這種方式更安全。

+1

CSRF令牌應隨每個操作而改變。你是否建議每個操作更新令牌?這並不意味着用戶的操作必須變得同步(其次在第一次返回並給出新的csrf標記之前不能啓動)。 – Mystic 2010-07-22 16:34:34

+0

這不是最好的答案。正如Carl Meyer在他的回答中所說的那樣:由於Django已經以不同的方式保護了AJAX請求,所以沒有必要通過在Django *中使用token *來保護來自CSRF的AJAX請求。這也消除了神祕人的擔憂。 – hopla 2010-09-10 07:43:40

+1

也許這將幫助,即使我沒有排序關於ajax和CSRF的故事http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax – amirouche 2011-04-06 21:21:01

0

取消,我錯了。 (請參閱評論。)您可以通過確保您的JSON遵循規範來防止漏洞利用:始終確保將對象字面值作爲頂級對象返回。 (我不能保證不會有進一步的漏洞,想象一下,瀏覽器可以訪問window.onerror事件中的失敗代碼!)

你不能依靠跨站點腳本規則來保持AJAX回覆私人。例如,如果您將CSRF令牌作爲JSON返回,則惡意網站可能會redefine the String or Array constructor並請求該資源。

bigmattyh是正確的:您需要在標記中的某處嵌入標記。或者,您可以拒絕任何有一個引用不匹配匹配的POST。這樣,只有擁有過熱軟件防火牆的人才會受到CSRF的影響。

16

UPDATE:以下是真實的,如果所有瀏覽器和插件都正確實施,則應該如此。不幸的是,我們現在知道它們不是,而且某些瀏覽器插件和重定向組合可以讓攻擊者在跨域請求中提供任意頭文件。不幸的是,這意味着即使是帶有「X-Requested-With:XMLHttpRequest」頭的AJAX請求現在也必須受CSRF保護。因此,Django no longer exempts Ajax requests from CSRF protection

原來的答案

值得一提的是,保護AJAX請求從CSRF是不必要的,因爲瀏覽器不允許跨站點AJAX請求。實際上,Django CSRF中間件現在automatically exempts AJAX requests from CSRF token scanning

這隻有在實際檢查「XMLHttpRequest」值(Django所做的)的X-Requested-With頭服務器端時纔有效,並且只能從CSRF掃描中免除真正的AJAX請求。