zoukankan      html  css  js  c++  java
  • flask内容学习第三天(flak中的csrf跨站请求)

    问题一:什么是csrf?

    英文全称Cross Site Request Forgery(跨站请求伪造);

    通俗来讲就是攻击者盗用你的身份,冒用你的名义发出恶意请求,包括发送邮件,电话信息,甚至于转账或者是购买虚拟货币;

    csrf攻击的示意图()

    CSRF攻击的原理:

    1,用户向服务器端发送请求登录信息,服务器端会在用户的浏览器上设置A站点的cookie值;

    2,用户在未清除cookie的情况下,在B站点中点击向隐藏的向A站点发送请求的标签,在用户不知情的情况下向A站点发送请求;

    3;若A站点在未进行csrftoken验证的情况下,B站点伪造过来的请求就会通过服务器的验证,从而进行下一步的操作。

    防止CSRF攻击的方法:

    1,前端页面发送请求数据的时候,后端会想cookies上设置一串随机字符串(csrf_token值);

    2,在form表单中将设置一个隐藏的字段,值与在cookies中设置的相同(csrf_token值);

    3,在用户点击提交的时候,客户端会同时将两个值发送到后端程序;

    4,后端接收到客户端的请求之后,会做出一下几个动作

      1,从cookies中将csrf_token值取出来;

      2,将forn表单中的csrf_token值出来;

      3,将两个随机字符串做对比;

    5,相同就就表明是用户自己发送过来的请求,不相同就表示是伪造的的用户请求。

    代码实例

     1 import base64
     2 import os
     3 from _curses import flash
     4 
     5 from flask import Flask, render_template, make_response
     6 from flask import redirect
     7 from flask import request
     8 from flask import url_for
     9 
    10 app = Flask(__name__)
    11 
    12 
    13 @app.route('/', methods=["POST", "GET"])
    14 def index():
    15     if request.method == "POST":
    16         # 取到表单中提交上来的参数
    17         username = request.form.get("username")
    18         password = request.form.get("password")
    19 
    20         if not all([username, password]):
    21             print('参数错误')
    22         else:
    23             print(username, password)
    24             if username == 'laowang' and password == '1234':
    25                 # 状态保持,设置用户名到cookie中表示登录成功
    26                 response = redirect(url_for('transfer'))
    27                 response.set_cookie('username', username)
    28                 return response
    29             else:
    30                 print('密码错误')
    31 
    32     return render_template('temp_login.html')
    33 
    34 
    35 @app.route('/transfer', methods=["POST", "GET"])
    36 def transfer():
    37     # 从cookie中取到用户名
    38     username = request.cookies.get('username', None)
    39     # 如果没有取到,代表没有登录
    40     if not username:
    41         return redirect(url_for('index'))
    42 
    43     if request.method == "POST":
    44         to_account = request.form.get("to_account")
    45         money = request.form.get("money")
    46         # 取到表单中的token
    47         form_csrf_token = request.form.get('csrf_token')
    48         # cookie中的token
    49         cookie_csrf_token = request.cookies.get('csrf_token', "")
    50 
    51         # 做校验。如果校验成功,再进行转账逻辑
    52         if form_csrf_token != cookie_csrf_token:
    53             return "非法请求"
    54 
    55         print('假装执行转账操作,将当前登录用户的钱转账到指定账户')
    56         return '转账 %s 元到 %s 成功' % (money, to_account)
    57 
    58     csrf_token = generate_csrf()
    59     # 渲染转换页面
    60     response = make_response(render_template('temp_transfer.html', csrf_token=csrf_token))
    61     # 往cookie中添加csrf_token
    62     response.set_cookie('csrf_token', csrf_token)
    63     return response
    64 
    65 
    66 # 生成 csrf_token
    67 def generate_csrf():
    68     return bytes.decode(base64.b64encode(os.urandom(48)))
    69 
    70 
    71 if __name__ == '__main__':
    72     app.run(debug=True, port=9000)
    站点A的逻辑代码示例
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>登录</title>
     6 </head>
     7 <body>
     8 
     9 <h1>我是网站A,登录页面</h1>
    10 
    11 <form method="post">
    12     <label>用户名:</label><input type="text" name="username" placeholder="请输入用户名"><br/>
    13     <label>密码:</label><input type="password" name="password" placeholder="请输入密码"><br/>
    14     <input type="submit" value="登录">
    15 </form>
    16 
    17 </body>
    18 </html>
    站点A的登录界面模拟
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>转账</title>
     6 </head>
     7 <body>
     8 <h1>我是网站A,转账页面</h1>
     9 
    10 <form method="post">
    11     <input type="hidden" name="csrf_token" value="{{ csrf_token }}">
    12     <label>账户:</label><input type="text" name="to_account" placeholder="请输入对方账户"><br/>
    13     <label>金额:</label><input type="number" name="money" placeholder="请输入转账金额"><br/>
    14     <input type="submit" value="转账">
    15 </form>
    16 
    17 </body>
    18 </html>
    站点A的转账模拟

    站点B的逻辑代码

     1 from flask import Flask
     2 from flask import render_template
     3 
     4 app = Flask(__name__)
     5 
     6 
     7 @app.route('/')
     8 def index():
     9     return render_template('temp_index.html')
    10 
    11 
    12 if __name__ == '__main__':
    13     app.run(debug=True, port=8000)
    站点B的逻辑代码模拟
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8 
     9 <h1 style="background: red">我是网站B</h1>
    10 
    11 <form method="post" action="http://127.0.0.1:9000/transfer">
    12     <input type="hidden" name="to_account" value="999999">
    13     <input type="hidden" name="money" value="190000">
    14     <input type="submit" value="点击领取优惠券">
    15 </form>
    16 
    17 </body>
    18 </html>
    站点B的模拟请求伪造的代码

    备注:B中隐藏的标签会在用户不知道的情况下携带A中的cookie值向A站点发送转账的请求;

  • 相关阅读:
    微软与谷歌盈利模式对比分析
    unity开源移动库iTween使用完整Demo
    开发过程遇到的问题和解决方法(备忘)
    微信开发基础教程
    WorkFlow基础实战
    操作系统学习笔记
    编译原理学习
    微信生态圈盈利模式分析
    数据与计算机通信学习笔记
    利用Spring.Net技术打造可切换的分布式缓存读写类
  • 原文地址:https://www.cnblogs.com/cerofang/p/9205558.html
Copyright © 2011-2022 走看看