在HTTP GET中使用MVC3的AntiForgeryToken来避免Javascript CSRF漏洞

时间:2011-02-06 17:44:48

标签: json asp.net-mvc-3 csrf antiforgerytoken

In regards to this Haacked blog,我对实施提议的反JSON GET劫持解决方案犹豫不决

  1. 缓解JSON劫持的推荐解决方案涉及非REST全JSON POST以获取GET数据

  2. 备用解决方案(对象包装)导致第三方控件出现问题我没有源代码访问权限。

  3. 我找不到一个社区审核实施,它实现了如何撰写安全令牌或在网页中安全地传递安全令牌的替代解决方案(如下所列)。我也不会声称只有专家来推动我自己的实施。

  4. 不能依赖推荐人标题

  5. 背景

    This blog描述了有关JSON劫持的CSRF问题,并建议使用JSON POST来获取GET数据。由于使用HTTP POST来获取GET数据并不是非常REST,我会寻找一个更多的RESTfull解决方案,它可以在每个会话或每页上启用REST操作。

    另一种缓解技术是将JSON数据包装在对象as described here中。我担心这可能会延迟这个问题,直到找到另一种技术。

    替代实施

    对我来说,使用jQuery HTTP GET为我的JSON扩展使用ASP.NET MVC's AntiForgeryToken似乎很自然。

    例如,如果我获取一些敏感数据,根据上面的Haacked链接,以下代码容易受到攻击:

    $.getJSON('[url]', { [parameters] }, function(json) {
        // callback function code
    });
    

    我同意使用推荐的POST解决方法来获取数据不是RESTfull。我的想法是在URL中发送验证令牌。这样,CSRF式攻击者就不会知道完整的URL。缓存或不缓存,他们将无法获取数据。

    下面是两个如何完成JSON GET查询的示例。我不确定哪种实现最有效,但可能会猜测第一种实现更容易从错误的代理缓存此数据,从而使其容易受到攻击者的攻击。<​​/ p>

    http://localhost:54607/Home/AdminBalances/ENCODEDTOKEN-TOKEN-HERE

    http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE

    ......也可能是MVC3的AntiForgeryToken,或其变体(see swt)。此标记将设置为上面选择的任何URL格式的内联值。

    阻止我推出自己的解决方案的示例问题

    1. 您将使用哪种网址格式(上方)来验证JSON GET(斜杠,问号等)代理会使用http://localhost:54607/Home/AdminBalances数据回复http://localhost:54607/Home/AdminBalances?ENCODEDTOKEN-TOKEN-HERE吗?

      < / LI>
    2. 您如何将该编码令牌传递到网页?内联,或作为页面变量?

    3. 你会如何撰写令牌?内置AntiforgeryToken,还是通过其他方式?

    4. AntiForgeryToken使用cookie。在这种情况下是否会使用/需要支持cookie?仅HTTP?那么SSL与仅HTTP一起使用呢?

    5. 您将如何设置缓存标头? Google Web Accelerator的任何特殊功能(例如)

    6. 只是将JSON请求设为SSL会有什么影响?

    7. 为了安全起见,返回的JSON数组是否仍然包裹在对象中?

    8. 此解决方案如何与Microsoft提议的templating and databinding功能相互配合

    9. 上述问题是我自己没有提前做这件事的原因。更不用说可能还有更多我没有想过的问题,但却存在风险。

3 个答案:

答案 0 :(得分:15)

Asp.net MVC AntiForgeryToken无法通过HTTP GET工作,因为它依赖于依赖HTTP POST的cookie(它使用OWASP XSRF Double Submit Cookies中描述的“Prevention Cheat Sheet”技术) 。您还可以通过设置为httponly来保护发送给客户端的cookie,这样就不会通过脚本欺骗它们。

this document中,您可以找到可用于防止XSRF的各种技术。您所描述的似乎属于方法1.但是我们在使用Ajax HTTP GET请求时如何在服务器上检索会话时遇到问题,因为cookie不随请求一起发送。所以你还需要为你的动作的URL添加一个会话标识符(也就是那些更容易被劫持的cookieless会话)。因此,为了执行攻击,攻击者只需知道正确的URL即可执行GET请求。

也许一个好的解决方案是使用用户SSL证书中的某些密钥存储会话数据(例如certs thumb-print)。这样,只有SSL证书的所有者才能访问其会话。这样您就不需要使用cookie,也不需要通过查询字符串参数发送会话标识符。

无论如何,如果您不想在Asp.net MVC中使用HTTP POST,则需要推出自己的XSRF保护。

答案 1 :(得分:4)

我遇到了这个问题并且解决方案并非如此微不足道,但是有一个很棒的博客可以帮助你开始使用get和post ajax。

http://johan.driessen.se/posts/Updated-Anti-XSRF-Validation-for-ASP.NET-MVC-4-RC

如果您将以下内容放在全局名称空间中,那么所有发布/获取都可以利用防伪令牌,而您不必修改您的ajax调用。在公共页面中创建一个输入元素。

<form id="__AjaxAntiForgeryForm" action="#" method="post">@Html.AntiForgeryToken()</form>

以下javascript将读取防伪forkken并将其添加到请求标头。

// Wire up the global jQuery ajaxSend event handler.
$(document).ajaxSend(namespace.ajax.globalSendHandler);

// <summary>
// Global handler for all ajax send events.
// </summary>
namespace.ajax.globalSendHandler = function (event, xhr, ajaxOptions) {
    // Add the anti forgery token
    xhr.setRequestHeader('__RequestVerificationToken', $("#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]").val());
};

答案 2 :(得分:0)

我认为在 ajax http GET 请求中使用 AntiforgeryToken (AFT) 是合法的,前提是它嵌入在已经提供 AFT 和相关 cookie 的表单中。然后,ajax 处理程序可以在服务器上进行验证,就像在普通表单中一样。