为了使当前的应用程序变得更加安全,我一直在阅读CSRF令牌以及Nonce。
我的问题很简单,CSRF令牌和Nonce是一样的吗?从目前为止我可以收集到的是,这两种方法都有不同的技术来实现同一目标,还是我误解了什么?
如果它们不同,你能不能提供一些示例代码或指向一些链接,我可以在其中了解更多关于如何在PHP应用程序中实现nonce的信息。
谢谢!
答案 0 :(得分:14)
不,他们不一样。
Nonce防止重放攻击(防止窃听者存储已签名的请求并在以后重新提交,例如,如果Alice发送“Pay Bob $ 100”,您不希望有人重新发送100次)。
CSRF令牌修补了用户操作身份验证中特定于HTML的弱点,第三方网站可以使用查看该网站的用户凭据提交表单(例如,使用您的浏览器将evil.example.com提交表单上的JavaScript提交给facebook.com,像你一样认证。)
CSRF令牌必须是秘密的,否则攻击者将拥有伪造请求所需的缺失部分。
Nonces不必保密,如果他们与请求者的秘密签署(只要攻击者不能用一个nonce替换另一个nonce)。
您可以允许使用CSRF令牌重播请求,并且仍然可以保护CSRF(您感兴趣的是这是否是用户的故意行为,但可能不一定要阻止用户执行多次)。
事实上,这通常是有用的属性,例如允许用户使用“后退”按钮并重新提交具有更正值的表单。如果使用类似Nonce的机制实现CSRF保护,当用户刷新提交的页面时,您将收到错误警报。
在没有Nonce的情况下阻止CSRF的简单方法是将会话ID放在隐藏的字段中(不是会话中存储的值,而是会话本身的ID,与您存储的相同) PHP中的cookie [session_id()
])。提交表单时,检查表单的会话ID是否与cookie中的ID匹配。这对CSRF来说已经足够了,因为攻击者无法知道cookie的值(CSRF只允许攻击者盲目发送cookie)。
答案 1 :(得分:13)
Nonce通常是一些随机字符串,它被添加到请求只是以不可预测的方式改变数据,用于计算签名。因此,任何服务器端业务逻辑通常都不使用nonce。
虽然CSRF令牌存储在服务器上的某个位置,但是传递给客户端并需要返回到服务器进行比较。如果匹配 - 那就OK。
因此,在您的情况下,最好将csrf令牌保存在会话变量(如
)中一次$_SESSION['csrf_token'] = bin2hex(random_bytes(16));
并在会话期间以您在申请表中的所有表格中保持不变。
(如果您没有random_bytes()
,请使用random_compat对其进行填充。)
答案 2 :(得分:7)
这是一回事。 “nonce”只是一次性密码本身。它可以作为加密盐,但基本上只是一个随机值。见WP:Nonce
但总而言之,通常使用 作为 CSRF令牌。这是一个实现细节。与其他用例的区别在于它后来被断言。
答案 3 :(得分:0)
CSRF有一些限制。 如果您有要求在新标签页中打开任何页面或链接的要求,则CSRF将不允许。现有令牌仅允许在新标签页中打开页面5次。 当您尝试第六次打开时,它将创建与“服务器端=客户端令牌”不匹配的新令牌。较早的令牌将过期,并且将创建新令牌(NONCE),在这种情况下,您将收到404或405错误。