【问题标题】:protecting against CSRF in asp.net web application when using ajax使用 ajax 时在 asp.net Web 应用程序中防止 CSRF
【发布时间】:2013-08-24 06:28:47
【问题描述】:

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

我使用了 VS 2012 中的 Microsoft 自动生成的代码,并将其添加到母版页,如 here 所述。它运行良好,但一个页面通过 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 方法来做到这一点?

感谢您的帮助。

【问题讨论】:

  • 如果我跟着你,你需要看看System.Web.UI.LosFormatter类,它可以用来从viewstate反序列化

标签: asp.net csrf


【解决方案1】:

这是我发现的。我最终使用了 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()

【讨论】:

    猜你喜欢
    • 2015-01-15
    • 2017-07-31
    • 2013-05-08
    • 2014-06-20
    • 2018-06-29
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多