如何在 PHP 中有效地防止跨站请求伪造 (CSRF)

Posted

技术标签:

【中文标题】如何在 PHP 中有效地防止跨站请求伪造 (CSRF)【英文标题】:How to prevent Cross-site request forgery (CSRF) effectively in PHP 【发布时间】:2016-02-19 22:52:04 【问题描述】:

我试图通过以下方式阻止CSRF 中的php

    $_SESSION['token'] 在每个页面的开头生成。我已经知道使用$_COOKIES 是完全错误的,因为它们是针对每个请求自动发送的。

    在每个<form> 中,附加以下输入:<input type="hidden" name="t" value="<?php echo '$_SESSION['token']; ?>">

    $_SESSION['token']; 已通过 $_POST['t'] 进行验证

现在我有几个小问题:

这是防止 CSRF 的好方法吗?如果不是,请解释。 当打开另一个设置相同$_SESSION变量的页面时,前一个(仍然打开的)页面会失效,如何防止这种情况发生? 对于表单,这个方法是明确的,但是如何处理正常的链接呢?是否也需要将令牌附加到每个链接?

非常感谢您。

【问题讨论】:

有一些方法可以进一步强化这一点(例如,将令牌绑定到单个表单,这样它们就不能在不同的上下文中重复使用,这就是我们的 anti-csrf 库所做的)。但你所描述的是大多数人都会做的事情。 感谢@ScottArciszewski 提供的链接和建议,我希望自己掌控一切,而不是依赖第三方库,但进一步限制它是一个非常好的主意. 【参考方案1】:

当黑客试图从经过身份验证的用户发送虚假请求时,就会发生 CSRF 攻击。通常会发生这种攻击 在网上商店或银行。

在php中防止csrf攻击我们可以: 1 = 创建检查登录功能: 如果设置了登录会话,则为 true 好的,如果不是 false 并返回登录页面。 2 = 创建一个随机的 makeToken 哈希函数:base64_encode(md5(microtime())) 并将其保存到会话中,并创建一个输入隐藏类型,其名称为 Token 函数和名称为 Token 的函数。 3 = 创建一个 checkTocken 函数并检查它,如果它等于 makeToken 函数,然后使用 unset 函数取消设置会话,并创建一个新的。

【讨论】:

【参考方案2】:

这是预防 CSRF 的好方法吗?

是的。这样做是为了强制客户端在对表单处理程序执行 POST 之前对表单执行 GET。这可以防止 CSRF 在现代浏览器中,因为浏览器会阻止客户端 javascript 向外部域发出 XHR GET 请求,因此第 3 方无法在其网站上模仿您的表单并成功获取有效令牌提交。

当打开另一个设置相同 $_SESSION 变量的页面时,前一个(仍然打开的)页面变得无效,如何防止这种情况发生?

一次允许多个令牌有效,在会话中保留一组有效令牌。或者,根本不存储令牌,而是使用令牌签名方案。我已经涉足并解释了here。备选方案 2:在整个会话中只使用一个令牌,而不会使令牌失效。 (向 cmets 中的@SilverlightFox 致敬)

对于表单这个方法是明确的,但是如何处理正常的链接呢?是否也需要将令牌附加到每个链接?

没有。你只需要保护 POST 请求,因为大概只有 POST 请求可以改变敏感数据(眨眼眨眼轻推,你坚持 REST 约定,对吧?!)并且 XHR GET 请求已经被浏览器阻止 -一边。

【讨论】:

感谢您的链接,是的,我当然会检查有效性,让我们更新我的问题以明确这一点。 什么是处理多个令牌的便捷方法,我可以使用页面 url 例如(假设用户没有两次打开同一个页面..) 我会在会话中保留一组$token => $timestamp 值;在每个表单提交array_filter那个数组上丢弃过期的token,然后用isset($_SESSION['tokens'][$_POST['token']])检查token是否有效。 我不明白为什么在 POST 之前进行 GET 是必要的?令牌验证可以在任何数据处理之前完全在服务器端完成。还是我误解了您关于提交验证的建议? @Glapa 客户端需要发出一个 GET 请求以加载包含有效令牌的表单,该令牌需要包含在他们的 POST 请求中。通过扩展,OP 应该注意不要通过 POST 泄露有效的令牌。

以上是关于如何在 PHP 中有效地防止跨站请求伪造 (CSRF)的主要内容,如果未能解决你的问题,请参考以下文章

跨站请求伪造 (CSRF) 缓解

request.getHeader("Origin") 如何防止跨站请求伪造攻击?

防止CSRF跨站请求伪造

第二百七十一节,Tornado框架-CSRF防止跨站post请求伪造

Tomcat怎样防止跨站请求伪造(CSRF)

如何解决跨站点请求伪造