2009-11-26 296 views
37

這是關於生成CSRF令牌的問題。CSRF令牌生成

平時我想基於掀起了獨特的作品與用戶的會話相關的數據的一個令牌,散列,並用私鑰鹹。

我的問題是關於在沒有唯一的用戶數據使用時生成令牌。沒有會話可用,Cookie不是一個選項,IP地址和這種性質的東西是不可靠的。

是否有任何理由,我可以不包括散列的以及請求的一部分字符串? 實施例的僞代碼生成令牌並將其嵌入:

var $stringToHash = random() 
var $csrfToken = hash($stringToHash + $mySecretKey) 
<a href="http://foo.com?csrfToken={$csrfToken}&key={$stringToHash}">click me</a> 

實施例的服務器端的跨站請求僞造的確認標記

var $stringToHash = request.get('key') 
var $isValidToken = hash($stringToHash + $mySecrtKey) == request.get('csrfToken') 

的字符串中的散列被用於將在每個請求不同。只要它包含在每個請求中,就可以繼續進行CSRF令牌驗證。由於每個請求都是新的,並且只嵌入在頁面中,因此外部對令牌的訪問將不可用。令牌的安全性然後落在我只知道的$ mySecretKey上。

這是一個天真的做法?我錯過了某些原因,爲什麼這不起作用?

由於

+8

所提出的解決方案是容易受到重放攻擊。相同的標記和組合鍵將無限期地工作。 – Matthew 2012-01-24 06:56:05

回答

2

CSRF令牌旨在防止(無意的)數據的修改,其通常與POST請求應用。

因此,你必須包括CSRF令牌針對每個改變的數據請求(GET或POST請求)。

我的問題是關於 生成的令牌時,有使用NO 獨特的用戶數據。沒有會話 可用,cookie不是 選項,IP地址和那個 性質是不可靠的。

然後簡單地創建爲每個訪問者的唯一用戶ID。 將該ID包含在cookie中或URL中(如果cookie被禁用)。

編輯:

考慮下列事件:

您已經登錄到您的Facebook帳戶,然後進入到一些任意網站。

在該網站上有,你提交一個表單,告訴你的瀏覽器發送POST請求到Facebook帳戶。

POST請求可能會更改您的密碼或添加評論等,因爲facebook應用程序將您識別爲註冊的&登錄用戶。 (除非還有另外一個鎖止機構,如CAPTCHA)

+0

將一部分令牌添加到一個URL中,另一半在表單中意味着沒有任何保護。 – blowdart 2009-12-04 09:27:18

+0

對不起,你是什麼意思?我沒有寫過...... – Dor 2009-12-04 10:53:38

+0

當然你確實,「將該ID包含在cookie中或URL中(如果cookie被禁用)」。 - 你說要把這個id放在URL中,這根本就不安全。 – blowdart 2009-12-04 11:30:51

-4

CSRF利用用戶的會話,所以,如果你沒有一個,有沒有CSRF。

+0

儘管這個答案根本沒有幫助,但它在技術上是正確的。 – 2016-05-25 09:27:45

25

是否有任何理由不能將字符串作爲請求的一部分散列?

CSRF令牌有兩個部分。嵌入在表單中的令牌以及其他地方的相應令牌,可以將其存儲在cookie中,存儲在會話中或其他地方。這種在其他地方的使用可以阻止頁面自成一體。

如果您在請求中包含哈希字符串,然後請求是自包含的,所以複製的形式是所有攻擊者需要做的,因爲他們有令牌的兩個部分,因而沒有任何保護措施。

即使將它放在表單URL中也意味着它是自包含的,攻擊者只需複製表單和提交URL即可。

+0

你需要記住存儲在服務器上的令牌...... – 2009-12-04 09:34:36

+14

不,你不需要。一半可以保留在會話中,或者可以通過cookie丟棄。它根本不需要存儲在服務器上,通常它是基於cookie的,因此您不必依靠啓用會話。 – blowdart 2009-12-04 09:53:17

+0

根據OWASP,這只是一個*緩解*稱爲「雙提交cookie」https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#Double_Submit_Cookies – zb226 2013-08-22 11:59:00

1

你只需要在URL /表單和cookie中使用相同的「標記」。這意味着你可以讓你的頁面通過JavaScript將令牌cookie設置爲任何想要的值(最好是一些隨機值),然後在傳送到服務器的所有請求中傳遞相同的值(作爲URI?param或form-領域)。無需讓您的服務器生成cookie。

只要我們相信瀏覽器不允許來自域的頁面編輯/讀取其他域的cookie,這是安全的,並且今天假定這是相當安全的。

讓您的服務器生成令牌會假設此令牌可以安全地傳輸到您的瀏覽器,而不會被任何CSRF嘗試(爲什麼冒險?)拾取。儘管可以將更多邏輯放入服務器生成的令牌中,但爲了防止CSRF,不需要。

(如果我錯了,在這裏請讓我知道)

0

我認爲最好的主意,以哈希基於HMAC,即讓哈希一些密碼本序列加密:用戶名+ USER_ID +時間戳。每個哈希請求必須不同,如果你不想簡單地重放攻擊哈希,時間戳必須是。

0

我想說你的方法奏效,因爲CSRF攻擊是攻擊者利用受害者的瀏覽器僞造登錄狀態,爲什麼他們可以這樣做?因爲在大多數服務器端,會話檢查是基於Cookie中的SessionID,並且Cookie是將一段數據自動附加到發送給服務器的HTTP請求。

因此,有兩個關鍵因素爲保衛CSRF

  1. 生成一個挑戰令牌,並要求客戶將其傳遞到服務器在非cookie的方式,無論是網址PARAM或POST形式是好的。
  2. 保持令牌安全,就像您對SessionID執行的操作一樣,例如使用SSL。

我建議你閱讀CSRF Prevention Cheat Sheet