在隐藏的表单字段中实现 CSRF 令牌是 CSRF 对表单发布请求的标准保护。
但是,您将如何为 GET 请求实现此功能?或者 ajax 请求 POST json 数据而不是 x-www-form-urlencoded 请求正文?这些类型的事情都是根据具体情况处理的吗?
OWASP关于 CSRF 和 GET 请求这样说:
理想的解决方案是仅在 POST 请求中包含 CSRF 令牌,并修改具有状态更改影响的服务器端操作以仅响应 POST 请求。这实际上是 RFC 2616 对 GET 请求的要求。如果保证敏感的服务器端操作只响应 POST 请求,则无需在 GET 请求中包含令牌。
此外,OWASP 指出:
此控件的许多实现包括 GET (URL) 请求中的质询令牌 [...]虽然此控件确实有助于降低 CSRF 攻击的风险,但唯一的每个会话令牌正在为 GET 请求公开。GET 请求中的 CSRF 令牌可能会在多个位置泄露:浏览器历史记录、HTTP 日志文件、指出记录 HTTP 请求第一行的网络设备,以及受保护站点链接到外部站点时的引用标头。
这里的问题是,如果用户的令牌被泄露,你仍然很容易受到攻击——而且泄露令牌太容易了。我不确定您的问题是否有一个很好的答案,不涉及将所有这些 GET 请求转换为 POST 请求。
值得注意的是,ASP.NET WebForms 中的 Viewstate 功能确实提供了一些针对 CSRF的保护,尽管它非常有限- 事实上,它也只保护 POSTback 请求。
为了更简单地说明这一点,您不应该使用 GET 请求作为任何函数的入口点,这些函数除了返回只读资源以供浏览器呈现之外,还执行其他操作。所以不要让 AJAX 脚本对像transferMoney.aspx?fromAcct=xyz&toAcct=abc&amount=20
.
HTTP 规范明确指出 HTTP GET 请求不应有副作用。尽可能保持 GET 请求幂等被认为是最佳实践。
我写了一篇关于保护 ASP.NET MVC 免受 CSRF 攻击的文章,它阐明了AntiForgeryToken
在您的站点上应用 POST 控制器方法的实用方法。
这取决于您应用的 CSRF 保护模式。首先,CSRF 适用于改变状态的端点。如果您是 GET 请求更改状态,那么我建议您将它们修改为 POST。话虽如此,这是一个有效的观点。
保存 Tokens 的理想位置是在 AUTH Header 中。这是跨 FORM-POST、AJAX 和 GET 请求的最低公分母。您当然可以将 Token 存储在 Cookie 中,但是当应用于多域站点时,这种设计存在漏洞。
您可以在 FORM-POST 期间从隐藏字段中解析 Token 而不会出现问题。改变这一点没有多大意义。假设您的GET请求是使用 AJAX 调用的,您可以利用 JQuery 的ajaxSetup方法在每个 AJAX 请求上自动插入 Token:
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "TOKEN " + myToken);
}
});
有一种相对较新的模式获得了关注,称为加密令牌模式。它在这里有详细描述,也在官方的OWASP CSRF Cheat Sheet上。还有一个名为ARMOR的工作实现,它可以为您提供您在各种类型的请求中寻找的灵活性。