1.什么是CSRF攻击?
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。简单来说,攻击者盗用了你的身份,以你的名义发送恶意请求。
比如你登陆了网银(假定是A网站)查看账户余额,这时候你的账户登录信息就以cookie的形式保存在访问的本地磁盘上。这时候你看到了一个醒目的链接,手欠点了进去,这时候CSRF就来了。
假如你访问的这个网站是恶意网站(假定是B网站),B站向A站发出请求转账到某账户的请求,然后就没有然后了。。。
总结一下CSRF攻击的条件:
1.你在没登出访问网站的情况下去访问危险网站。
2.攻击者了解你访问的网站(比如上面说的网银),这样才能发出准确的请求。
3.攻击者的目标站点具有持久化授权cookie或者受害者具有当前会话cookie。
4.目标站点没有对用户在网站行为的第二授权此时。
这时候,你可能会说:“如果我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:
1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。
2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了......)
3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。
既然有CSRF攻击,那必须得有办法防止它。MVC中的Token就是针对解决CSRF攻击的。
具体步骤:
1.在Html表单里面使用@Html.AntiForgeryToken()。页面上的Html.AntiForgeryToken()会给访问者一个默认名为__RequestVerificationToken的cookie。
1 <input name="__RequestVerificationToken" type="hidden" value="9rUlMYvsH6eMcFN9tn/wRwAG07eROraVaeTn9hHMXKkMmDbR8jLw5DKdVnZBJ9siQHeGyl1w4rSB141LnxMp2ahV0qP1lElPeukqfcUFYoxrm/EfpSJjZavykmzn15VeGFMKkmgFj5a1UFhZFaW2aZgeN38x9lt0OFSoca7eMVU=" />
Html.AntiForgeryToken()调用了AntiForgery静态类的GetHtml方法,它产生一个随机值然后分别存储到客户端cookie和页面的hidden field中,其中cookie的key的名字和页面hidden field的名字是一样的,默认都是"__RequestVerificationToken",如果有提供
ApplicationPath的话,那就是由"__RequestVerificationToken"和经过处理后的ApplicationPath组成。
2.为了验证一个来自form post,还需要在目标action上增加[ValidateAntiForgeryToken]特性,它是一个验证过滤器,它主要检查:
(1)请求的是否包含一个约定的AntiForgery名的cookie;
(2)请求是否有一个Request.Form["约定的AntiForgery名"],约定的AntiForgery名的cookie和Request.Form值是否匹配;
1 [HttpPost] 2 [ValidateAntiForgeryToken] 3 public ActionResult Index() 4 { 5 return View(); 6 }
ValidateAntiForgeryTokenAttribute继承了FilterAttribute和IAuthorizationFilter,通过传递匿名委托方法,
委托调用AntiForgery类的Validate方法来实现验证。
Validate方法中主要验证Request.Cookies[antiForgeryTokenName]和<input name=antiForgeryTokenName ...>两个的值是否相同,
如果页面没有<input name=antiForgeryTokenName ...>,或者两个值不相等,就会抛出异常。
加了Token之后,如果不小心进入危险网站,并提交了请求,服务器端action上的[ValidateAntiForgeryToken]特性就会去验证,如果提交请求中没有token或者token不匹配则拒绝访问。
当然,并不是说加了token就安全了,安全永远都是相对的。虽然恶意网站不能被token挡了一层,但如果有办法获取到cookie呢?不就拿到token了?这就有事xss攻击了,详细看下一篇。