[ASP.NET MVC]@Html.AntiForgeryToken() 防止CSRF攻击

MVC Html.AntiForgeryToken() 防止CSRF攻击javascript

MVC中的Html.AntiForgeryToken()是用来防止跨站请求伪造(CSRF:Cross-site request forgery)攻击的一个措施,它跟XSS(XSS又叫CSS:Cross-Site-Script),攻击不一样,XSS通常是利用站内信任的用户在网站内插入恶意的脚本代码进行攻击,而CSRF则是伪形成受信任用户对网站进行攻击。html

 

举个简单例子,譬如整个系统的公告在网站首页显示,而这个公告是从后台提交的,我用最简单的写法:java

网站后台(Home/Index页面)设置首页公告内容,提交到HomeController的Text Actionjquery

@using (Html.BeginForm("Text","Home",FormMethod.Post)) { @:网站公告:<input type="text" name="Notice" id="Notice" />  
    <input type="submit" value="Submit" /> } 

 

HomeController的Text Actionajax

 

[HttpPost] public ActionResult Text() { ViewBag.Notice = Request.Form["Notice"].ToString(); return View(); } 

 


填写完公告,提交,显示json

 

 

此时提供给了跨站攻击的漏洞,CSRF通常依赖几个条件浏览器

(1)攻击者了解受害者所在的站点安全

(2)攻击者的目标站点具备持久化受权cookie或者受害者具备当前会话cookie服务器

(3)目标站点没有对用户在网站行为的第二受权此时cookie

具体参见http://baike.baidu.com/view/1609487.htm

 

现假设我知道我要攻击的网站的地址,譬如是http://localhost:6060/Home/Text,且也知足2,3的状况。

因而我新建一个AntiForgeryText.html文件,内容以下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml" >  
<head>  
    <title></title>  
</head>  
<body>  
    <form name="badform" method="post" action="http://localhost:6060/Home/Text">  
        <input type="hidden" name="Notice" id="Notice" value="你的网站被我黑了。。" />  
        <input type="submit" value="黑掉这个网站" />  
    </form>  
</body>  
</html>

 

在这个html中加了一个隐藏的字段,Name和Id和网站要接收的参数名同样。

我点击了“黑掉这个网站”,呈现以下

 

这个就是利用了漏洞把首页的公告给改了,这就是一个简单的跨站攻击的例子。

 

MVC中经过在页面上使用 Html.AntiForgeryToken()配合在对应的Action上增长[ValidateAntiForgeryToken]特性来防止跨站攻击。

把上面的代码改为

@using (Html.BeginForm("Text","Home",FormMethod.Post)) { @Html.AntiForgeryToken() @:网站公告:<input type="text" name="Notice" id="Notice" />  
<input type="submit" value="Submit" /> } 

 

对应的Action

 

[HttpPost] [ValidateAntiForgeryToken] public ActionResult Text() { ViewBag.Notice = Request.Form["Notice"].ToString(); return View(); } 

 

这样子我在AntiForgeryText.html中点"黑掉这个网站",就会出现

这样就防止了跨站攻击。

 

页面上的Html.AntiForgeryToken()会给访问者一个默认名为__RequestVerificationToken的cookie
为了验证一个来自form post,还须要在目标action上增长[ValidateAntiForgeryToken]特性,它是一个验证过滤器,
它主要检查

(1)请求的是否包含一个约定的AntiForgery名的cookie

(2)请求是否有一个Request.Form["约定的AntiForgery名"],约定的AntiForgery名的cookie和Request.Form值是否匹配

 

其中主要涉及到System.Web.WebPages.dll中的静态类AntiForgery
Html.AntiForgeryToken()调用了AntiForgery静态类的GetHtml方法,它产生一个随机值而后分别存储到客户端cookie和页面的hidden field中,

(1)Request.Cookies[antiForgeryTokenName](默认也是Request.Cookies["__RequestVerificationToken"])

(2)页面上的hiddenfield

