在HTTP GET中使用MVC3的AntiForgeryToken来避免Javascript CSRF漏洞
关于这个被黑客攻击的博客,我对实施提议的反 JSON 犹豫不决GET 劫持解决方案,因为
减轻 JSON 劫持的建议解决方案涉及使用非 REST 完整 JSON POST 获取数据
替代解决方案(对象包装)导致我无法访问源代码的第 3 方控件出现问题。
我找不到经过社区审查的实现来实现替代解决方案(如下所列),以了解如何编写安全令牌或在网页中安全地交付它。我也不会声称自己是足够的专家来推出自己的实现。
不能依赖Referrer标头
背景
此博客描述了有关 JSON 劫持的 CSRF 问题,并建议使用 JSON POST 来获取数据。由于使用 HTTP POST 获取数据并不是非常 RESTfull,因此我正在寻找一种更加 RESTfull 的解决方案,该解决方案能够为每个会话或每个页面启用 REST 操作。
另一种缓解技术是将 JSON 数据包装在对象中如此处所述< /a>.恐怕这可能会推迟问题的解决,直到找到另一种技术。
替代实现
对我来说,扩展使用 ASP 似乎很自然.NET MVC 的 AntiForgeryToken 与我的 JSON 的 jQuery HTTP GET。
例如,如果我获取一些敏感数据,根据上面的 Haacked 链接,以下代码很容易受到攻击:
$.getJSON('[url]', { [parameters] }, function(json) {
// callback function code
});
我同意使用推荐的 POST 解决方法获取数据不是 RESTfull。我的想法是在 URL 中发送验证令牌。这样,CSRF 式攻击者就不会知道完整的 URL。缓存或未缓存,他们都无法获取数据。
下面是如何完成 JSON GET 查询的两个示例。我不确定哪种实现最有效,但可能猜测第一个实现更安全,不会被错误的代理缓存此数据,从而使其容易受到攻击者的攻击。
http://localhost:54607/Home/AdminBalances/ENCODEDTOKEN-TOKEN-HERE
或
http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE
...这也可能是 MVC3 的AntiForgeryToken 或变体 (参见 swt)。该令牌将被设置为上面选择的任何 URL 格式的内联值。
阻止我推出自己的解决方案的示例问题
您将使用什么 URL 格式(上面)来验证 JSON GET(斜杠、问号等)代理会响应 http://localhost:54607/Home/AdminBalances 与 http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE 数据?
您将如何将该编码令牌传送到网页?内联还是作为页面变量?
您将如何编写令牌?内置 AntiforgeryToken,还是通过其他方式?
AntiForgeryToken 使用 cookie。在这种情况下会使用/需要支持 cookie 吗?仅限 HTTP? SSL 与 HTTP Only 结合使用怎么样?
您将如何设置缓存标头? Google Web Accelerator 的任何特殊内容(例如)
仅使 JSON 请求 SSL 有何影响?
为了安全起见,返回的 JSON 数组是否仍应包装在对象中?
此解决方案将如何与 Microsoft 提议的 模板化和数据绑定功能
上面的问题是我没有继续前进并自己做这件事的原因。更不用说可能还有更多我没有想到但仍然存在风险的问题。
In regards to this Haacked blog, I'm hesitant to implement the proposed anti-JSON GET hijacking solutions since
The recommended solutions to mitigating JSON hijacking involve non-REST-full JSON POSTs to GET data
The alternate solution (object wrapping) causes problems with 3rd party controls I don't have source-code access to.
I can't find a community-vetted implementation that implements the Alternative Solution (listed below) on how to compose the security token, or securely deliver it within the webpage. I also won't claim to be enough of an expert to roll my own implementation.
Referrer headers can't be relied upon
Background
This blog describes a CSRF issue regarding JSON Hijacking and recommends using JSON POSTs to GET data. Since using a HTTP POST to GET data isn't very REST-full, I'd looking for a more RESTfull solution that enables REST actions per session, or per page.
Another mitigation technique is to wrap JSON data in an object as described here. I'm afraid this may just delay the issue, until another technique is found.
Alternative Implementation
To me, it seems natural to extend the use ASP.NET MVC's AntiForgeryToken with jQuery HTTP GETs for my JSON.
For example if I GET some sensitive data, according to the Haacked link above, the following code is vulnerable:
$.getJSON('[url]', { [parameters] }, function(json) {
// callback function code
});
I agree that it isn't RESTfull to GET data using the recommended POST workaround. My thought is to send a validation token in the URL. That way the CSRF-style attacker won't know the complete URL. Cached, or not cached, they won't be able to get the data.
Below are two examples of how a JSON GET query could be done. I'm not sure what implementation is most effective, but may guess that the first one is safer from errant proxies caching this data, thus making it vulnerable to an attacker.
http://localhost:54607/Home/AdminBalances/ENCODEDTOKEN-TOKEN-HERE
or
http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE
... which might as well be MVC3's AntiForgeryToken, or a variant (see swt) thereof. This token would be set as an inline value on whatever URL format is chosen above.
Sample questions that prevent me from rolling my own solution
What URL format (above) would you use to validate the JSON GET (slash, questionmark, etc) Will a proxy respond to http://localhost:54607/Home/AdminBalances with http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE data?
How would you deliver that encoded token to the webpage? Inline, or as a page variable?
How would you compose the token? Built in AntiforgeryToken, or by some other means?
The AntiForgeryToken uses a cookie. Would a backing cookie be used/needed in this case? HTTP Only? What about SSL in conjunction with HTTP Only?
How would you set your cache headers? Anything special for the Google Web Accelerator (for example)
What are the implications of just making the JSON request SSL?
Should the returned JSON array still be wrapped in an object just for safety's sake?
How will this solution interop with Microsoft's proposed templating and databinding features
The questions above are the reasons I'm not forging ahead and doing this myself. Not to mention there likely more questions I haven't thought of, and yet are a risk.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Asp.net MVC AntiForgeryToken 无法通过 HTTP GET 工作,因为它依赖于 HTTP POST 的 cookie(它使用“双重提交 Cookie" 技术在 OWASP XSRF 预防备忘单)。您还可以通过设置 httponly 来额外保护发送到客户端的 cookie,以便它们无法通过脚本进行欺骗。
在本文档中,您可以找到可用于防止 XSRF 的各种技术。看来您所描述的属于方法 1。但是我们在使用 Ajax HTTP GET 请求时如何检索服务器上的会话存在问题,因为 cookie 不随请求一起发送。因此,您还必须向操作的 URL 添加会话标识符(又名无 cookie 会话,更容易被劫持)。因此,为了执行攻击,攻击者只需要知道正确的 URL 即可执行 GET 请求。
也许一个好的解决方案是使用用户 SSL 证书中的某些密钥(例如证书指纹)来存储会话数据。这样,只有 SSL 证书的所有者才能访问他的会话。这样您就不需要使用 cookie,也不需要通过查询字符串参数发送会话标识符。
无论如何,如果您不想在 Asp.net MVC 中使用 HTTP POST,则需要推出自己的 XSRF 保护。
The Asp.net MVC AntiForgeryToken won't work through HTTP GET, because it relies on cookies which rely on HTTP POST (it uses the "Double Submit Cookies" technique described in the OWASP XSRF Prevention Cheat Sheet). You can also additionally protect the cookies sent to the client by setting the as httponly, so they cannot be spoofed via a script.
In this document you can find various techniques that can be used to prevent XSRF. It seems the you described would fall into the Approach 1. But we have a problem on how to retrieve the session on the server when using Ajax HTTP GET request since the cookies are not sent with the request. So you would also have to add a session identifier to you action's URL (aka. cookieless sessions, which are easier to hijack). So in order to perform an attack the attacker would only need to know the correct URL to perform the GET request.
Perhaps a good solution would be to store the session data using some key from the users SSL certificate (for example the certs thumb-print). This way only the owner of the SSL certificate could access his session. This way you don't need to use cookies and you don't need to send session identifiers via query string parameters.
Anyway, you will need to roll out your own XSRF protection if you don't want to use HTTP POST in Asp.net MVC.
我遇到了这个问题,解决方案并不是那么简单,但是有一个很棒的博客可以帮助您入门,它可以与 get 和 post ajax 一起使用。
http://johan.driessen .se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC
如果您将以下内容放置在全局名称空间中,您的所有帖子/获取都可以利用防伪造功能令牌,您不必修改您的 ajax 调用。在公共页面中创建输入元素。
以下javascript将读取防伪tokken并将其添加到请求标头中。
I came to this problem and the solution was not so trivial however there is a fantastic blog to get you started this can be used with get and post ajax.
http://johan.driessen.se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC
If you place the following in the global name space all your post/gets can take advantage having an anti forgery token and you don't have to modify your ajax calls. Create an input element in a common page.
The following javascript will read the anti forgery tokken and add it to the request header.
我认为在 ajax http GET 请求中使用 AntiforgeryToken (AFT) 是合法的,前提是它嵌入到已经提供 AFT 和关联 cookie 的表单中。然后,ajax 处理程序可以在服务器上进行验证,就像在正常形式的帖子中一样。
I think it is legitimate to use AntiforgeryToken (AFT) within an ajax http GET request provided that it is embedded in a form that already provides the AFT and associated cookie. The ajax handler can then do the validate on the server just how it would in a normal form post.