使用Python编写CSRF攻击和防御的实验课程

2023-04-17 00:00:00 攻击 编写 防御

CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的网络攻击方式,主要针对已经登录的用户。本实验课程将使用Python演示CSRF攻击和防御的方法。

准备工作:安装Python和Flask框架

  1. CSRF攻击

首先,我们需要编写一个简单的Flask应用程序来演示CSRF攻击。该应用程序包含一个简单的表单和一个提交按钮,用户可以在表单中输入一个文本字符串,并将其发送到服务器上。

from flask import Flask, render_template, request

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/submit', methods=['POST'])
def submit():
    text = request.form['text']
    return f'Text submitted: {text}'

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

上述代码中,index函数用于渲染一个包含表单的HTML页面,submit函数用于接收用户提交的表单数据并将其显示在结果页面上。

接下来,我们编写一个简单的HTML页面作为CSRF攻击的载体。该页面包含一个隐藏的表单,在用户不知情的情况下,提交用户的登录状态(例如cookie)和一个文本字符串到服务器。

<!DOCTYPE html>
<html>
<body>
<script>
    function submit_form() {
        // 创建一个隐藏的表单
        const form = document.createElement('form');
        form.method = 'POST';
        form.action = 'http://localhost:5000/submit';

        // 创建表单元素并将其添加到表单中
        const text = document.createElement('input');
        text.type = 'hidden';
        text.name = 'text';
        text.value = 'pidancode.com';

        // 添加表单元素到表单中
        form.appendChild(text);

        // 将表单添加到页面中
        document.body.appendChild(form);

        // 提交表单
        form.submit();
    }
</script>

<button onclick="submit_form()">Click me</button>
</body>
</html>

上述代码中的Javascript函数,会在用户点击“Click me”按钮时,自动创建一个隐藏的表单并将其提交到服务器。用户并不知道正在提交表单,因此这种方式被称为“伪造请求”。

在使用CSRF攻击之前,我们需要登录到Flask应用程序中。我们可以手动在浏览器中登录到应用程序中,或者使用以下代码进行登录:

import requests

# 登录到Flask应用程序中
session = requests.Session()

data = {
    'username': 'username',
    'password': 'password'
}

login_url = 'http://localhost:5000/login'
response = session.post(login_url, data=data)

现在,我们可以使用上述准备过的HTML页面进行CSRF攻击。将HTML页面保存为csrf.html文件,并使用以下代码在本地服务器上运行:

from flask import Flask, render_template, request

app = Flask(__name__)

# 登录状态
logged_in = False

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/submit', methods=['POST'])
def submit():
    global logged_in
    text = request.form['text']
    if logged_in:
        return f'Text submitted: {text}'
    else:
        return 'Not logged in.'

@app.route('/login', methods=['POST'])
def login():
    global logged_in
    logged_in = True
    return 'Logged in.'

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

最后,在浏览器中打开Flask应用程序并登录,然后访问csrf.html文件。在页面中,单击“Click me”按钮,看到文本字符串通过CSRF攻击已成功提交到服务器。

  1. CSRF防御

为了防止CSRF攻击,我们可以使用CSRF令牌来验证每次提交是否是合法的。在Flask框架中,可以使用flask-wtf扩展来轻松地生成和验证CSRF令牌。

首先,我们需要安装Flask-WTF扩展。可以使用以下命令进行安装:

pip install flask-wtf

接下来,在Flask应用程序中添加CSRF保护,只需使用CSRFProtect类即可。您还需要通过在Flask配置中设置SECRET_KEY来配置应用程序的加密密钥。

from flask import Flask, render_template, request
from flask_wtf.csrf import CSRFProtect

app = Flask(__name__)
csrf = CSRFProtect(app)

app.config['SECRET_KEY'] = 'your-secret-key'

现在,每次Flask应用程序呈现包含表单的页面时,csrf_token()函数将自动为表单生成CSRF令牌。我们需要将CSRF令牌包含在每个表单提交中,这可以通过在模板中添加一个隐藏的输入字段来完成。

<!DOCTYPE html>
<html>
<body>
{{ form.csrf_token }}
<form method="POST" action="{{ url_for('submit') }}">
    <input type="text" name="text">
    <button type="submit">Submit</button>
</form>
</body>
</html>

现在,当用户提交表单时,Flask-WTF扩展将自动验证CSRF令牌是否匹配,以确保请求是合法的。如果CSRF令牌不匹配,应用程序将拒绝请求并显示错误。

from flask import Flask, render_template, request
from flask_wtf.csrf import CSRFProtect

app = Flask(__name__)
csrf = CSRFProtect(app)

app.config['SECRET_KEY'] = 'your-secret-key'

@app.route('/')
def index():
    form = TextForm()
    return render_template('index.html', form=form)

@app.route('/submit', methods=['POST'])
@csrf.exempt    # 在测试代码中,我们需要在这里禁用CSRF保护
def submit():
    text = request.form['text']
    return f'Text submitted: {text}'

注:为了方便,这里使用了一个名为TextForm的WTForms表单,用于在index函数中呈现表单。实际上,这并不是必须的,您可以使用原始HTML表单来替换它。

现在,我们可以再次启动Flask应用程序,并访问具有安全保护的页面,进行手动测试。在进行CSRF攻击时,Flask-WTF扩展将验证CSRF令牌是否匹配,从而阻止攻击。

以上就是Python编写CSRF攻击和防御的实验课程,希望对您有所帮助。

相关文章