所以,我创建了一个以所有形式自动插入的类:<input type="hidden" name="csrf" value="csrf_value_uniq_id" />
现在我的问题是,我将密钥设置为在5分钟后过期,但是如果你留在页面上或者当你回来并且提交表单时你去吃饭,那么csrf密钥将不匹配。
现在,我可以将其设置为24小时后过期,但我不知道这是否会像预期的那样安全。我在帖子表单上使用它。
那么什么是最好的解决方案我应该怎么做呢?
答案 0 :(得分:1)
不需要服务器端状态从而超时的解决方案是签名的令牌。您创建了一个包含在表单中的随机值,然后只有您知道的签署该密钥才会显示秘密:
$secret = 'weufiwu93tu2b248hg24';
$token = uniqid('', true);
$signature = sha1($secret . ':' . $token);
然后,您将令牌和签名嵌入到表单中。再次收到表单后,使用表单中的标记重复SHA1(secret:token)
操作,并将结果与表单中的签名进行比较。如果你有一个精心挑选的,随机的秘密和一个强大的哈希,没有人能够签署令牌,但知道秘密的人,因此你已经证明了令牌来自你。
此外,您可以在表单/签名中包含一个时间戳,以限制令牌的有效性(使其超过5分钟,但不足以让令牌永远可用),用户ID绑定令牌给特定用户,预期的表单字段以防止表单字段注入以及您可能想要检查的任何其他内容。 E.g:
signature = SHA1(secret:token:timestamp:userid:[form_field_name[:...]])
对于上述签名,您在表单中嵌入了签名,标记,时间戳以及表单字段;提交后,检查提交的时间戳是否在特定窗口内,从服务器获取机密和用户ID,重新创建包含所有这些部分的签名,并根据提交的签名进行检查。
请注意,上面的代码只是一个示例,您的令牌应该使用更好的随机源并且更长,并且您的哈希函数应该像HMAC或bcrypt一样更健壮。这是传达想法,而不是实现细节。
可以在此处找到实际的实现:Kunststube\CSRFP。我把它放在一起回答这个问题,因为无论如何我需要类似的东西。
答案 1 :(得分:1)
攻击者可以通过两种方式获得有效令牌:
前者可以通过使用具有足够熵的适当随机源来减轻。后者可以通过保护传输(即HTTPS)和防止可以用来获取用户令牌的跨站点脚本攻击来建立。
如果同时执行这两项操作,您甚至可以使其永不过期(或在用户会话结束时)。