跨站请求伪造(CSRF,Cross-Site Request Forgery)
定义
跨站请求伪造(CSRF)是一种攻击方式,攻击者诱使已认证的用户在不知情的情况下执行非预期的操作。这种攻击利用了用户对目标网站的信任。
攻击原理
- 用户登录:用户登录目标网站(如银行网站),并获得一个会话Cookie。
- 诱使用户访问恶意网站:攻击者通过邮件、社交媒体等方式诱使用户访问恶意网站。
- 伪造请求:恶意网站包含一个自动提交的表单或脚本,向目标网站发送请求(如转账请求)。
- 执行操作:目标网站接收到请求后,由于用户已认证,请求会被执行。
示例
假设银行网站的转账接口如下:
POST /transfer HTTP/1.1 Host: bank.com Content-Type: application/x-www-form-urlencoded amount=1000&toAccount=attackerAccount
攻击者可以在恶意网站中嵌入以下代码:
<form action="https://bank.com/transfer" method="POST"> <input type="hidden" name="amount" value="1000"> <input type="hidden" name="toAccount" value="attackerAccount"> </form> <script> document.forms[0].submit(); </script>
当用户访问恶意网站时,表单会自动提交,导致用户账户向攻击者账户转账。
防御措施
1. 使用CSRF令牌
- 原理:为每个表单生成一个唯一的令牌(Token),并在提交时验证该令牌。
- 实现: 服务器生成令牌并嵌入表单中。提交表单时,服务器验证令牌是否匹配。
- 示例:
2. 验证请求来源
- 检查Referer头:验证请求是否来自合法的来源。
- 注意:某些浏览器可能不发送Referer头,或用户可能禁用该功能。
3. 使用SameSite Cookie属性
- 原理:设置Cookie的
SameSite
属性为Strict
或Lax
,限制跨站请求携带Cookie。 - 示例:
4. 双重验证
- 原理:对于敏感操作(如转账),要求用户进行二次验证(如输入密码或短信验证码)。
5. 限制敏感操作的HTTP方法
- 原理:仅允许POST、PUT等HTTP方法执行敏感操作,避免GET请求被滥用。
6. 自定义请求头
- 原理:在AJAX请求中添加自定义头(如
X-Requested-With
),并在服务器端验证。 - 注意:这种方法仅适用于AJAX请求。
示例代码(CSRF令牌实现)
服务器端(生成令牌)
import os from flask import Flask, render_template, request, session app = Flask(__name__) app.secret_key = os.urandom(24) @app.route('/transfer', methods=['GET', 'POST']) def transfer(): if request.method == 'GET': # 生成CSRF令牌 session['csrf_token'] = os.urandom(16).hex() return render_template('transfer.html', csrf_token=session['csrf_token']) elif request.method == 'POST': # 验证CSRF令牌 if request.form.get('csrf_token') != session.get('csrf_token'): return "CSRF验证失败", 403 # 执行转账操作 return "转账成功" if __name__ == '__main__': app.run()
客户端(HTML表单)
<form action="/transfer" method="POST"> <input type="hidden" name="csrf_token" value="{{ csrf_token }}"> <label for="amount">金额:</label> <input type="text" id="amount" name="amount"> <label for="toAccount">收款账户:</label> <input type="text" id="toAccount" name="toAccount"> <input type="submit" value="转账"> </form>
总结
CSRF攻击利用了用户对目标网站的信任,通过伪造请求执行非预期操作。防御CSRF的关键在于:
- 使用CSRF令牌。
- 验证请求来源。
- 设置SameSite Cookie属性。
- 对敏感操作进行双重验证。
通过以上措施,可以有效防止CSRF攻击。
进阶高级测试工程师 文章被收录于专栏
《高级软件测试工程师》专栏旨在为测试领域的从业者提供深入的知识和实践指导,帮助大家从基础的测试技能迈向高级测试专家的行列。 在本专栏中,主要涵盖的内容: 1. 如何设计和实施高效的测试策略; 2. 掌握自动化测试、性能测试和安全测试的核心技术; 3. 深入理解测试驱动开发(TDD)和行为驱动开发(BDD)的实践方法; 4. 测试团队的管理和协作能力。 ——For.Heart