在許多教程和指南中,我看到應該根據請求刷新CSRF令牌。我的問題是為什麼我必須這樣做?在每個會話中使用單個CSRF令牌是否比在每個請求中生成一個並跟踪所請求的令牌要容易得多?
在每個請求的基礎上生成令牌似乎並不能提高安全性。每個會話令牌已經可以了。唯一的論據似乎是XSS保護,但這並不適用,因為當您遇到XSS漏洞時,腳本仍然可以讀出新令牌。
每個請求生成新令牌有什麼好處?
在許多教程和指南中,我看到應該根據請求刷新CSRF令牌。我的問題是為什麼我必須這樣做?在每個會話中使用單個CSRF令牌是否比在每個請求中生成一個並跟踪所請求的令牌要容易得多?
在每個請求的基礎上生成令牌似乎並不能提高安全性。每個會話令牌已經可以了。唯一的論據似乎是XSS保護,但這並不適用,因為當您遇到XSS漏洞時,腳本仍然可以讀出新令牌。
每個請求生成新令牌有什麼好處?
由於已經討論的原因,沒有必要為每個請求生成新的令牌。它帶來了幾乎為零的安全優勢,並且在可用性方面使您付出了代價:一次只能使用一個令牌,用戶將無法正常瀏覽Web應用程序。例如,如果他們單擊“後退”按鈕並使用新值提交表單,則提交將失敗,並可能向他們發送一些敵對的錯誤消息。如果他們嘗試在第二個選項卡中打開資源,他們會發現會話在一個或兩個選項卡中隨機中斷。通常不值得犧牲應用程序的可用性來滿足這一無意義的要求。
在一個地方,值得 發行一個新的CSRF令牌:一個會話。也就是說,主要是在登錄時。這是為了防止會話固定攻擊導致CSRF攻擊的可能性。
例如:攻擊者訪問站點並生成一個新會話。他們獲取會話ID並將其註入受害者的瀏覽器中(例如,通過從易受攻擊的鄰居域編寫cookie或使用其他漏洞(如jsessionid URL)),還將CSRF令牌注入受害者的瀏覽器中的一種形式。他們等待受害者使用該表單登錄,然後使用另一個表單發布讓受害者使用仍然有效的CSRF令牌執行操作。
為防止這種情況,請使CSRF令牌無效並在您已經在對會話ID進行相同操作的地方(例如登錄名)發布一個新的密碼,以防止會話固定攻擊。
概述。標準建議是使用唯一的CSRF令牌,該令牌對於每個請求都是唯一的。為什麼?因為與每個會話令牌相比,每個請求令牌對某些類型的實現錯誤更具彈性。這使得每個請求令牌可以說是新Web應用程序開發的最佳選擇。同樣,沒有安全審核員會麻煩您使用按請求的CSRF令牌。
如果您是Web應用程序開發人員,這就是您所需要知道的,您可以在這裡停止閱讀。但是,如果您是安全專家,想知道此建議背後的詳細原理,或者想知道如果您確實使用按會話的令牌會帶來多大的風險,請繼續閱讀...。
深入研究。事實是,如果您的網站中沒有其他漏洞,則每個會話一個CSRF令牌就可以了。沒有理由為什麼您必須必須為每個請求生成一個新的CSRF令牌。
事實也證明了這一點,您還會找到著名的安全專家,他們說另一種合理的做法防禦CSRF的方法是使用cookie兩次提交:換句話說,您使用一些客戶端Javascript計算會話cookie的哈希並將其添加到每個POST請求中,並將哈希視為CSRF令牌。您可以看到,這實質上是即時生成的CSRF令牌與整個會話相同。
當然,我知道為什麼有人建議為每個請求生成一個新的CSRF令牌的爭論。他們在想,如果您的網站上也存在XSS漏洞,那麼如果您在每個會話中使用單個CSRF令牌,則使用XSS即可輕鬆恢復CSRF令牌,而如果您根據每個請求生成一個新的CSRF令牌,則會很容易將需要更多的工作來恢復CSRF令牌。就我個人而言,我認為這不是一個令人信服的論點。如果您的站點上存在XSS漏洞,即使您為每個請求生成一個新的CSRF令牌,也仍然可以恢復CSRF令牌,它只需要多加幾行惡意Javascript。無論哪種方式,如果您的站點上都有XSS漏洞,並且您面對的是嚴重的,知識淵博的攻擊者,那麼無論您如何生成CSRF令牌,都很難保證安全性。
總體而言,它不會造成傷害為每個請求生成一個新的CSRF令牌。也許最好這樣做,只是讓安全審核員擺脫困境。但是,如果您已經有一個在整個會話中使用單個CSRF令牌的舊版應用程序,那麼花錢將其轉換為每個請求生成一個新的CSRF令牌可能不會在我的優先級列表中過高:我敢打賭可以找到這筆錢和開發人員精力的其他用途,從而進一步提高安全性。
XSS可以用來讀取CSRF令牌,即使它是單個提交令牌也是如此,這就是孩子的遊戲。推薦的單個提交令牌可能來自不了解CSRF的人。
使用“單個提交令牌”的唯一原因是要防止用戶意外單擊提交。兩次。這樣做的一個好方法是防止用戶兩次單擊“結帳”並意外向客戶收費兩次。
CAPTCHA或要求用戶提供當前密碼可以用作不能使用的反csrf措施
我建議閱讀 CSRF預防速查表。
如果令牌在整個會話中都是相同的,則攻擊者可能會從一頁洩漏令牌並將其用於其他操作。
例如,您可以使用iframe加載頁面,然後使用XSS漏洞提取令牌。從那裡開始,您可以使用該令牌提交密碼更改表單
使用每個請求令牌而不是整個會話範圍的令牌會更加困難,但這不會阻止CSRF。攻擊者可以簡單地利用XSS從頁面讀取令牌,然後將其觸發。但是,如果令牌是全局的,而不是局限於該單個頁面,則攻擊者可以將任何頁面作為目標來竊取令牌。為每個請求使用單獨的令牌會更加困難。
除其他答案外,如果您的服務器容易受到 BREACH攻擊的影響,那麼刷新令牌也很明智。
這需要滿足以下三個條件:
- 由使用HTTP級壓縮的服務器提供服務
- 在HTTP響應正文中反映用戶輸入
- 反映秘密(例如作為HTTP響應正文中的 CSRF令牌)
為減輕破壞,您需要在加載表單的GET請求上刷新CSRF令牌使所有先前的令牌無效。這樣,創建附加請求以發現頁面中令牌的MITM(中間人)每次都會獲得一個不同的令牌。這確實意味著真實用戶在MITM情況下將無法提交表單。
當然,您還需要滿足其他兩個條件。在每個會話中維護CSRF令牌並為任何提供表單的頁面禁用HTTP級壓縮可能會更容易。
這不是一個眾所周知的事實,但是普通的字符串比較容易受到定時攻擊(例如這種。長話短說,普通的字符串比較操作( ==
或 ===
)將兩個字符串從左到右逐個字符地進行比較,一旦在兩個字符串中的給定位置遇到任何不相等的字符,則返回false。 被證明是可檢測的
。通過使用定時攻擊來嘗試每個位置的每個可能字符,可以弄清楚實際令牌是什麼。通過每次提交帶有令牌的請求時都創建一個新令牌,可以防止這種攻擊。
當然,只有在無效時也重新創建令牌的情況下,此攻擊才有效令牌已提交,這可能是不希望的。因此,最好使用時間不敏感的字符串比較功能(例如this)來解決此問題。
每個請求要更改CSRF令牌的原因之一是減輕令牌的壓縮洩漏。我的意思是,如果攻擊者Eve可以在包含令牌的頁面上註入數據,然後向頁面發送壓縮的Eve,則可以猜測字符串的第一個字符,從而為該頁面接收較小的數據集,因為她知道自己猜對了,然後就去了。轉到下一個字符。
這類似於定時攻擊。
目前(我知道)沒有理由僅在HTTP標頭中發送令牌時更改令牌。
另一種方法是在發現失敗的請求後立即更改令牌,但這可能會導致用戶無法提交任何表單。
如果整個會話使用相同的令牌,那麼攻擊者就有可能使用 XSS 劫持令牌,並使用受害者的會話進行某些惡意活動,例如更改密碼。
他們可以通過將iframe拖到您正在使用的網站中來偽裝密碼。
因此,每個請求最好使用一個令牌,以避免攻擊者獲取訪問該令牌。