赞
踩
CSRF(Cross-Site Request Forgery,跨站请求伪造)攻击是一种允许攻击者通过受害者的身份执行非预期操作的安全威胁。为了防御这种攻击,前端开发者通常需要结合后端验证和特定的前端策略。
这是最常用的防御手段,通常涉及生成一个CSRF令牌,并将其在客户端和服务器之间交换。
在用户登录成功后,服务器生成一个CSRF令牌,并将其存储在用户的会话中。
# Python 示例
from flask import Flask, session
app = Flask(__name__)
@app.route('/login')
def login():
session['csrf_token'] = generate_csrf_token()
return render_template('login.html', csrf_token=session['csrf_token'])
将令牌嵌入到每个需要防护的表单中,或者作为HTTP头的一部分。
<!-- HTML 示例 -->
<form action="/protected" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<!-- ...其他表单字段... -->
</form>
// JavaScript 示例(使用Fetch API)
fetch('/protected', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-CSRF-Token': window.csrfToken
},
body: formData
});
虽然不完全可靠,因为Referer头可以被浏览器禁用或篡改,但通常可以作为辅助防御措施。
# Python 示例(Flask中间件)
from flask import request
@app.before_request
def check_referer():
if request.method in ['POST', 'PUT', 'DELETE']:
if not request.referrer or request.referrer != app.config['APP_BASE_URL']:
return abort(403)
要求用户在提交敏感操作前进行二次确认,例如通过弹窗或验证码。
设置Cookie的SameSite
属性为Lax
或Strict
,限制跨站提交。Lax
模式允许在top-level
导航中发送,而Strict
模式则更严格,只在同一站点内的请求中发送。
# Python 示例(使用Flask-Session扩展)
from flask_session import Session
from flask import Flask
app = Flask(__name__)
Session(app)
app.session_interface.cookie_samesite = 'Lax'
对于敏感操作,只接受POST请求,不使用GET请求,因为GET请求容易被浏览器书签、链接预加载或第三方脚本滥用。
前端代码中,防御CSRF通常涉及在表单提交或Ajax请求时附带CSRF令牌。确保在后端验证令牌的有效性是至关重要的,因为前端的防御措施可以被绕过。
以下是一个Node.js + Express + CSRF保护的示例:
// server.js const express = require('express'); const bodyParser = require('body-parser'); const csrf = require('csurf'); const app = express(); // 使用cookie-parser中间件解析cookie app.use(require('cookie-parser')()); // 使用中间件生成和注入CSRF令牌 const csrfProtection = csrf({ cookie: true }); app.use(csrfProtection); // 保护路由 app.post('/protected', csrfProtection, (req, res) => { // 验证令牌并执行操作 if (req.csrfToken() === req.body.csrfToken) { // 安全的操作 } else { // CSRF令牌无效,返回错误 res.status(403).send('CSRF token mismatch'); } }); // 响应HTML页面,包含CSRF令牌 app.get('/', (req, res) => { res.send(` <form action="/protected" method="POST"> <input type="hidden" name="csrfToken" value="${req.csrfToken()}"> <button type="submit">Submit</button> </form> `); }); app.listen(3000);
内容安全策略(CSP)是一种网络安全策略,通过指定哪些外部资源可以被加载或执行,来减少跨站脚本攻击的风险。虽然CSP主要针对XSS攻击,但它也能间接帮助防御CSRF,特别是当CSP配置得当,限制了第三方网站对你的应用发起请求的能力时。
// 在Express应用中设置CSP头部
app.use((req, res, next) => {
res.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline'");
next();
});
尽管不如使用CSRF令牌可靠,但在某些场景下检查Origin头部也可以作为一种辅助防御措施。如果请求来自不受信任的源,服务器可以选择拒绝该请求。
# Flask示例
from flask import request
@app.before_request
def verify_origin():
if request.method == 'POST':
allowed_origins = ['https://your-trusted-origin.com']
origin = request.headers.get('Origin')
if origin not in allowed_origins:
return 'Unauthorized', 401
强制浏览器只通过HTTPS与服务器通信,可以防止中间人攻击,从而降低CSRF攻击的风险,因为攻击者更难以拦截或修改HTTPS通信。
# Flask示例
@app.after_request
def apply_hsts(response):
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
return response
Web应用防火墙可以提供额外的防护层,检测并阻止恶意请求,包括CSRF攻击。WAF可以是硬件设备、软件服务或云服务,通常基于签名匹配、行为分析或机器学习算法来识别和阻止攻击。
限制用户执行敏感操作的速率可以帮助防止大规模的CSRF攻击。例如,限制用户在一分钟内只能提交几次更改密码或删除账户的请求。
// 使用JavaScript实现简单的速率限制
let lastRequestTime = null;
const LIMIT = 60 * 1000; // 一分钟
function submitSensitiveAction() {
const currentTime = Date.now();
if (lastRequestTime && currentTime - lastRequestTime < LIMIT) {
alert('Too many requests, please try again later.');
return;
}
// 提交请求...
lastRequestTime = currentTime;
}
虽然POST请求通常被认为比GET请求更安全,但某些情况下,GET请求可能不可避免。在这种情况下,确保URL不会被缓存或记录在浏览器历史记录中,以降低CSRF风险。例如,使用动态生成的随机参数,而不是直接暴露敏感信息。
# Django示例
from django.http import HttpResponseBadRequest
def sensitive_get_view(request):
if not request.GET.get('random_token') == request.session.get('random_token'):
return HttpResponseBadRequest('Invalid token')
# 执行敏感操作...
# 清除随机令牌,防止重放攻击
request.session.pop('random_token', None)
现代Web应用经常使用OAuth 2.0或JSON Web Tokens (JWT)进行身份验证。这些协议提供了内置的机制来验证请求的来源和授权状态,从而降低CSRF攻击的风险。然而,正确实现这些协议同样至关重要,因为它们也有自己的安全挑战。
确保你使用的前端框架、后端库和服务器软件都保持最新,以便获得最新的安全补丁和修复。
遵循安全编码最佳实践,如输入验证、输出编码、错误处理和日志记录,可以帮助发现和修复潜在的漏洞。此外,定期进行安全测试,如渗透测试和代码审查,可以确保应用在发布之前是安全的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。