跨站攻击与防御(XSS、CSRF)
Web 项目中最常见的两种安全漏洞是 XSS 和 CSRF。本页将讲解它们的原理、危害与防御方案。
🔐 XSS(跨站脚本攻击)
💡 原理
攻击者在网页中插入恶意 JavaScript,诱导用户执行,达到窃取数据或控制页面的目的。
💣 示例:
<!-- 用户输入内容未经过处理直接渲染 -->
<p>评论内容:<script>alert('被攻击了')</script></p>
✅ 防御方法
| 方法 | 描述 |
|---|---|
| 输出转义 | 对用户输入进行 HTML 编码 |
| CSP 策略 | 限制可加载的脚本来源 |
| 禁止内联脚本 | 避免使用 dangerouslySetInnerHTML |
📦 React 安全示例
// 安全:React 自动转义
<p>{userComment}</p>
// 不安全:允许原样插入脚本
<p dangerouslySetInnerHTML={{ __html: userComment }} />
🎭 CSRF(跨站请求伪造)
💡 原理
攻击者诱导用户在已登录状态下发起未授权请求,例如偷偷提交表单或发送转账请求。
💣 示例攻击代码
<!-- 用户访问此页面,浏览器自动携带 cookie -->
<img src="https://yourbank.com/transfer?to=attacker&amount=1000">
✅ 防御方法
| 方法 | 描述 |
|---|---|
| CSRF Token | 后端生成并验证每次请求中的唯一标识 |
| SameSite Cookie | 防止跨站点自动携带 Cookie |
| Referer 检查 | 校验请求来源是否可信 |
| 验证码 | 阻断自动提交流程(辅助防御) |
🧑💻 实战防御代码
✅ Express 中使用 CSRF Token
const csrf = require("csurf");
app.use(csrf({ cookie: true }));
app.get("/form", (req, res) => {
res.render("form", { csrfToken: req.csrfToken() });
});
✅ 设置 SameSite Cookie 限制
Set-Cookie: sessionid=abc123; SameSite=Strict; HttpOnly; Secure
✅ 配置 CSP 策略(Nginx 示例)
add_header Content-Security-Policy "default-src 'self'";
限制脚本、图片、CSS 资源必须来自本域。
🧠 对比总结
| 项目 | XSS | CSRF |
|---|---|---|
| 攻击目标 | 浏览器 | 服务器 |
| 利用点 | 插入脚本 | 自动携带 Cookie |
| 用户操作 | 点击/访问恶意内容 | 无需点击即可触发 |
| 防御核心 | 输出转义 / CSP | Token / SameSite / Referer |
📌 应用场景下的防御建议
| 场景 | 建议 |
|---|---|
| 有用户评论、昵称等输入 | 使用输出转义防止 XSS |
| 登录后执行敏感操作 | 添加 CSRF Token 校验 |
| 接口用 Cookie 认证 | 启用 SameSite 限制跨站携带 |
| 用户生成内容可渲染 HTML | 强制 CSP 策略、避免 innerHTML |