即使没有匹配,AntiForgery.Validate也会始终验证

时间:2016-09-04 22:55:34

标签: asp.net asp.net-mvc-5 antiforgerytoken

我有一个类,用于执行Antiforgery令牌的验证,其中有效负载是Json。那个班级看起来像这样(来自Phil Haacked):

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (ReferenceEquals(filterContext, null)) throw new ArgumentNullException("filterContext");

        var request = filterContext.HttpContext.Request;

        //  Only validate POSTs
        if (request.HttpMethod == WebRequestMethods.Http.Post)
        {
            //  Ajax POSTs and normal form posts have to be treated differently when it comes
            //  to validating the AntiForgeryToken
            if (request.IsAjaxRequest())
            {
                var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

                var cookieValue = ReferenceEquals(antiForgeryCookie, null) ? null : antiForgeryCookie.Value;

                AntiForgery.Validate(cookieValue, request.Headers[AntiForgeryConfig.CookieName]);
            }
            else
            {
                new ValidateAntiForgeryTokenAttribute().OnAuthorization(filterContext);
            }
        }

    }
}

这是我使用它的第一个Angular项目,并没有抛出我期望的异常。例如,标题中的值与Cookie中的值不同,对AntiForgery.Validate的调用无一例外地进行。

防伪令牌在shell视图中呈现(即Index.cshtml),并将其添加到Angular的模块运行函数中的标题中:

// Handle routing errors and success events
theApp.run(['$http', '$route', '$rootScope', '$q', 'routeOverlord',
    function ($http, $route, $rootScope, $q, routeOverlord) {
        // Include $route to kick start the router.
        routeOverlord.setRoutingHandlers();

        // Include AntiForgeryToken to prevent CSRF attacks
        $http.defaults.headers.common['__RequestVerificationToken'] = angular.element('input[name="__RequestVerificationToken"]').val();
    }]);

这是一个众所周知的事吗?很高兴在请求时提供cookie和标题中不同字符串的Fiddler截图。

干杯

2 个答案:

答案 0 :(得分:1)

Cookie令牌和表单令牌(在您的案例中标题中的那个)是应该是相同的(它会更容易伪造)。

Cookie令牌包含随机blob。表单标记包含相同的blob,以及一些标识数据(以及可选的一些附加数据)。

AntiForgery.Validate()检查两个blob是否相同,并且表单标记中的其他数据对应于标识数据和可选的附加数据。

答案 1 :(得分:0)

我也见过这个。 cookie值和字段值不同,但.Net框架仍然允许它们通过。

这是因为.Net Framework的实现比简单的值匹配检查稍微复杂一点。

查看Github上的源代码后,看到令牌除了GUID之外还包含其他信息(它们将它绑定到当前用户)。

我可以在TokenValidator中看到,cookie值是表示SessionToken的标记,其中字段值(您的标题值)不应该是会话标记。

// Do the tokens have the correct format?
if (!sessionToken.IsSessionToken || fieldToken.IsSessionToken)
{
    throw HttpAntiForgeryException.CreateTokensSwappedException(_config.CookieName, _config.FormFieldName);
}

但是他们仍然用来验证行动是否来自授权用户,而不是来自恶意人员的一些预防性攻击。

我个人需要更多地研究微软的实现,但从我现在看到的一点点(以及下面的链接)来看,值肯定会有所不同。

我看过参考文献: