2009-11-26 292 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