深入理解CSRF攻击

96 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情

在web安全导致,表单提交数据的安全尤为重要,之前通过表单校验,已经过滤了一部分非法提交的数据,但是在提交数据的过程当中还是有一个风险的,就是跨域请求伪造登录,我们举个例子:

1)假设用户打开了一个银行网站,并且登录了 2)登录成功后,会返回一个cookie给前端,浏览器将cookie保存下来 3)用户在没有登出银行网站的情况下,在当前浏览器又新打开多了一个选项卡,访问了一个危险的网站 4)这个网站有个危险的超链接,这个超链接指向了银行网站 5)用户点击这个超链接,由于这个超链接会自动携带上cookie,所以用户不知不觉在点击这个超链接的时候,还要一些请求是发到了银行网站那里去。

image-20221201181621379.png

Flask CSRF防御

防御原理

flask 本身没有对csrf的预防策略,但是flask-wtf模块插件是有的,这个原理就是:

1)在渲染的表单上添加一个隐藏的表单域,设置一个加密值 csrf_token,这个值只在当前页面下发。

2)然后表单提交的时候顺带提交,服务端如果校验不是这个值,证明提交的来源不是当前页面,就拒绝请求。

这样就可以防止请求不是从页面上来,(当然,如果在渲染页面完成之后,获取到token值,然后携带也可以跳过页面进行请求,但是如果对方不是人为调整,而是js端恶意跳转的话,已经主够防御了。)

配置步骤

安装flask-jwt

pip install Flask-WTF

csrf导入和配置

from flask import Flask,render_template
from flask_wtf import CSRFProtect
​
app = Flask(__name__)
app.secret_key = "abcdefghijklmnopqrstuvwsyz" #设置token加密的盐值
csrf = CSRFProtect() #创建csrf实例
csrf.init_app(app) #csrf实例绑定到app上
​
@app.route("/index")
def index():
    return render_template("index.html")
​
if __name__ == "__main__":
    app.run(debug=True)

前端使用csrf

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>csrf案例</title>
</head>
<body>
    <form action="" method="post">
         <input type="hidden" name="csrf_token" value="{{csrf_token()}}">
        账号:<input type="text" name="username"><br><br>
        密码:<input type="password" name="password"><br><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

关闭CSRF保护

其实有的请求是不需要csrf保护的,所以可以进行csrf关闭:

全局关闭

app.config中设置WTF_CSRF_ENABLED = False

单个表单不使用csrf保护

单个表单禁用:生成表单时加入参数form = Form(csrf_enabled=False)

单个视图添加csrf保护

在不需要保护的路由上当加上: @csrf.exempt