1.CSRF攻击原理
- 用户登录受信任网站:用户在受信任的网站上登录,并获得一个会话
Cookie。 - 攻击者诱导用户访问恶意网站:攻击者通过各种手段(如
钓鱼邮件、恶意广告等)诱导用户访问一个恶意网站。 - 恶意网站发送伪造请求:恶意网站在用户不知情的情况下,向受信任的网站发送
伪造的请求。这些请求会携带用户的会话Cookie,从而使受信任的网站认为这些请求是合法用户发出的。 - 受信任网站执行请求:受信任的网站接收到伪造的请求后,认为是合法用户发出的,从而执行相应的操作(如
转账、修改密码等)。
2.防御 CSRF 攻击的方法
- 使用 CSRF Token:在每个表单或请求中加入一个随机生成的
CSRF Token,并在服务器端进行验证。只有携带正确 Token 的请求才会被执行。
html表单
<form method="POST" action="/transfer">
//关键代码
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="text" name="amount" placeholder="Amount">
<button type="submit">Transfer</button>
</form>
服务器端验证(Node.js 示例)
const express = require('express');
const csrf = require('csurf');
const bodyParser = require('body-parser');
const app = express();
const csrfProtection = csrf({ cookie: true });
app.use(bodyParser.urlencoded({ extended: false }));
app.use(csrfProtection);
app.get('/transfer', (req, res) => {
res.render('transfer', { csrf_token: req.csrfToken() });
});
app.post('/transfer', (req, res) => {
// 验证 CSRF Token
if (req.body.csrf_token !== req.csrfToken()) {
return res.status(403).send('Invalid CSRF Token');
}
// 处理转账逻辑
res.send('Transfer successful');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
- 验证 Referer 或 Origin 头:在服务器端检查请求的
Referer 或 Origin 头,确保请求是从受信任的源发出的。 - SameSite Cookie 属性:设置 Cookie 的 SameSite 属性为
Strict或Lax,限制第三方网站发送的请求携带 Cookie。 - 双重提交 Cookie:在请求中同时提交 Cookie 和表单字段中的 Token,服务器端验证两者是否一致。
- 使用 CAPTCHA:在关键操作前使用 CAPTCHA 验证,确保请求是由用户主动发出的。