面试题答案
一键面试CSRF 攻击原理
- 攻击场景:用户已登录目标网站 A 并处于认证状态,此时在同一浏览器中访问恶意网站 B。
- 恶意操作触发:恶意网站 B 构造一个伪装成网站 A 合法请求的表单或 AJAX 请求,利用浏览器自动携带已登录网站 A 的 Cookie 等认证信息的特性,在用户不知情的情况下,向网站 A 发起请求,执行一些如转账、修改密码等敏感操作。例如,恶意网站 B 中有一段隐藏的表单:
<form action="https://target - site - a.com/transfer" method="post">
<input type="hidden" name="amount" value="1000" />
<input type="hidden" name="to" value="attacker_account" />
<input type="submit" value="Submit" style="display:none" />
</form>
<script>document.forms[0].submit();</script>
当用户访问恶意网站 B 时,该表单会自动提交,由于浏览器会携带用户在目标网站 A 的认证 Cookie,目标网站 A 会认为这是一个合法用户的请求,从而执行转账操作。
防范 CSRF 攻击的策略
1. CSRF Token
- 原理:在用户访问网站时,服务器生成一个随机且唯一的 Token 并返回给客户端,客户端在每次向服务器发送请求时,将该 Token 包含在请求中。服务器验证请求中的 Token 是否与预期一致,如果不一致则拒绝请求。
- 在 Next.js 项目中的实现:
- 生成 Token:在服务器端(如 API Routes 中),可以使用
crypto
模块生成 Token。例如:
- 生成 Token:在服务器端(如 API Routes 中),可以使用
import crypto from 'crypto';
export default function handler(req, res) {
const csrfToken = crypto.randomBytes(32).toString('hex');
res.setHeader('Set - Cookie', `csrfToken=${csrfToken}; HttpOnly; Path=/`);
res.status(200).json({ csrfToken });
}
- **验证 Token**:在处理敏感请求的 API Routes 中,获取请求中的 Token 并进行验证。
import { NextApiRequest, NextApiResponse } from 'next';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const receivedToken = req.cookies.csrfToken;
const expectedToken = req.body.csrfToken;
if (receivedToken!== expectedToken) {
return res.status(403).json({ error: 'CSRF token mismatch' });
}
// 处理正常业务逻辑
res.status(200).json({ message: 'Request processed successfully' });
}
2. Same - Site Cookies
- 原理:通过设置
Same - Site
属性为Strict
或Lax
来限制 Cookie 的发送范围。Strict
模式下,只有在同站请求时才会发送 Cookie;Lax
模式下,允许在一些安全的跨站导航(如从外部链接点击进入网站)时发送 Cookie,但对于跨站的 POST 等非安全请求不会发送 Cookie。 - 在 Next.js 项目中的实现:在设置 Cookie 时添加
Same - Site
属性。例如:
import { NextApiRequest, NextApiResponse } from 'next';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.setHeader('Set - Cookie', `sessionId=12345; Same - Site=Strict; Path=/`);
res.status(200).json({ message: 'Cookie set' });
}
3. Double Submit Cookie
- 原理:与 CSRF Token 类似,服务器在设置 Cookie 时,同时将 Token 作为 Cookie 的值。客户端在发送请求时,将该 Cookie 值作为请求头(或请求体)的一部分发送回服务器。服务器验证 Cookie 中的 Token 和请求中的 Token 是否一致。
- 在 Next.js 项目中的实现:
- 设置 Cookie 与 Token:
import crypto from 'crypto';
import { NextApiRequest, NextApiResponse } from 'next';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const csrfToken = crypto.randomBytes(32).toString('hex');
res.setHeader('Set - Cookie', `csrfToken=${csrfToken}; Path=/`);
res.status(200).json({ csrfToken });
}
- **验证 Token**:
import { NextApiRequest, NextApiResponse } from 'next';
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const receivedTokenFromCookie = req.cookies.csrfToken;
const receivedTokenFromRequest = req.headers['x - csrf - token'];
if (receivedTokenFromCookie!== receivedTokenFromRequest) {
return res.status(403).json({ error: 'CSRF token mismatch' });
}
// 处理正常业务逻辑
res.status(200).json({ message: 'Request processed successfully' });
}