<input name="__RequestVerificationToken" type="hidden" value="9rUlMYvsH6eMcFN9tn/wRwAG07eROraVaeTn9hHMXKkMmDbR8jLw5DKdVnZBJ9siQHeGyl1w4rSB141LnxMp2ahV0qP1lElPeukqfcUFYoxrm/EfpSJjZavykmzn15VeGFMKkmgFj5a1UFhZFaW2aZgeN38x9lt0OFSoca7eMVU=" />

 

其中cookie的key的名字和页面hidden field的名字是同样的,默认都是"__RequestVerificationToken",若是有提供ApplicationPath的话,那就是由"__RequestVerificationToken"和通过处理后的ApplicationPath组成。

 

Controller端则经过在Action上增长[ValidateAntiForgeryToken]特性来验证,
ValidateAntiForgeryTokenAttribute继承了FilterAttribute和IAuthorizationFilter,经过传递匿名委托方法,

委托调用AntiForgery类的Validate方法来实现验证。

Validate方法中主要验证Request.Cookies[antiForgeryTokenName]和<input name=antiForgeryTokenName ...>两个的值是否相同,

若是页面没有<input name=antiForgeryTokenName ...>,或者两个值不相等,就会抛出异常。

 

 

(二)关于CSRF攻击及mvc中的解决方案 [ValidateAntiForgeryToken]

 

 

一.CSRF是什么?

  CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。

二.CSRF能够作什么?

  你这能够这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF可以作的事情包括:以你名义发送邮件,发消息,盗取你的帐号,甚至于购买商品,虚拟货币转帐......形成的问题包括:我的隐私泄露以及财产安全。

三.CSRF漏洞现状

  CSRF这种攻击方式在2000年已经被国外的安全人员提出,但在国内,直到06年才开始被关注,08年,国内外的多个大型社区和交互网站分别爆出CSRF漏洞,如:NYTimes.com(纽约时报)、Metafilter(一个大型的BLOG网站),YouTube和百度HI......而如今,互联网上的许多站点仍对此毫无防备,以致于安全业界称CSRF为“沉睡的巨人”。

四.CSRF的原理

 

 

 从上图能够看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:

  1.登陆受信任网站A,并在本地生成Cookie。

  2.在不登出A的状况下,访问危险网站B。

  看到这里,你也许会说:“若是我不知足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此,但你不能保证如下状况不会发生:

  1.你不能保证你登陆了一个网站后,再也不打开一个tab页面并访问另外的网站。

  2.你不能保证你关闭浏览器了后,你本地的Cookie马上过时,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登陆/结束会话了......)

  3.上图中所谓的攻击网站,多是一个存在其余漏洞的可信任的常常被人访问的网站。

 

以上内容转自:http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html

 

具体步骤:

一、在Html表单里面使用了@Html.AntiForgeryToken()就能够阻止CSRF攻击。

二、相应的咱们要在Controller中也要加入[ValidateAntiForgeryToken]过滤特性。该特性表示检测服务器请求是否被篡改。注意:该特性只能用于post请求,get请求无效。

三、至于JS,咱们的项目中引用的是<script src="@Url.Content("~/Content/js/jqueryToken-1.4.2.js")" type="text/javascript"></script>

在JS时要使用: $.ajaxAntiForgery才行,
如:

 $.ajaxAntiForgery({ type: "post", data: { GroupName: $("#GroupName").val(), GroupPhones: $("#GroupPhones").val() }, dataType: "json", url: "/Event/Mass/AddGroup", success: function (data) { if (data) { alert("添加成功 "); $.unblockUI(); } else { alert("添加失败 "); } } })

注:对数据进行增删改时要防止csrf攻击!

 

(三)BeginFormAntiForgeryPost

Orchard1.6中,Module.txt文件中的设置AntiForgery:enable及页面中BeginFormAntiForgeryPost的做用也是同样的,再也不赘述!

 

 

(四)参考网址

 

http://www.cnblogs.com/dragon_mail/archive/2011/07/10/2102364.html

http://blog.csdn.net/luck901229/article/details/8261640

相关文章
相关标签/搜索