zoukankan      html  css  js  c++  java
  • python web框架Flask——csrf攻击

    CSRF是什么?

      (Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用也就是人们所知道的钓鱼网站。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

    CSRF可以做什么?

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

    它这么厉害,那它的原理是什么?

    CSRF原理简述

      用户访问一个网站就会将用户的相关信息保存cookies中(session可以认为加了密的cookies,然后保存到的cookies中),这时用户又访问了一个很危险的网站,这个网站就会利用你之前访问网站留下的cookies发送一些恶意请求

    CSRF预防的方式

      我总结了两种预防CSRF攻击的方式:后台直接处理CSRF攻击(个人说法)和前端ajax请求方式

      后台处理CSRF攻击

        很简单,只需要在表单中增加一个name属性值为csrf_token、value属性值为{{ csrf_token() }} 的隐藏的input表单标签。

    <form class="form-signin" method="post">
            <h2 class="form-signin-heading">请登录</h2>
    
            <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
    
            <label for="inputEmail" class="sr-only">邮箱:</label>
            <input type="email" id="inputEmail" class="form-control" name="email" placeholder="请输入邮箱地址" required autofocus>
            <label for="inputPassword" class="sr-only">密码:</label>
            <input type="password" id="inputPassword" class="form-control" name="password" placeholder="请输入密码" required>
            <div class="checkbox">
              <label>
                <input type="checkbox" name="remember" value="1"> 记住我
              </label>
            </div>
            <button class="btn btn-lg btn-primary btn-block" type="submit">立即登录</button>
    </form>

         后台的csrftoken需要绑定到app上,这样前端表单传入的参数不会受到CSRF攻击就可以像平常一样获取post参数即可(上篇python web框架Flask后台登录,就是使用这种方式处理CSRF攻击的)

    def create_app():
        """
        主入口文件创建app,供其他蓝图使用
        :return: 返回一个app
        """
        app = Flask(__name__)
        # 防止csrf注入攻击
        CSRFProtect(app)
        # 注册蓝图模块
        app.register_blueprint(cms_bp, url_prefix="/cms")
        app.register_blueprint(common_bp, url_prefix="/common")
        app.register_blueprint(front_bp)
    
        # 导入配置文件
        app.config.from_object(config)
        # 数据库db初始化app
        db.init_app(app)
        # 后台登录login_manager初始化app
        cms_login_manager.init_app(app)
        return app
    
    
    if __name__ == '__main__':
        app = create_app()
        app.run()

      前端ajax请求方式

        前端Ajax请求是实现页面刷新的一种非常好的方式,但是Ajax请求也会有CSRF攻击。防止CSRF攻击也很简单,只需要两步:

          1)在当前页面上添加一个name为csrf-token, content为{{csrf_token()}}的meta标签

    <meta name="csrf-token" content="{{ csrf_token() }}">

          2)重写Ajax请求,并返回一个含有csrftoken的请求头

    'use strict';
    var cpajax = {
        "get": function(args){
            args["method"] = "get";
            this.ajax(args);
        },
        "post": function(args){
            args["method"] = "post";
            this.ajax(args);
        },
        "ajax": function(args){
            this._ajaxSetup();
            $.ajax(args);
        },
        "_ajaxSetup": function(args){
            $.ajaxSetup({
                "beforeSend": function(xhr, settings){
                    if(!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain){
                        var csrftoken = $("meta[name=csrf-token]").attr("content");
                        xhr.setRequestHeader("X-CSRFToken", csrftoken);
                    }
                }
            });
        }
    };

         3)这样前端就不能使用$.post()请求了(这种请求不能阻止CSRF攻击的),而是使用我们重写的Ajax请求。

    $(function(){
        $("#submit").on("click", function(event){
            event.preventDefault();
    
            var oldpwdE = $("input[name=oldpwd]");
            var newpwdE = $("input[name=newpwd]");
            var newpwd2E = $("input[name=newpwd2]");
    
            var oldpwd = oldpwdE.val();
            var newpwd = newpwdE.val();
            var newpwd2 = newpwd2E.val();
    
            //1、要在模板中的meta标签中渲染一个csrf-token
            //2、在ajax请求的头部设置x-CSRFtoken
            console.log("aaaaaaa");
            cpajax.post({
                "url": "/cms/resetpwd",
                "data": {
                    "oldpwd": oldpwd,
                    "newpwd": newpwd,
                    "newpwd2": newpwd2
                },
                "success": function(data){
                    console.log(data)
                },
                "fail": function(error){
                    console.log(error)
                }
            })
        })
    });

      

  • 相关阅读:
    GPS精度因子(GDOP,PDOP,HDOP,VDOP,TDOP)
    VTD专题
    使用Python的Numpy 生成随机数列表
    Win10 下使用Ubuntu子系统
    Python依赖库查找
    使用技巧
    openstreetmap算路服务搭建
    笔记
    markdownpad
    缓和曲线09正弦一波型
  • 原文地址:https://www.cnblogs.com/aitiknowledge/p/11653641.html
Copyright © 2011-2022 走看看