【发布时间】:2012-08-19 03:07:29
【问题描述】:
在隐藏的表单字段中实现 CSRF 令牌是 CSRF 对表单发布请求的标准保护。
但是,您将如何为 GET 请求实现此功能?或者 ajax 请求 POST json 数据而不是 x-www-form-urlencoded 请求正文?这些类型的事情都是根据具体情况处理的吗?
【问题讨论】:
在隐藏的表单字段中实现 CSRF 令牌是 CSRF 对表单发布请求的标准保护。
但是,您将如何为 GET 请求实现此功能?或者 ajax 请求 POST json 数据而不是 x-www-form-urlencoded 请求正文?这些类型的事情都是根据具体情况处理的吗?
【问题讨论】:
OWASP says this 关于 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 的保护,though it's very limited - 事实上,它也只保护 POSTback 请求。
为了更简单地说明这一点,您不应将 GET 请求用作任何函数的入口点,该函数除了返回只读资源以供浏览器呈现之外,还执行其他操作。因此,不要让 AJAX 脚本对 transferMoney.aspx?fromAcct=xyz&toAcct=abc&amount=20 之类的 URL 进行基于 GET 的调用。
HTTP 规范states explicitly HTTP GET 请求不应有副作用。尽可能保持您的 GET 请求idempotent 被认为是最佳实践。
我已经写了an article 关于保护 ASP.NET MVC 免受 CSRF 的攻击,它阐明了将AntiForgeryToken 应用于您网站上的 POST 控制器方法的实用方法。
【讨论】:
这取决于您应用的 CSRF 保护模式。首先,CSRF 适用于改变状态的端点。如果您是 GET 请求更改状态,那么我建议您将它们修改为 POST。话虽如此,这是一个有效的观点。
持久化 Token 的理想位置是在 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);
}
});
有一种相对较新的模式获得了关注,称为加密令牌模式。 here有详细描述,官方OWASP CSRF Cheat Sheet也有。还有一个名为 ARMOR 的工作实现,它可以为您提供您在各种类型的请求中寻找的灵活性。
【讨论】: