我在Angular.js中實現了一個網站,該網站正在訪問ASP.NET WebAPI後端。Angular對Asp.Net WebApi,在服務器上實現CSRF
Angular.js有一些內置的功能來幫助防csrf保護。在每個http請求上,它將查找名爲「XSRF-TOKEN」的cookie並將其作爲名爲「X-XSRF-TOKEN」的頭提交。
這依賴於Web服務器能夠在認證用戶之後設置XSRF-TOKEN cookie,然後檢查傳入請求的X-XSRF-TOKEN標頭。
要利用這一點,你的服務器需要設置令牌叫XSRF-TOKEN的第一個HTTP GET請求一個JavaScript可讀會話cookie。在隨後的非GET請求中,服務器可以驗證該Cookie是否與X-XSRF-TOKEN HTTP標頭匹配,因此請確保只有在您的域中運行的JavaScript可以讀取令牌。令牌對於每個用戶必須是唯一的,並且必須由服務器驗證(以防止JavaScript構成自己的令牌)。我們建議該令牌是您的網站身份驗證Cookie的摘要,以增加安全性。
我找不到任何有關ASP.NET WebAPI的很好的例子,所以我在各種來源的幫助下推出了自己的例子。我的問題是 - 任何人都可以看到代碼有問題嗎?
首先我定義了一個簡單的輔助類:
public class CsrfTokenHelper
{
const string ConstantSalt = "<ARandomString>";
public string GenerateCsrfTokenFromAuthToken(string authToken)
{
return GenerateCookieFriendlyHash(authToken);
}
public bool DoesCsrfTokenMatchAuthToken(string csrfToken, string authToken)
{
return csrfToken == GenerateCookieFriendlyHash(authToken);
}
private static string GenerateCookieFriendlyHash(string authToken)
{
using (var sha = SHA256.Create())
{
var computedHash = sha.ComputeHash(Encoding.Unicode.GetBytes(authToken + ConstantSalt));
var cookieFriendlyHash = HttpServerUtility.UrlTokenEncode(computedHash);
return cookieFriendlyHash;
}
}
}
然後我在我的授權控制器下面的方法,我稱之爲我叫FormsAuthentication.SetAuthCookie(後):
// http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-(csrf)-attacks
// http://docs.angularjs.org/api/ng.$http
private void SetCsrfCookie()
{
var authCookie = HttpContext.Current.Response.Cookies.Get(".ASPXAUTH");
Debug.Assert(authCookie != null, "authCookie != null");
var csrfToken = new CsrfTokenHelper().GenerateCsrfTokenFromAuthToken(authCookie.Value);
var csrfCookie = new HttpCookie("XSRF-TOKEN", csrfToken) {HttpOnly = false};
HttpContext.Current.Response.Cookies.Add(csrfCookie);
}
然後我有一個自定義屬性,我可以將其添加到控制器以使其檢查csrf標頭:
public class CheckCsrfHeaderAttribute : AuthorizeAttribute
{
// http://stackoverflow.com/questions/11725988/problems-implementing-validatingantiforgerytoken-attribute-for-web-api-with-mvc
protected override bool IsAuthorized(HttpActionContext context)
{
// get auth token from cookie
var authCookie = HttpContext.Current.Request.Cookies[".ASPXAUTH"];
if (authCookie == null) return false;
var authToken = authCookie.Value;
// get csrf token from header
var csrfToken = context.Request.Headers.GetValues("X-XSRF-TOKEN").FirstOrDefault();
if (String.IsNullOrEmpty(csrfToken)) return false;
// Verify that csrf token was generated from auth token
// Since the csrf token should have gone out as a cookie, only our site should have been able to get it (via javascript) and return it in a header.
// This proves that our site made the request.
return new CsrfTokenHelper().DoesCsrfTokenMatchAuthToken(csrfToken, authToken);
}
}
最後,我清除CSRF令牌當用戶註銷:
HttpContext.Current.Response.Cookies.Remove("XSRF-TOKEN");
任何人都可以發現這種做法任何明顯的(或不那麼明顯)的問題?
我試圖想出一個解決方案,以及想知道如果比較這兩個餅乾是好的,當他們都可以被攻擊者改變?如果你的鹽被發現,那麼這是不是妥協? – BenCr 2013-10-25 11:03:16
BenCr,只有在我的域上運行的JavaScript才能讀取cookie並將其放入標題中。因此,如果存在導致瀏覽器向我的網站提交請求的惡意網站,請求將不會有頭,因此它會拒絕該請求。 – dbruning 2013-10-28 05:11:08
你能解釋一下你在這裏描述的解決方案的結果嗎?它如何失敗?或者你是否要求我們在安全方面找到漏洞? – user1852503 2013-11-12 01:02:58