flask学习笔记代码篇-13

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CSDNgaoqingrui/article/details/82557757

flask13-模拟CSRF攻击


CSRF

CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造。
CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求。
包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......
造成的问题:个人隐私泄露以及财产安全。
CSRF攻击示意图

客户端访问服务器时没有同服务器做安全验证

防止 CSRF 攻击

步骤

在客户端向后端请求界面数据的时候,后端会往响应中的 cookie 中设置 csrf_token 的值
在 Form 表单中添加一个隐藏的的字段,值也是 csrf_token
在用户点击提交的时候,会带上这两个值向后台发起请求
后端接受到请求,以会以下几件事件:
从 cookie中取出 csrf_token
从 表单数据中取出来隐藏的 csrf_token 的值
进行对比
如果比较之后两值一样,那么代表是正常的请求,如果没取到或者比较不一样,代表不是正常的请求,不执行下一步操作
以下使用代码模拟实现webB攻击webA
目录结构:

webA

from flask import Flask, render_template, request, make_response, redirect, url_for, flash
import base64
import os

app = Flask(__name__)
app.secret_key = 'sdfg'


def generate_token():
    return base64.b64encode(os.urandom(48)).decode()


# 根节点-登录页
@app.route('/', methods=["GET", "POST"])
def index():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        if not all([username, password]):
            flash("请输入用户名和密码")
            return render_template("html/03-login.html")
        # 判断用户名和密码是否正确
        if username != "laowang" or password != "123456":
            flash("用户名和密码错误")
            return render_template("html/03-login.html")
        resp = make_response(redirect(url_for('transfer')))
        resp.set_cookie('username', username)
        return resp
    return render_template('html/03-login.html')


# /transfer 转账页面
@app.route('/transfer', methods=["GET", "POST"])
def transfer():
    # if判断:如果没有登录,重定向到登录页
    username = request.cookies.get('username')
    if not username:
        return redirect(url_for('index'))
    if request.method == 'POST':
        # 去做转账的逻辑
        # 取出参数
        to_account = request.form.get('to_account')
        money = request.form.get('money')
        # 从表单中取出来隐藏随机值
        form_token = request.form.get('token')
        # 再从 cookie 中取出随机值
        cookie_token = request.cookies.get('cookie_token')
        if not all([to_account, money]):
            flash("请完整输入参数")
            return render_template('html/03-transfer.html')
        if form_token != cookie_token:
            return '非法请求'
        # 执行转账操作
        print("假装执行转账操作,转给 %s, 转 %s" % (to_account, money))
        return "假装执行转账操作,转给 %s, 转 %s" % (to_account, money)
    # 生成随机值
    token = generate_token()
    # 将渲染模板的操作封装成响应
    resp = make_response(render_template('html/03-transfer.html', token=token))
    # 再存一份到 webB 不能取到的地方
    resp.set_cookie('cookie_token', token)
    return resp


if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

webB

from flask import Flask,render_template

app = Flask(__name__)


@app.route('/', methods=['get', 'post'])
def index():
    return render_template('html/03-beat.html')


if __name__ == '__main__':
    app.run(port=9001)

03-login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webA_login page</title>
</head>
<body>
    <h1>我是 WebA 的登录页面</h1>
    <form method="post">
        <lable>用户名:</lable><input type="text" name="username">

        <lable>密&nbsp;&nbsp;&nbsp;码:</lable><input type="password" name="password">

        <input type="submit" value="登录">
    </form>
    <hr>
    {% for message in get_flashed_messages() %}
        {{ message }}
    {% endfor %}
</body>
</html>

猜你喜欢

转载自blog.csdn.net/CSDNgaoqingrui/article/details/82557757