zoukankan      html  css  js  c++  java
  • ASP.NET MVC 防止CSRF攻击

    简介

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

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

    实例

      我们新建一个简单的网站发布公告界面

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
    </head>
    <body>
        @using (Html.BeginForm("Notice", "Home", FormMethod.Post))
        {
            @:网站公告:<input type="text" name="Notice" id="Notice" />
            <input type="submit" value="Submit" />
        }
    </body>
    </html>

    1

    提交后

    2

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

    (1)攻击者知道该目标站点。

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

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

    比如我们现在知道发布新闻的地址:http://localhost:56874/Home/Notice

    比如我们新建一个页面

    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
    </head>
    <body>
        <form action="http://localhost:56874/Home/Notice" method="post">
            网站公告:<input type="text" name="Notice" id="Notice" />
            <input type="submit" value="Submit" />
        </form>
    </body>
    </html>

    发起攻击

    3

    这样在网站的公告就被篡改了。作为安全性考虑,这种情况肯定不会让它发生的。

    如何防止

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

    修改上面提交代码

    @using (Html.BeginForm("Notice", "Home", FormMethod.Post))
        {
            @Html.AntiForgeryToken();
            @:网站公告:<input type="text" name="Notice" id="Notice" />
            <input type="submit" value="Submit" />
        }
    [HttpPost]
            [ValidateAntiForgeryToken]
            public ActionResult Notice(string Notice)
            {
                ViewBag.Notice = Notice;
                return View();
            }

    再次运行网站,界面没什么变化当我们查看源代码的时候发现多了一个东西

    <input name="__RequestVerificationToken" type="hidden" value="oo1kDYx6CUL3YSyZHokvWgPzOcZhZID_75tiqYBgNMBBjQNo4FgmWpO5dRsVlvqIVgZH34FvTArCFbWKuDkCbwl5UFOAxzxmaTwuQ9iBBHY1" />

    现在当我们再次篡改数据的时候

    我们看一下Html.AntiForgeryToken()会为当前请求,生成一个名为__RequestVerificationToken的cookie,还有一个名为__RequestVerificationToken的隐藏域。

    为了验证一个来自form post请求,还需要在目标action上增加[ValidateAntiForgeryToken]特性,它是一个验证过滤器,它主要检查

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

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

    Ajax如何CSRF攻击

    在Asp.net Mvc里加入防伪标记很简单在表单中加入Html.AntiForgeryToken()即可。

    Html.AntiForgeryToken()会生成一对加密的字符串,分别存放在Cookies 和 input 中。

    我们在ajax post中也带上AntiForgeryToken

    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <script src="~/Script/jquery-1.10.2.min.js"></script>
    </head>
    <body>
        <form>
            网站公告:<input type="text" name="Notice" id="Notice" />
            <input type="button" value="提交" id="btn" />
        </form>
    </body>
    </html>
    <script>
        $(function () {
            $("#btn").click(function () {
                var token = $('@Html.AntiForgeryToken()').val();
                var headers = {};
                headers["__RequestVerificationToken"] = token;
                $.ajax({
                    type: 'POST',
                    url: '/Home/Notice',
                    cache: false,
                    headers: headers,
                    data: { Notice: $("#Notice").val()},
                    success: function (data) {
                        alert(data)
                    },
                    error: function () {
                        alert("Error")
                    }
                });
    
            })
        })
    </script>

    自定义ValidateAntiForgeryToken

    public class MyValidateAntiForgeryToken: AuthorizeAttribute
        {
            public override void OnAuthorization(AuthorizationContext filterContext)
            {
                var request = filterContext.HttpContext.Request;
                if (request.HttpMethod== WebRequestMethods.Http.Post)
                {
                    if (request.IsAjaxRequest())
                    {
                        var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
                        var cookiValue = antiForgeryCookie != null ? antiForgeryCookie.Value : null;
                        var s = request.Headers["__RequestVerificationToken"];
                        AntiForgery.Validate(cookiValue, request.Headers["__RequestVerificationToken"]);
                    }
                    else
                    {
                        new ValidateAntiForgeryTokenAttribute() .OnAuthorization(filterContext);
    
                    }
                }
            }
        }

    修改HomeController Notice方法

    [HttpPost]
            //    [ValidateAntiForgeryToken]
            [MyValidateAntiForgeryToken]
            public ActionResult Notice(string Notice)
            {
                ViewBag.Notice = Notice;
                
                return Json(new { message = Notice });
            }
    这样就防止了ajax post数据到服务器不加防伪标记,造成CSRF攻击
  • 相关阅读:
    laravel前后端分离分页查询
    swagger-open api 手动编写规范
    linux开启端口命令
    docker容器的基本使用
    centos更换阿里云的yum源
    VS中生成pdf
    代码整洁之道阅读笔记-02
    周总结
    Mongo的基本操作
    Redis的基本操作
  • 原文地址:https://www.cnblogs.com/studydp/p/9675425.html
Copyright © 2011-2022 走看看