抗酒醉的功效和目的。在AJAX调用中验证
MVC4 SPA模板有一个抗酒醉的功效和目的。在AJAX调用中验证,ajax,vb.net,security,asp.net-mvc-4,antiforgerytoken,Ajax,Vb.net,Security,Asp.net Mvc 4,Antiforgerytoken,MVC4 SPA模板有一个ValidateHttpAntiForgeryTokenAttribute类,该类带有一个ValidateRequestHeader函数,该函数在为AJAX调用组装数据时解析出客户端构建的RequestVerificationToken头的两半。客户机AJAX代码从表单上的一个字段获取其值,该字段组合了表单令牌和cookie令牌。我觉得把这些结合成一个单一的价值,就看不到防暴标志的作用;他们分开是有原因的。通过这种方式使用防伪令牌,我们是否获得了安全性 Server.v
ValidateHttpAntiForgeryTokenAttribute
类,该类带有一个ValidateRequestHeader
函数,该函数在为AJAX调用组装数据时解析出客户端构建的RequestVerificationToken
头的两半。客户机AJAX代码从表单上的一个字段获取其值,该字段组合了表单令牌和cookie令牌。我觉得把这些结合成一个单一的价值,就看不到防暴标志的作用;他们分开是有原因的。通过这种方式使用防伪令牌,我们是否获得了安全性
Server.vbhtml代码(基于Razor):
服务器验证代码:
Private Sub ValidateRequestHeader(request As HttpRequestMessage)
Dim cookieToken As String = String.Empty
Dim formToken As String = String.Empty
Dim tokenHeaders As IEnumerable(Of String) = Nothing
If request.Headers.TryGetValues("RequestVerificationToken", tokenHeaders) Then
Dim tokenValue As String = tokenHeaders.FirstOrDefault()
If Not String.IsNullOrEmpty(tokenValue) Then
Dim tokens As String() = tokenValue.Split(":"c)
If tokens.Length = 2 Then
cookieToken = tokens(0).Trim()
formToken = tokens(1).Trim()
End If
End If
End If
AntiForgery.Validate(cookieToken, formToken)
End Sub
是什么阻止客户机挑选过去使用过的任意cookieToken和formToken对,并在AJAX调用中一起提交以使其通过?这难道不是防伪功能应该防止的吗?这只是一个愚蠢的开销,不能提高安全性,还是有一部分我遗漏了
是什么阻止客户机挑选过去使用过的任意cookieToken和formToken对,并在AJAX调用中一起提交以使其通过?这难道不是防伪功能应该防止的吗?这只是一个愚蠢的开销,不能提高安全性,还是有一部分我遗漏了
防伪令牌的设计不是为了防止伪造。这就是重用旧值来创建另一个请求的地方,其目的是欺骗目标机器接受过去的有效指令
防伪令牌旨在防止攻击
一个简单的例子如下:
- 您只需在一个选项卡上登录
bank.com
- 通过点击一个链接,你会收到一封电子邮件来观看一段有趣的视频,该链接会将你重定向到
evil.com
上的网页包含一个隐藏表单,由JavaScript提交到evil.com
bank.com/make\u money\u transfer
bank.com
并通过浏览器发送cookie时,bank.com
认为您提出了请求并在您不知情的情况下发起了汇款,因为从服务器的角度来看,一切都很好
令牌的设计目的是通过在请求有效负载中包含一些不能由非当前域的域自动提交的内容来防止这种情况。由于其他域无法访问令牌值,因此无法通过隐藏表单或任何其他方式发送合法请求。该令牌在每个登录会话中都是唯一的,因此攻击者无法获得可发送到服务器的令牌和cookie的有效组合
查看的源代码(虽然是C#而不是VB.NET),我们可以看到ValidateTokens
方法检查令牌中编码的用户名是否与当前HTTP请求中的用户名匹配:
if (!String.Equals(fieldToken.Username, currentUsername, (useCaseSensitiveUsernameComparison) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase))
{
throw HttpAntiForgeryException.CreateUsernameMismatchException(fieldToken.Username, currentUsername);
}
这将阻止攻击者获取旧版本的表单字段值并在其CSRF攻击中提交该值-他们的编码用户名将与其受害者的登录用户不匹配。但是模板代码中的cookie和令牌值都存储在表单上!这难道不会破坏cookie令牌的安全性吗?抱歉-稍微误解了您最初的问题!不管怎样,我已经用答案更新了它。用户名是阻止这一点的一个问题:模板代码对IIdentity参数传递“Nothing”,除非我读错了代码,导致currentUsername保持为空。我看到的唯一
Nothing
在Antifforgery中。对于oldCookieToken
参数,GetTokens
?用户名没有传递,它是从HttpContext
计算出来的。啊,对了。然后我脑海中剩下的一个问题是,为什么要分别维护cookie令牌(又名会话令牌?)和表单令牌(又名字段令牌?),而它们都在表单上。为什么不直接使用fieldToken/formToken?
function ajaxRequest(type, url, data, dataType) { // Ajax helper
var options = {
dataType: dataType || "json",
contentType: "application/json",
cache: false,
type: type,
data: data ? ko.toJSON(data) : null
};
var antiForgeryToken = $("#antiForgeryToken").val();
if (antiForgeryToken) {
options.headers = {
'RequestVerificationToken': antiForgeryToken
}
}
return $.ajax(url, options);
}
Private Sub ValidateRequestHeader(request As HttpRequestMessage)
Dim cookieToken As String = String.Empty
Dim formToken As String = String.Empty
Dim tokenHeaders As IEnumerable(Of String) = Nothing
If request.Headers.TryGetValues("RequestVerificationToken", tokenHeaders) Then
Dim tokenValue As String = tokenHeaders.FirstOrDefault()
If Not String.IsNullOrEmpty(tokenValue) Then
Dim tokens As String() = tokenValue.Split(":"c)
If tokens.Length = 2 Then
cookieToken = tokens(0).Trim()
formToken = tokens(1).Trim()
End If
End If
End If
AntiForgery.Validate(cookieToken, formToken)
End Sub
if (!String.Equals(fieldToken.Username, currentUsername, (useCaseSensitiveUsernameComparison) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase))
{
throw HttpAntiForgeryException.CreateUsernameMismatchException(fieldToken.Username, currentUsername);
}