2013-12-11 56 views
0

MVC4 SPA模板的ValidateHttpAntiForgeryTokenAttribute類具有ValidateRequestHeader函數,該函數在爲AJAX調用組裝數據時分析客戶端構造的RequestVerificationToken頭的兩部分。客戶端AJAX代碼從組合表單令牌和Cookie令牌的表單中的字段獲取其值。我覺得將這些組合成一個單一的值會失去AntiForgery令牌的目的;他們分開是有原因的。我們是否通過這種方式使用防僞令牌來獲得任何安全保障?AntiForgery.Validate在AJAX調用中的功效和用途

服務器.vbhtml代碼(剃刀爲主):

Public Function GetAntiForgeryToken() As String 
    Dim cookieToken As String = String.Empty 
    Dim formToken As String = String.Empty 

    AntiForgery.GetTokens(Nothing, cookieToken, formToken) 
    Return cookieToken & ":" & formToken 
End Function 

...

@If User.Identity.IsAuthenticated Then 
    @<input id="antiForgeryToken" type="hidden" value="@GetAntiForgeryToken()" /> 
End If 

客戶端AJAX代碼:

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 

是什麼阻止客戶挑選過去使用過的任意一對cookieToken和formToken,並通過AJAX調用將它們一起提交以使其通過?這不是什麼防僞功能應該防止?這只是很多愚蠢的開銷,不會提高安全性,還是我缺少一部分內容?

回答

1

什麼阻止客戶端挑選過去使用過的任何cookieToken和formToken對,並在AJAX調用中將它們一起提交以使其通過?這不是什麼防僞功能應該防止?這只是很多愚蠢的開銷,不會提高安全性,還是我缺少一部分內容?

防僞標記的目的不是爲了防止Replay Attack。這是舊的價值被重新用來創造另一個要求,目的是欺騙目標機器接受過去的有效指令。

防僞標記旨在防止Cross Site Request Forgery攻擊。

一個簡單的例子如下:

  • 你登錄到bank.com一個標籤。
  • 您收到一封電子郵件,通過點擊您重定向到 evil.com
  • evil.com該網頁包含一個由JavaScript submited到bank.com/make_money_transfer

您一個隱藏的表單中的鏈接可查看搞笑視頻登錄到bank.com並且您的cookies由瀏覽器發送,bank.com認爲您提出請求並在您不知情的情況下啓動資金轉移,因爲從服務器的角度來看,一切都很好。

令牌旨在通過讓請求有效內容中包含的某些內容無法由不是當前域的域自動提交的東西來阻止此問題。由於Same Origin Policy另一個域無法訪問令牌值,因此無法通過隱藏窗體或通過任何其他方式發送合法請求。該令牌在每次登錄會話中都是唯一的,因此攻擊者無法獲得可以發送到服務器的令牌和cookie的有效組合。

看的源代碼TokenValidator.cs(儘管C#代替VB.NET)我們可以看出,ValidateTokens方法檢查在令牌中編碼的用戶名相匹配的當前的HTTP請求的一個:

if (!String.Equals(fieldToken.Username, currentUsername, (useCaseSensitiveUsernameComparison) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase)) 
{ 
    throw HttpAntiForgeryException.CreateUsernameMismatchException(fieldToken.Username, currentUsername); 
} 

這將阻止攻擊者抓取表單字段值的舊版本並在其CSRF攻擊中提交 - 它們的編碼用戶名將與其受害者的登錄用戶不匹配。

+0

但模板代碼*中的cookie和標記值都存儲在表單*上!這不會破壞cookie標記的安全嗎? – BlueMonkMN

+0

對不起 - 稍有誤解您的原始問題!無論如何,我已經用答案更新了它。 – SilverlightFox

+0

只有一個問題,即用戶名是什麼可以防止這種情況:模板代碼爲IIdentity參數傳遞「Nothing」,除非我讀錯代碼,否則會導致currentUsername保持爲空。 – BlueMonkMN