_ _ VIEWSTATE 防止 CSRF

信息安全 csrf 视图状态
2021-08-15 14:28:03

我不是 .NET 开发人员,我想了解 __ViewState 究竟是如何防止 CSRF/XSRF 攻击的。

我遇到了以下情况:

关于类似主题的安全堆栈交换讨论OWASP CSRF 保护指南

我对这里的 CSRF 保护到底是如何发生的有点困惑。如果我们看一下从上面提到的 OWASP 链接中获取的以下代码:

    private const string AntiXsrfTokenKey = "__AntiXsrfToken";
    private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
    private string _antiXsrfTokenValue;
    protected void Page_Init(object sender, EventArgs e)
{
    // The code below helps to protect against XSRF attacks
    var requestCookie = Request.Cookies[AntiXsrfTokenKey];
    Guid requestCookieGuidValue;
    if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
    {
       // Use the Anti-XSRF token from the cookie
       _antiXsrfTokenValue = requestCookie.Value;
       Page.ViewStateUserKey = _antiXsrfTokenValue;
    }
    else
    {
       // Generate a new Anti-XSRF token and save to the cookie
       _antiXsrfTokenValue = Guid.NewGuid().ToString("N");
       Page.ViewStateUserKey = _antiXsrfTokenValue;
       var responseCookie = new HttpCookie(AntiXsrfTokenKey)
       {
          HttpOnly = true,
          Value = _antiXsrfTokenValue
       };
       if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
       {
          responseCookie.Secure = true;
       }
       Response.Cookies.Set(responseCookie);
    }
    Page.PreLoad += master_Page_PreLoad;
}

据我了解,上面的代码检查是否已经存在名为“__AntiXsrfToken”的cookie。

如果不是,则生成一个新的随机值,将其分配给 ViewStateUserKey 并设置为 cookie 的值“__AntiXsrfToken”。

如果 cookie 已经存在,则简单地获取 cookie 的值并将其分配给 ViewStateUserKey。

现在我不明白的是,关于 antiXSRF 令牌的全部意义在于它不应该被猜测,当然也不应该在 cookie 中传递,因为 cookie 总是会随浏览器的每个请求一起发送。在上述情况下,由于 AntiXsrf 令牌被用作 cookie,它如何防止它?ViewStateUserKey 的真正用途是什么?它如何在此处对 XSRF 的保护发挥作用?

2个回答

问题是 OWASP 指南中的代码示例不完整。具体来说,它缺少在master_Page_PreLoad方法的最后一行连接的Page_Init方法的实现。

如果包含该方法(我可能会在此处很快添加),您会看到,cookie 设置的 ViewStateUserKey 值正在与表单的 ViewState 字段提交的 ViewState[AntiXsrfTokenKey] 值进行比较。

这就是提供 CSRF 保护的原因。您是绝对正确的,当提交恶意请求时,它将与您的 cookie 一起提交,该 cookie 将具有您的防伪令牌,并将设置为 ViewStateUserKey 值。但是,您没有看到的是,这与提交的表单值进行了比较。在跨站点请求伪造场景中,该表单值将成为攻击者的防伪令牌;作为视图状态添加的那个是他的ViewStateUserKey,这与 cookie 中的值不匹配。所以,验证会失败,请求也不会成功。

除了当前 OWASP 页面上的代码之外,什么都没有,您感到困惑是对的。

但请记住,虽然 cookie 和会话可以从您网站上的所有页面访问,但 ViewState 值不会在页面之间传递,它们会在回发之间传递值:

如果您的网站对用户进行身份验证,您可以在 Page_Init 事件处理程序中设置 ViewStateUserKey 属性以将页面的视图状态与特定用户相关联。这有助于防止一键式攻击,其中恶意用户使用先前创建的页面的视图状态创建一个有效的、预填充的 Web 页面。然后,攻击者诱使受害者点击一个链接,该链接使用受害者的身份将页面发送到服务器。

当设置 ViewStateUserKey 属性时,攻击者的身份用于创建原始页面的视图状态的哈希。当受害者被引诱重新发送页面时,由于用户密钥不同,哈希值会有所不同。该页面将无法验证并引发异常。

您必须将 ViewStateUserKey 属性设置为每个用户的唯一值,例如用户名或标识符。

在您的代码中:

// 生成一个新的 Anti-XSRF 令牌并保存到 cookie

_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
   Page.ViewStateUserKey = _antiXsrfTokenValue;
   var responseCookie = new HttpCookie(AntiXsrfTokenKey)
   {
      HttpOnly = true,
      Value = _antiXsrfTokenValue
   };

每次页面加载时,它都会生成一个新的 Anti-XSRF 令牌。所以攻击者无法猜测该值。并且每次cookie值都在变化。所以破解是非常困难的。