Flask实现CSRF保护

  参考官方文档

 CSRF跨站请求伪造,源于WEB的隐式身份验证机制,WEB的身份验证机制虽然可以抱着一个请求时来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。

 例如,用户登录受信任的网址A,在本地生成了Cookie,在Cookie没有失效的情况下去访问了危险网站B,B可能会盗用你的身份,以你的名义去发送恶意请求,邮件,盗取你的账号,设置购买商品,造成你个人隐私泄露,已经财产安全。

 

 实现

为了能够让所有的视图受到CSRF保护,需要扩展 CsrfProtect模块

from flask_wtf.csrf import CsrfProtect

CsrfProtect(app)

 注意,需要为CSRF保护设置一个密钥,但通常情况下,和Flask应用的SECRET_KEY是一样的。

如果你设置的模板中存在表单,你只需要在表单中添加如下

<form method="post" action="/">
    {{ form.csrf_token }}
</form>

如果没有模板中没有表单,你仍然需要一个 CSRF 令牌:

<form method="post" action="/">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
</form>

如果网站没有通过CSRF验证,都会返回400响应,我们可以自定义这个错误响应:

from flask_wtf.csrf import CsrfProtect

csrf = CsrfProtect()


@csrf.error_handler
def csrf_error(reason):
    return render_template('csrf_error.html', reason=reason), 400

这里官方强烈建议对所有视图启用CSRF保护,也提供了给某些视图函数不需要保护的装饰器:

@csrf.exempt
@app.route('/foo', methods=('GET', 'POST'))
def my_handler():

(这里csrf是CsrfProtect()的一个拓展对象)

你也可以在所有的视图中禁用CSRF保护,app.config中通过设置 WTF_CSRF_CHECK_DEFAULT 为 False,仅仅当你需要的时候选择调用csrf.protect(). 这样能够让你在检查CSRF令牌前做一些预处理:

@app.before_request
def check_csrf():
    if not is_oauth(request):
        csrf.protect()

AJAX

不用表单,通过ajax发送post请求成为可能,flask 0.9后的版本可用。如果你使用了  CsrfProtect(app),你可以通过 {{ csrf_token() }} 获取 CSRF 令牌。这个方法在每个模板中都可以使用,你并不需要担心在没有表单时如何渲染 CSRF 令牌字段。

官方推荐在<meta>标签中渲染CSRF令牌:

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

在<script>标签中渲染同样可以:

<script type="text/javascript">
    var csrftoken = "{{ csrf_token() }}"
</script>

无论什么时候发送Ajax POST请求,都要添加X-CSRFToken请求头

 

实现案例

view.py中代码案例

from flask_wtf.csrf import CSRFProtect
CSRFProtect(app)


@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        # 获取传过来的数据, 这里不是用表单的方式提交,所以用的 request.values.get("key") ,
        # 如果是表单的方式提交数据的话,需要用request.form["key"] 或者 request.form.get("key")
        name = request.values.get("name")
        pwd = request.values.get("pwd")
        # models查询操作,到数据库中查找满足条件的数据,first()返回查询结果的第一条数据,实际是一个aa对象
        flag = aa.query.filter(aa.username == name, aa.password == pwd).first()
        print(flag)
        if flag != None:
            return make_response("{}")
        return make_response("")
    return render_template("login.html")

这里点击登录后,会到aa中去查找是否存在,然后返回不同的response,

login.html中的Ajax代码以及对应的表格,这里我没有使用表单

                var csrftoken = $("meta[name=csrf-token]").attr("content");
                if(flag){
                    //判断账号密码是否匹配
                    $.ajax({
                        url:"/login",
                        type:"POST",
                        dataType:"json",
                        data:{"name":username, "pwd":pwd,},
                        headers:{"X-CSRFToken":csrftoken},
                        success:function (data) {
                            if (data!=null && data!=""){
                                location.href="/index";
                            }else {
                                texta.innerText="账号或密码错误"
                            }
                        },
                        error:function (data) {
                            alert("+++"+data.msg);
                        }
                    });
                }
<table width="500px" border="1" cellspacing="0" cellpadding="0" align="center">
            <meta name="csrf-token" content="{{ csrf_token() }}">
            <tr height="50px">
                <th colspan="2" style="font-size: 30px;" >登录图书管理系统</th>
            </tr>
            <tr>
                <td style="background-color: cornflowerblue;">用户名:</td>
                <td>
                    <input id="username" type="text" name="username" value="">
                </td>
            </tr>
            <tr>
                <td style="background-color: cornflowerblue;">密码:</td>
                <td>
                    <input id="pwd" type="password" name="pwd" value="">
                </td>
            </tr>
            <tr>
                <td colspan="2" align="center">
                    <input type="button" value="登录" onclick="login()"/>
                </td>
            </tr>
            <tr>
                <td colspan="2">
                    <a id="a" style="color: red"></a>
                </td>
            </tr>
        </table>

使用ajax,则必须在其中添加  headers:{"X-CSRFToken":csrftoken},否则就会下图所示错误

会提示CSRF令牌缺失,

这里就是我关于flask中添加CSRF保护后,关于Ajax POST提交问题所遇到的问题,解决方法就是添加X-CSRFToken请求头

 

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
DVWA和Burp Proxy (BP) 都可以用来实现CSRF攻击。DVWA是一个用于学习和测试网络安全漏洞的虚拟环境,其中包含了多种不同的漏洞,包括CSRF。在DVWA的1.medium和2.high级别中,分别使用了不同的防护措施,包括http_referer和token值。在CSRF攻击中,攻击者利用受害者的浏览器本地的cookie信息,发送恶意请求(修改参数)来实现攻击,比如修改密码或账号信息。而Burp Proxy (BP)是一款常用的网络安全测试工具,可以用于拦截和修改网络请求,包括用于测试CSRF漏洞的攻击请求。通过BP,攻击者可以捕获受害者的正常请求,然后构造一个恶意的CSRF Poc(Proof of Concept,即证明漏洞存在的代码),并发送给受害者,从而实现CSRF攻击。因此,DVWA和BP都可以被用来实现CSRF攻击。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [DVWA-CSRF](https://blog.csdn.net/ahannn/article/details/122927445)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [DVWA-—【CSRF】漏洞利用](https://blog.csdn.net/qq_34914659/article/details/117020651)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值