0

我有一个我想更新以防止跨站点请求伪造攻击的 ASP Web 应用程序。

我使用了 VS 2012 中的 Microsoft 自动生成的代码,并将其添加到母版页中,如此处所述。它运行良好,但一个页面通过 AJAX 请求将 JSON 发布到 webmethod

我也想检查这个 ajax 请求。

可预见的问题是:

var responseCookie = new HttpCookie(AntiXsrfTokenKey)
   {
        //Set the HttpOnly property to prevent the cookie from
        //being accessed by client side script
                HttpOnly = true,

这显然可以改变,但这似乎会增加网站的脆弱性。这是一个重要的问题吗?

我可以使用 ajax 请求发送 viewstate 隐藏输入的值,但是这需要被解码回键值对以执行以下操作:

(string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue 

有没有一种简单的方法可以使用现有的 asp.net 方法来做到这一点?

感谢您的任何帮助。

4

1 回答 1

0

这是我发现的。我最终使用了 geedubb 所描述的 LosFormatter,方法是将以下代码添加到 MasterPage,并将值分配给一个隐藏的输入,该输入与 ajax 请求一起发回。当我发布 HttpCookie.HttpOnly 属性仍然在 ajax 请求上回发 cookie 的问题时,我没有意识到,因此可以将其设置为 false。

internal string GetToken()
{
    // call the static method to guarantee LosFormatter remains threadsafe
    return GetToken(_antiXsrfTokenValue); 
}
private static string GetCurrentUserName()
{
    var currentUser = HttpContext.Current.User.Identity;
    return (currentUser == null) ? string.Empty : currentUser.Name;
}
private static string GetToken(string token)
{
    var los = new System.Web.UI.LosFormatter(true, token);
    var writer = new System.IO.StringWriter();
    var data = new Dictionary<string,string>();
    data.Add("TokenValue",token);
    data.Add("UserNameKey", GetCurrentUserName());
    los.Serialize(writer, data);
    return writer.ToString();
}
internal static void Validate(string token)
{
    var request = HttpContext.Current.Request;
    var requestCookie = request.Cookies[AntiXsrfTokenKey];
    var antiXsrfTokenValue = requestCookie.Value;
    var los = new System.Web.UI.LosFormatter(true, antiXsrfTokenValue);
    var xsrfData = (Dictionary<string,string>)los.Deserialize(token);
    if (xsrfData["TokenValue"] != antiXsrfTokenValue || xsrfData["UserNameKey"] != GetCurrentUserName())
    {
        throw new System.Security.Authentication.AuthenticationException("Validation of Anti-XSRF token failed.");
    }
}

最初,我尝试使用相同的代码发送 _VIEWSTATE 隐藏输入的值

       var los = new System.Web.UI.LosFormatter(true, antiXsrfTokenValue);
       var ajaxViewState = los.Deserialize(token)

但这引发了一个错误,指出提供的密钥无法反序列化字符串。显然设置

       Page.ViewStateUserKey = _antiXsrfTokenValue;

具有比单独提供的密钥更复杂的密钥。如果有人知道如何使用 userKey 反序列化视图状态字符串,我会很感兴趣。

我提供的方法的唯一问题是回发的字符串的大小 - GUID + 6 个字符的用户名长度为 1976 个字符!!!!

如果再次处理这个问题,我会引用 System.Web.WebPages.dll(在 mvc 项目中使用),并使用在 MVC 中创建 Html.AntiForgeryToken 的相同方法

namespace System.Web.Helpers
{
    /// <summary>
    /// Provides access to the anti-forgery system, which provides protection against
    /// Cross-site Request Forgery (XSRF, also called CSRF) attacks.
    /// </summary>
    public static class AntiForgery
    {
        public static void GetTokens(string oldCookieToken, out string newCookieToken, out string formToken)
        public static void Validate()
于 2013-08-23T22:21:22.373 回答