CSRF令牌生成

Jim*_*eam 46 csrf

这是关于生成CSRF令牌的问题.

通常,我想基于与用户会话相关联的唯一数据生成令牌,并使用密钥进行散列和腌制.

我的问题是在没有唯一用户数据时生成令牌.没有可用的会话,cookie不是一个选项,IP地址和这种性质的东西是不可靠的.

我有什么理由不能将字符串包含在请求中作为请求的一部分吗?示例伪代码生成令牌并嵌入它:

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

CSRF令牌的服务器端验证示例

var $stringToHash = request.get('key')
var $isValidToken = hash($stringToHash + $mySecrtKey) == request.get('csrfToken')
Run Code Online (Sandbox Code Playgroud)

散列中使用的字符串在每个请求上都是不同的.只要它包含在每个请求中,CSRF令牌验证就可以继续进行.由于每个请求都是新的,并且只嵌入在页面中,因此无法访问令牌.然后令牌的安全性落到了仅为我所知的$ mySecretKey.

这是一种天真的做法吗?我错过了一些为什么这不起作用的原因?

谢谢

blo*_*art 28

我有什么理由不能将字符串包含在请求中作为请求的一部分吗?

CSRF令牌有两部分.表单中嵌入的令牌,以及其他位置的相应令牌,可以是cookie,存储在会话中或其他地方.其他地方的使用会阻止页面自包含.

如果在请求中包含要散列的字符串,那么请求是自包含的,因此复制表单是攻击者需要做的全部内容,因为它们具有令牌的两个部分,因此没有保护.

即使将其放在表单URL中也意味着它是自包含的,攻击者只需复制表单和提交URL即可.

  • 不,你没有.一半可以保持在会话中,或者可以通过cookie丢弃.它根本不必存储在服务器上,通常是基于cookie的,因此您不必依赖启用会话. (15认同)

Dor*_*Dor 1

CSRF 令牌旨在防止(无意的)数据修改,通常与 POST 请求一起应用。

因此,您必须为每个更改数据的请求(GET 或 POST 请求)包含 CSRF 令牌。

我的问题是关于在没有可用的唯一用户数据时生成令牌的问题。没有可用的会话,cookie 不是一个选项,IP 地址和类似性质的东西不可靠。

然后只需为每个访问者创建一个唯一的用户 ID。将该 ID 包含在 Cookie 或 URL 中(如果禁用了 Cookie)。

编辑:

考虑以下事件:

您已登录您的 Facebook 帐户,然后进入某个任意网站。

在该网站中,有一个您提交的表单,它会告诉您的浏览器向您的 Facebook 帐户发送 POST 请求。

该 POST 请求可能会更改您的密码或添加评论等,因为 Facebook 应用程序将您识别为注册和登录用户。(除非有另一种阻止机制,例如 CAPTCHA )