CSRF令牌 - 如何正确实施?

时间:2011-09-15 15:48:49

标签: php security csrf

我刚刚在我的应用程序中设置了一个简单的CSRF保护。它会创建一个独特的面包屑,在提交表单时会根据会话值进行验证。

不幸的是,这意味着我不能同时打开我的应用程序中的多个实例(浏览器中的选项卡),因为CSRF碎屑彼此冲突。

我应该为每个实际表单创建一个单独的令牌,还是为我的所有表单使用共同的共享面包屑? 这里有什么常识?

3 个答案:

答案 0 :(得分:5)

你可以做任何一件事。这取决于您想要的安全级别。

OWASP Enterprise Security API(ESAPI)使用每个用户会话方法的单个令牌。假设您没有XSS漏洞并且会话时间相当短,那么这可能是一种非常有效的方法。如果您允许会话保持活动数天或数周,那么这不是一个好方法。

就个人而言,我并不觉得难以为每个表单的每个实例使用不同的标记。我使用键值对在用户会话中存储结构。每个项目的关键是表单的ID,值是包含令牌的另一个结构以及该令牌的到期日期。通常情况下,我只允许令牌存活10-20分钟,然后它就会过期。对于更长的表格,我可以给它一个很长的到期时间。

如果您希望能够在同一会话中的多个浏览器选项卡中支持相同的表单,那么我的方法会变得有点诡计,但仍然可以通过使用唯一的表单ID轻松完成。

答案 1 :(得分:4)

OWASP Cheat Sheet对这类事情有最明确的答案。它讨论了不同的方法以及安全性与可用性的平衡。

简而言之,他们建议每个(浏览器)会话使用一个令牌。换句话说,在您的情况下,标签之间共享相同的标记。备忘单还强调,不要将您的站点暴露给跨站点脚本漏洞非常重要,因为这会破坏每个会话的CSRF令牌策略。

答案 2 :(得分:-3)

据我所知,CSRF可以使用

1)随机数并将其保存到会话中:
将其添加到名为hidden的隐藏输入,然后当您重新接收信息时,您可以使用会话值

检查隐藏字段

2)静态配置变量(与之前但没有会话一样)
隐藏字段将包含此值(来自config的变量)。验证时,您将检查隐藏的已发布和配置安全密钥值

3)HTTP Referer
您可以使用http referrer来了解用户的来源,然后使用真实域进行检查(如果您的网站包含xss,此方法可能会受到攻击)。

据我所知,您可以使用任何解决方案:)