这是关于生成CSRF令牌的问题.
通常,我想基于与用户会话相关联的唯一数据生成令牌,并使用密钥进行散列和腌制.
我的问题是在没有唯一用户数据时生成令牌.没有可用的会话,cookie不是一个选项,IP地址和这种性质的东西是不可靠的.
我有什么理由不能将字符串包含在请求中作为请求的一部分吗?示例伪代码生成令牌并嵌入它:
var $stringToHash = random() var $csrfToken = hash($stringToHash + $mySecretKey) click me
CSRF令牌的服务器端验证示例
var $stringToHash = request.get('key') var $isValidToken = hash($stringToHash + $mySecrtKey) == request.get('csrfToken')
散列中使用的字符串在每个请求上都是不同的.只要它包含在每个请求中,CSRF令牌验证就可以继续进行.由于每个请求都是新的,并且只嵌入在页面中,因此无法访问令牌.然后令牌的安全性落到了仅为我所知的$ mySecretKey.
这是一种天真的做法吗?我错过了一些为什么这不起作用的原因?
谢谢
我有什么理由不能将字符串包含在请求中作为请求的一部分吗?
CSRF令牌有两部分.表单中嵌入的令牌,以及其他位置的相应令牌,可以是cookie,存储在会话中或其他地方.其他地方的使用会阻止页面自包含.
如果在请求中包含要散列的字符串,那么请求是自包含的,因此复制表单是攻击者需要做的全部内容,因为它们具有令牌的两个部分,因此没有保护.
即使将其放在表单URL中也意味着它是自包含的,攻击者只需复制表单和提交URL即可.
试试base64_encode(openssl_random_pseudo_bytes(16))
.
https://github.com/codeguy/php-the-right-way/issues/272#issuecomment-18688498我将它用于https://gist.github.com/mikaelz/5668195中的表单示例