美文网首页.net core
ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)

ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)

作者: _sands | 来源:发表于2019-03-21 15:08 被阅读0次

    CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装成受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

    from baidu

    这幅图已经能够很好地解释了跨站攻击是怎么回事,这样的网站很容易被别人钓鱼,

    示例:

    创建2个网站
    officialsite站点里有个 pay页面

    view:
          <h1>支付</h1>
          <form action="/pay/post" method="post">
              <input name="user" placeholder="姓名" />
              <input name="price" placeholder="金额" />
              <button type="submit">提交</button>
          </form>
    
    paycontroller:
            [HttpPost]
            public IActionResult Post(string user, decimal price)
            {
                return Json(new { ok = true, msg = $"{user}支付成功{price}元" });
            }
    

    FakeSite 站点里有个fakepay页面

    view:
        <h1>假的支付</h1>
        <form action="https://localhost:44316/pay/post" method="post">
            <input name="user" placeholder="姓名" />
            <input name="price" placeholder="金额" />
            <button type="submit">提交</button>
         </form>
    
    

    提交的请求并非自己站点 而是上一个站点的接口

    • 运行效果
    界面 运行效果
    image.png image.png
    image.png image.png 点击提交后一样返回了上面网站的请求结果,这样官网就太危险了。

    那么asp.net core mvc里怎么处理?

    CSRF能够成功是因为在同一个浏览器中Cookies是共享的,也就无法通过cookies权限认证和验证来防止。
    解决的办法就是:要确保请求是自己的站点发出的就可以了,其他的站点发来的请求阻挡掉。
    通过AntiForgeryToken 在页面生成一个Token,发请求的时候把Token带上。处理服务端处理请求的时候需要验证这个Token。而其他站点没有这个token那么也就没法通过验证,就被阻挡了。

    • 继续改造上面的demo:
    <form action="/pay/post" method="post">
        @Html.AntiForgeryToken()
        <input name="user" placeholder="姓名" />
        <input name="price" placeholder="金额" />
        <button type="submit">提交</button>
    </form>
    
    F12看生成的html
    
    <h1>支付</h1>
    <form action="/pay/post" method="post">
        <input name="__RequestVerificationToken" type="hidden" value="CfDJ8Efjwr3EXZVEmlMrBkJrUWtWFC05YY78yz-ce3W4IjEE5m7SzISCXShbON9col2WEDQiqSuKJMbjnUV94a7nwO3O9YXHaFGJMl04AdDpviAGK8DidGgu9d7Gpbm8Zncd01AWL4v274emVQgJTabzPfo" />
        <input name="user" placeholder="姓名" />
        <input name="price" placeholder="金额" />
        <button type="submit">提交</button>
    </form>
    
    controller
     [ValidateAntiForgeryToken]
            [HttpPost]
            public IActionResult Post(string user, decimal price)
            {
                return Json(new { ok = true, msg = $"{user}支付成功{price}元" });
            }
    

    运行后界面一切正常

    接下来我们在取运行上一个伪造的站点,什么都不改,提交后就会提示返回400的错误


    image.png

    这样就能搞定了。
    以上是表单提交,项目中常用的还是ajax请求,那该如何处理呢

    view:
    @inject Microsoft.AspNetCore.Antiforgery.IAntiforgery csrf
    <form action="/pay/post" method="post">
        @Html.AntiForgeryToken()
        <input name="user" placeholder="姓名" />
        <input name="price" placeholder="金额" />
        <button type="submit">提交</button>
        <button type="button" id="btnajax">ajax提交</button>
    </form>
    
     <script type="text/javascript">
            $(function () {
                $("#btnajax").click(function () {
                    $.ajax({
                        url: "/pay/post",
                        dataType: "text",
                        data: {
                            user: $("input[name=user]").val(),
                            price: $("input[name=price]").val()
                        },
                        headers: {
                            "RequestVerificationToken": '@csrf.GetAndStoreTokens(Context).RequestToken'
                        },
                        type: "post",
                        success: function (res) {
                            alert(res);
                        }
                    });
                })
            })
        </script>
    

    将ajax请求头里加上token,这样服务端就会校验。
    运行结果

    image.png

    配置

    这个令牌验证还是需要借助cookie的
    配置 在setup里,可以根据需要去添加,比如需要验证的域名

      services.AddAntiforgery(options =>
                {
                    options.Cookie = new CookieBuilder { Domain = "company.com" };
                });
    

    demo代码见 github

    相关文章

      网友评论

        本文标题:ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)

        本文链接:https://www.haomeiwen.com/subject/ycepnftx.html