跨站要求捏造(CSRF)是一种网络攻击方式,攻击者利用受害者在已登录的情况下,通过捏造的要求来履行歹意的操作,例如转账、更改密码等。本篇文章将介绍怎样使用Python实现csrf攻击和防御。
一、CSRF攻击
1.攻击原理
由于受害者已登录了某个网站,那末该网站的Cookie值已被存储在受害者浏览器中。攻击者可以捏造一个要求,将该要求发送给受害者,当受害者打开该要求时,该要求将在受害者的浏览器中被履行。此时,由于该要求携带的是捏造的Cookie,因此该要求被认为是合法的,网站没法辨别该要求是受害者自己发起的,或者攻击者捏造的。
2.攻击进程
攻击进程以下:
(1)攻击者构造一个包括攻击代码的页面,并将该页面发送给受害者。
(2)当受害者接收到该页面时,会自动履行页面里的攻击代码。
(3)攻击代码会构造一个要求,该要求中包括了攻击者所期望的操作。
(4)要求被发送至目标服务器,由于该要求包括了受害者的Cookie值,因此服务器会误认为该要求是合法的,并履行攻击者所期望的操作。
3.攻击代码
攻击代码以下:
import requests def csrf_attack(): # 将攻击代码放在一个页面中,并将该页面发送给受害者。 url = 'http://www.pidancode.com/attack.html' header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'} response = requests.get(url, headers=header) print(response.text)
攻击代码的作用是构造一个包括攻击要求的页面,并将该页面发送给受害者。在实际攻击中,攻击者可能会通过社交工程等手段来让受害者打开该页面。
4.攻击演示
为了演示攻击进程,我们可以构造一个被攻击的网站(这里以摹拟登录的网站为例)。
攻击网站代码:
from flask import Flask, request, render_template, session, redirect, url_for app = Flask(__name__) app.secret_key = 'pidancode' @app.route('/', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] # 简单摹拟登录功能,当用户名为'pidancode',密码为'123456'时登录成功。 if username == 'pidancode' and password == '123456': session['logged_in'] = True return redirect(url_for('home')) return render_template('login.html') @app.route('/home') def home(): if 'logged_in' in session: return 'Welcome to Pidancode.com!' else: return redirect(url_for('login')) if __name__ == '__main__': app.run(debug=True)
登录页面:
<!DOCTYPE html> <html> <head> <meta charset="utf⑻"> <title>Login</title> </head> <body> <form method="POST" action=""> <label>Username:</label> <input type="text" name="username"> <br> <label>Password:</label> <input type="password" name="password"> <br> <input type="submit" value="Login"> </form> </body> </html>
当用户名为’pidancode’,密码为’123456’时,登录成功,并显示’Welcome to Pidancode.com!’。
运行攻击网站,然后在另外一个窗口中运行攻击代码,具体进程以下:
(1)使用浏览器访问攻击网站,输入正确的用户名和密码,成功登录。
(2)使用同一浏览器访问攻击页面(attack.html),攻击代码自动履行。
(3)在攻击网站中会发现自动履行了一个注销登录的操作。
(4)此时,在攻击页面中再次访问攻击网站(http://localhost:5000/home),发现已退出登录。说明攻击成功。
二、CSRF防御
1.防御原理
防御CSRF攻击的方法很多,其中最多见的一种是使用验证码。当受害者发送一个要求时,系统会要求受害者先输入验证码,如果验证通过,则系统才会处理该要求,否则该要求将被谢绝。
2.防御代码
防御CSRF攻击的代码以下所示:
from flask import Flask, request, render_template, session, redirect, url_for import string, random app = Flask(__name__) app.secret_key = 'pidancode' @app.route('/', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] # 简单摹拟登录功能,当用户名为'pidancode',密码为'123456'时登录成功。 if username == 'pidancode' and password == '123456': session['logged_in'] = True session['csrf_token'] = ''.join(random.choice(string.ascii_lowercase + string.ascii_uppercase + string.digits) for x in range(32)) return redirect(url_for('home')) return render_template('login.html') @app.route('/home', methods=['GET', 'POST']) def home(): if 'logged_in' in session: if request.method == 'POST': # 验证CSRF Token,如果验证不通过,则谢绝该要求。 if request.form.get('csrf_token') != session.get('csrf_token'): return 'Error: Invalid CSRF Token' # 处理正确的要求。 operation = request.form.get('operation') if operation == 'logout': session.pop('logged_in', None) session.pop('csrf_token', None) return redirect(url_for('login')) else: return 'Error: Invalid Operation' # 防御CSRF攻击的核心代码,插入一个CSRF Token。 session['csrf_token'] = ''.join(random.choice(string.ascii_lowercase + string.ascii_uppercase + string.digits) for x in range(32)) return render_template('home.html', csrf_token=session['csrf_token']) else: return redirect(url_for('login')) if __name__ == '__main__': app.run(debug=True)
在登录成功后,为了防御CSRF攻击,我们会创建一个CSRF Token,并将该Token存储在用户的会话中,以便在遭到要求时进行验证。
当用户发送一个带有操作数据的POST要求时,我们会从前端获得到该要求中的CSRF Token,并根据前端提供的Token来验证该要求。如果验证通过,则继续进行数据处理。
另外,在每次用户访问主页时,都需要重新生成一个CSRF Token,并将该Token插入到网页中,以保证每一个要求都是唯一的。
3.防御演示
在使用防御代码后,可以复现上述攻击流程:
(1)使用浏览器访问攻击网站,输入正确的用户名和密码,成功登录。
(2)使用同一浏览器访问攻击页面(attack.html),攻击代码自动履行。
(3)攻击者期望的注销登录操作没有被履行,并且在攻击页面中访问http://localhost:5000/home,收到了’Error: Invalid CSRF Token’消息,说明要求被谢绝。
这表明,我们的CSRF防御代码已成功地防御了该攻击。
本文来源:https://www.yuntue.com/post/83500.html | 云服务器网,转载请注明出处!