我读过如何在ASP.NET MVC Web应用程序中保护我的网站免受CSRF攻击。他们提到了两种方法:
使用<@Html.AntiForgeryToken()>
和[ValidateAntiforgeryToken]
使用HTTP引荐来源验证,例如:
public class IsPostedFromThisSiteAttribute : AuthorizeAttribute
{
public override void OnAuthorize(AuthorizationContext filterContext)
{
if (filterContext.HttpContext != null)
{
if (filterContext.HttpContext.Request.UrlReferrer == null)
throw new System.Web.HttpException("Invalid submission");
if (filterContext.HttpContext.Request.UrlReferrer.Host !=
"mysite.com")
throw new System.Web.HttpException
("This form wasn't submitted from this site!");
}
}
}
和
[IsPostedFromThisSite]
public ActionResult Register(…)
所以我很困惑我是否应该使用它们来保护我的网站免受CSRF攻击,或者我是否可以选择其中一种方法?
答案 0 :(得分:10)
检查引荐来源是有问题的。首先,HTTP规范明确允许客户端不发送引用字符串(出于各种隐私原因)。因此,您的一些客户可能不会包含它。其次,引用者字符串可以被欺骗,具有足够技能的攻击者可以使它们看起来像是为了成功进行CSRF攻击。
使用CSRF验证令牌是一种更强大的方法,是抵御CSRF攻击的首选方法。您可以在OWASP CSRF Cheat Sheet上了解原因。
我还要指出,你没有理由不能同时做到这两点。通常需要防御深度(DiD)策略,以便攻击者需要击败多个独立的防御来执行成功的攻击。您可以实现弱引用者检查方法(如果客户提供引用者,请确保它在执行请求之前应该是什么;如果引用者不存在,则继续进行,就像它存在并且正确一样)以及CSRF验证令牌。这样,如果客户端提供它,同时仍然使用更强的验证令牌方法,则检查引用的信息。
答案 1 :(得分:2)
HTTP Referer
(原文如此)标头is not reliable。你不应该依赖它来做任何重要的事情。引用Wikipedia's CSRF article:
“检查HTTP
Referer
标头以查看请求是否来自授权页面通常用于嵌入式网络设备,因为它不会增加内存要求。但是请求省略Referer
标头必须被视为未经授权,因为攻击者可以通过发出来自FTP或HTTPS URL的请求来抑制Referer
标头。这种严格的Referer
验证可能会导致浏览器或代理忽略Referer
的问题标题出于隐私原因。此外,旧版本的Flash(9.0.18之前)允许恶意Flash使用CRLF Injection生成带有任意HTTP请求标头的GET或POST请求。客户端中的类似CRLF注入漏洞可用于欺骗引用者一个HTTP请求。“
引荐来源检查也无法帮助抵御persistent CSRF攻击,攻击者可以将恶意链接直接注入您的网站。防止此类攻击的唯一可靠方法是使用防伪标记。
答案 2 :(得分:2)
虽然我从未使用它,但我个人不会在HTTP_REFERER上做任何事情。我认为现在这种情况并不常见,但我记得互联网安全套件(例如Norton Internet Security)会阻止发送的HTTP_REFERER。这只是意味着可以阻止真正的用户合法使用您的网站。
修改:请参阅this question。
我不指望它是可靠的。
答案 3 :(得分:2)
正如其他答案所示,单独使用引荐来源检查是不够的,你真的应该使用防伪令牌。
但是,正如@jeffsix指出的那样,您可以使用引荐来源检查作为深度防御(DID)策略,因此攻击者需要击败多个独立的防御来执行成功的攻击。</ p >
下面的ValidateReferrerAttribute属性可用于您的HttpPost MVC操作。如果引用者为空,则不执行任何操作。如果引用者不为null,则它检查它是否等于指定的主机名。你只需要在任何使用ValidateAntiForgeryTokenAttribute的地方添加它,这样就可以很容易地添加。
/// <summary>
/// For POST requests, checks that the requests referrer is the current site. This could be used along side the ValidateAntiForgeryToken
/// Note that many clients do not send the referrer, so we do nothing in this case.
/// This attribute can be used as part of a Defence-in-Depth (DID) strategy, so an
/// attacker would need to defeat multiple, independent, defenses to execute a successful attack.
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class ValidateReferrerAttribute : FilterAttribute, IAuthorizationFilter
{
/// <summary>
/// Called when authorization is required.
/// </summary>
/// <param name="filterContext">The filter context.</param>
/// <exception cref="System.ArgumentNullException">filterContext</exception>
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if ((filterContext.HttpContext.Request.UrlReferrer != null) &&
string.Equals(filterContext.HttpContext.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(filterContext.HttpContext.Request.UrlReferrer.Host, filterContext.HttpContext.Request.Url.Host, StringComparison.OrdinalIgnoreCase))
{
this.HandleExternalPostRequest(filterContext);
}
}
/// <summary>
/// Handles post requests that are made from an external source.
/// By default a 403 Forbidden response is returned.
/// </summary>
/// <param name="filterContext">The filter context.</param>
/// <exception cref="System.Web.HttpException">Request not allowed.</exception>
protected virtual void HandleExternalPostRequest(AuthorizationContext filterContext)
{
throw new HttpException((int)HttpStatusCode.Forbidden, "Request not allowed.");
}
}