我試圖理解與CSRF和適當的方式來防止它的整個問題。 (資源我已閱讀,理解並同意:OWASP CSRF Prevention CHeat Sheet,Questions about CSRF。)爲什麼將CSRF預防標記放入Cookie中很常見?
據我所知,圍繞CSRF的漏洞是通過假設(從web服務器的角度來看)一個有效的會話cookie傳入的HTTP請求反映了經過身份驗證的用戶的願望。但是,所有來源域的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客戶端上。)
爲什麼使用Set- Cookie作爲CSRF令牌的下游傳輸/爲什麼這是個好主意?我想所有這些框架的作者仔細考慮了他們的選擇,並沒有得到這個錯誤。但乍一看,使用cookie來解決cookies本質上的設計限制看起來很愚蠢。事實上,如果您使用cookie作爲往返傳輸(Set-Cookie:header下游服務器告訴瀏覽器CSRF令牌,並且Cookie:header上游瀏覽器將其返回給服務器),則您將重新引入此漏洞正在嘗試修復。
我意識到上面的框架在CSRF令牌的整個往返過程中不使用cookie;他們在下游使用Set-Cookie,然後在上游使用其他東西(例如X-CSRF-Token標頭),這確實關閉了漏洞。但即使使用Set-Cookie作爲下游交通工具也可能具有誤導性和危險性。瀏覽器現在將CSRF令牌附加到包括真正的惡意XSRF請求在內的每個請求;充其量只會讓請求變得比它需要的更大,而最壞的情況是一些善意但錯誤的服務器代碼可能會嘗試使用它,這將會非常糟糕。此外,由於CSRF令牌的實際目標收件人是客戶端JavaScript,這意味着此cookie不能僅使用http保護。因此,在Set-Cookie頭中向下遊發送CSRF令牌對我來說似乎並不理想。
感謝您的詳細解答。有關Cookie在初始頁面加載的生命週期內保持有效的觀點,對於不是單頁應用程序的應用程序來說,這是一個不錯的選擇。 – metamatt
我不確定我是否理解「如何檢索CSRF令牌的AJAX請求」(「自定義標頭:下游」部分中的第4步)可以安全地完成;由於這是一個單獨的請求,因此服務器不知道它來自哪裏;它如何知道泄露CSRF令牌是安全的?在我看來,如果你不能從最初的頁面加載中獲取令牌,那麼你會丟失(不幸的是,這使得自定義的下游響應頭部不起作用)。 – metamatt
它將以這樣的方式完成,即同源策略保護響應不被不同域(例如AJAX POST)讀取。 – SilverlightFox