我在我的应用程序中使用令牌来防止CSRF攻击。但是这个应用程序是单页面和基于AJAX的,所以我需要找到一种方法在一个页面中为N个动作提供有效的令牌:
e.g。文档片段加载了3个可能的操作,每个操作都需要一个令牌才能正常工作,但服务器端只有一个有效的令牌...
由于每个令牌只是一个encrypted nonce(值不是基于特定形式),我想到了为每个动作自动化令牌分配的想法,如下所示:
我认为该方法不够有效,因为攻击者可以使用与我的App完全相同的脚本(检索令牌并附加到请求中)。
如何改进我的方法以有效对抗CSRF攻击?
其他信息:我的后端环境是PHP / Phalcon,令牌是generated using Phalcon。
答案 0 :(得分:3)
比仅使用AJAX标记更简单的方法可能是检查只能出现在您自己域名的AJAX请求中的标题。
有两个选项:
Origin
标头也可以用于普通的HTML表单提交,您可以在表单提交处理之前验证它是否包含您自己网站的URL。
如果您决定检查X-Requested-With
标头,则需要确保将其添加到每个AJAX请求客户端(JQuery默认会这样做)。由于此标头无法跨域发送(未经您的服务器首先同意浏览器),检查是否存在并设置为您自己的值(例如“XMLHttpRequest
”)将验证该请求不是CSRF攻击
答案 1 :(得分:2)
前一段时间我不得不处理类似的事情。使用ajax请求nonce是一个非常糟糕的主意 - 恕我直言,如果攻击者可以在不重新加载页面的情况下简单地生成它,则无效。我最终实现了以下内容:
它的主要问题在于决定nonce何时到期并清理它们,因为它们像类固醇上的细菌一样生长。您不希望用户提交一个已打开一小时的表单并因为nonce过期/删除而卡住。在这些情况下,您可以使用重新生成的随机数返回“超时,请再试一次”消息,因此根据以下请求,一切都会通过。
正如已经建议的那样,没有任何东西是100%防弹,在大多数情况下是过度杀伤。我认为这种方法在偏执和不浪费时间之间是一个很好的平衡。它对我有多大帮助吗?与极大地改善安全性相比,它做了更多的偏执。
从逻辑上思考,在这些情况下你能做的最好的事情就是分析请求背后的行为,如果他们有疑问就把它们计时。例如,来自一个ip,跟踪鼠标/键盘的每分钟20个请求,确保它们在请求之间处于活动状态。换句话说,确保请求不是自动化的,而不是确保它们带有有效的随机数。