问题一:什么是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 response29 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 # 取到表单中的token47 form_csrf_token = request.form.get('csrf_token')48 # cookie中的token49 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_token62 response.set_cookie('csrf_token', csrf_token)63 return response64 65 66 # 生成 csrf_token67 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)
1 2 3 4 516 17 18登录 6 7 8 9我是网站A,登录页面
10 11
1 2 3 4 516 17 18转账 6 7 8我是网站A,转账页面
9 10
站点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)
1 2 3 4 516 17 18Title 6 7 8 9我是网站B
10 11
备注:B中隐藏的标签会在用户不知道的情况下携带A中的cookie值向A站点发送转账的请求;