zoukankan      html  css  js  c++  java
  • MVC Html.AntiForgeryToken() 防止CSRF攻击

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

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

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

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

    HomeController的Text Action

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

    填写完公告,提交,显示

    此时提供给了跨站攻击的漏洞,CSRF一般依赖几个条件

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

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

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

    具体参见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 ...>,或者两个值不相等,就会抛出异常。

  • 相关阅读:
    NTP on FreeBSD 12.1
    Set proxy server on FreeBSD 12.1
    win32 disk imager使用后u盘容量恢复
    How to install Google Chrome Browser on Kali Linux
    Set NTP Service and timezone on Kali Linux
    Set static IP address and DNS on FreeBSD
    github博客标题显示不了可能是标题包含 特殊符号比如 : (冒号)
    server certificate verification failed. CAfile: none CRLfile: none
    删除文件和目录(彻底的)
    如何在Curl中使用Socks5代理
  • 原文地址:https://www.cnblogs.com/_dragon/p/2102364.html
Copyright © 2011-2022 走看看