处理ASP.NET MVC中缺少/无效的AntiForgeryTokens

时间:2014-05-30 19:11:43

标签: asp.net-mvc

我在[ValidateAntiForgeryToken]行动中使用[HttpPost]属性。出于好奇,我去了一个带有表单的页面,删除了 __ RequestVerificationToken cookie,并提交了表单。

结果:

  

System.Web.Mvc.HttpAntiForgeryException:所需的防伪cookie" __ RequestVerificationToken"不存在。

本着同样的精神,我改变了cookie的价值并提交了表格。

结果:

  

System.Web.Mvc.HttpAntiForgeryException:无法解密防伪令牌。如果托管此应用程序......

在我看来,应用程序应该只检查SessionID,而不是爆炸,如果有效,则设置一个新令牌并重新显示视图。

我想知道,如果有理由说MVC抛出异常而不是做我所描述的。我正计划处理异常并按照我上面所描述的那样做,但在此之前,我想知道是否有一个很好的理由 - 可能与安全相关? - 这种情况没有得到更优雅的处理默认情况下。

3 个答案:

答案 0 :(得分:3)

获取无效令牌是一种特殊情况。因此,抛出异常。我不希望应用程序以合理的方式响应或多或少的攻击。<​​/ p>

有关异常处理的更多信息,请参阅:http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx

答案 1 :(得分:3)

@Jason我非常喜欢你的想法我决定实施它。

更新:顺便说一句,我没有看到以下列方式处理这些异常的任何安全问题。它肯定比不使用防伪验证更安全。基本上,黑客可以做的唯一事情就是设置GET请求的查询字符串,并且通常只有POST请求才需要反XSRF(除非您使用GET请求修改数据... tisk-tisk),如果黑客瞄准GET请求他们可以直接向您的网站提供精心设计的链接,而不是通过自己的网站。如果有人知道攻击媒介,我会忽略,我很乐意听到它。

更新:我确实看到这样做的一个警告是错误和攻击被无声地吞噬,你从来没有听说过它们。我在代码中添加了注释,建议记录错误。

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new GracefullyHandleHttpAntiForgeryExceptionAttribute());
    }
}

public class GracefullyHandleHttpAntiForgeryExceptionAttribute : HandleErrorAttribute
{
    public GracefullyHandleHttpAntiForgeryExceptionAttribute()
    {
        this.ExceptionType = typeof(HttpAntiForgeryException);
    }

    public override void OnException(ExceptionContext filterContext)
    {
        if (this.ExceptionType.IsAssignableFrom(filterContext.Exception.GetType()))
        {
            // Consider logging these errors, you don't want some
            // problem in your code silently failing and it's worth
            // tracking potential attacks.

            filterContext.ExceptionHandled = true;
            filterContext.Result = new RedirectResult(filterContext.HttpContext.Request.RawUrl);
        }
    }
}

以下是一些可能为您的用户提供更好体验的方案:

  1. Jane Doe在example.com上有一个帐户。 Hacker Joe通过电子邮件向Jane Doe发送了一个指向example.comev.il的链接,Jane跟随它并呈现了一个她填写的表单。 Joe的表单POST只发送到example.com上的资源,只有在Jane登录时才能访问该资源。由于Jane已登录,POST已获得授权,但[ValidateAntiForgeryToken]属性会介入并正确抛出异常。通常简会出现一个错误页面(希望不是YSOD介意你:-)并且很困惑。虽然不是一次糟糕的体验,但事情可能会更好。如果不是以这种方式发生错误,而是向当前URL发出GET请求,Jane会出现该页面(假设它可以处理GET),并继续她的生活。
  2. Jane Doe快速连续打开两个浏览器窗口到同一个站点。每个浏览器窗口都将获得自己的反XSRF令牌,但只有一个有效。如果她要使用无效令牌从窗口提交表单,她将收到错误页面。使用这个帮助器只需刷新表单,虽然她输入的数据将会消失,但她可以立即再次填写表单。通过一些额外的工作,您可以向刷新页面上显示的用户显示令人欣慰的消息。

答案 2 :(得分:1)

你是对的,这是出于安全考虑。 AntiForgeryToken有两个部分,客户端部分(cookie)和服务器部分。当HttpRequest到达服务器时,服务器将检查cookie并检索令牌值并与服务器部分进行比较。

在典型的XSRF场景中,例如

Mallory: Hello Alice! Look here:
   <img src="http://bank.example.com/withdraw?account=Alice&amount=1000000&for=Mallory">

当受害者点击图片时,她的请求将被视为无效请求,因为没有客户端令牌,并且抛出异常以保护受害者。