为什么你需要关注 XSS 和 CSRF?

215 阅读6分钟

前言

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

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

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

攻击方式

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

  1. 死循环:导致页面卡死或崩溃。
  2. 窃取 Cookie:获取用户的登录凭证。
  3. 监听用户行为:记录键盘输入、鼠标点击等操作。
  4. 修改 DOM:伪造登录表单或其他交互界面。
  5. 生成浮窗广告:干扰用户体验。
类型
  1. 反射型 XSS

    • 恶意脚本通过 URL 注入。
    • 脚本作为网络请求的参数,经过服务器反射到 HTML 文档中执行。
    • 特点:服务器不会存储这些恶意脚本。
    • 常见场景:网站搜索、跳转功能。
  2. 存储型 XSS

    • 恶意脚本发送到服务器数据库。
    • 当前端请求数据时,服务器将恶意脚本返回给前端并执行。
    • 特点:脚本存储在服务器上。
    • 常见场景:论坛发帖、商品评论、用户私信。
  3. DOM 型 XSS

    • 恶意代码由浏览器端完成解析和执行。
    • 不经过服务器处理,属于前端 JavaScript 的安全漏洞。
    • 常见场景:通过 URL 参数或动态生成的 DOM 结构触发。 通过修改页面的 DOM 树来注入恶意脚本,客户端脚本在处理 DOM 数据时没有进行适当的验证和过滤,导致攻击者可以利用这一点来修改页面内容并执行恶意脚本。
  4. 文档型 XSS

    • 攻击者劫持网络数据包,直接修改 HTML 文档。

    • 场景包括:

      • WIFI 路由劫持。
      • 本地恶意软件。
防范措施
  1. 对输入进行转码过滤

    • 对用户输入的数据进行严格校验和转义,防止特殊字符(如 <>& 等)被解析为 HTML 或 JavaScript。

输入过滤与转义

// 使用 encodeURIComponent 转义特殊字符
const safeInput = encodeURIComponent(userInput);
// 或借助第三方库(如 DOMPurify)过滤危险标签
const cleanHTML = DOMPurify.sanitize(dirtyHTML);
  1. 利用 CSP(Content Security Policy)

    • 浏览器内容安全策略,核心是限制浏览器加载哪些资源。

    • 功能:

      • 限制其他域下的资源加载。
      • 禁止向其他域提交数据。
      • 提供上报机制。
  • 通过 HTTP 头设置资源加载白名单:
Content-Security-Policy: default-src 'self'; script-src https://trusted.cdn.com;
  1. HttpOnly Cookie

    • 设置 HttpOnly 属性,阻止 JavaScript 访问 Cookie。
    • 保护敏感信息(如会话标识符)不被恶意脚本窃取。
    1. 什么是 HttpOnly

HttpOnly 是一种 Cookie 属性,当一个 Cookie 被设置为 HttpOnly 时,浏览器会禁止前端 JavaScript 直接访问该 Cookie。这意味着,即使攻击者通过 XSS(跨站脚本攻击)成功注入恶意脚本,也无法通过 document.cookie 获取或修改这个 Cookie 的值。


二、CSRF(跨站请求伪造)

定义

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

攻击原理
  • 利用同源策略中的 Cookie 自动携带机制。
  • 攻击者构造恶意请求,诱导用户在不知情的情况下提交请求。
攻击方式
  1. 自动发送 GET 请求
    利用 img src="..."script src="..." 标签发送请求。当用户访问包含恶意代码的网页时,这些标签会自动向目标网站发送 GET 请求,并携带用户的 Cookie 等信息。

     

    比如,攻击者创建了一个恶意网页,其中包含以下代码:

    <img src="https://bank.com/transfer?amount=1000&to=attacker_account">
    

    如果用户在已登录银行网站的情况下访问该恶意网页,就可能会触发向银行网站发送转账 1000 元到攻击者账户的 GET 请求。<!---->

  2. 自动发送 POST 请求:构造隐藏的 form 表单并自动提交。表单中包含攻击者预设的参数,如转账金额、目标账号等,在用户不知情的情况下提交到目标网站。攻击者在恶意网站中构造了如下隐藏表单:

<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_account">
</form>
<script>document.forms[0].submit();</script>

当用户访问该恶意网站时,表单会自动提交,向银行网站发送转账 5000 元到攻击者账户的 POST 请求。

  1. 诱导点击发送 GET 请求:通过伪装链接或按钮,诱导用户点击。例如,将恶意链接伪装成正常的下载链接,用户点击后就会向目标网站发送恶意 GET 请求。攻击者将恶意链接bank.com/transfer?am…伪装成 “点击下载最新电影资源”,用户一旦点击,就可能触发向银行网站的转账请求。
危害
  • 冒充用户执行敏感操作(如转账、删除数据)。
  • 泄露用户隐私信息。
防范措施
  1. SameSite Cookie

    • 设置 Cookie 的 SameSite 属性,控制跨站请求是否携带 Cookie。

    • 取值:

      • Strict:完全禁止第三方请求携带 Cookie。
      • Lax:仅允许 GET 请求携带 Cookie。
      • None:默认模式,允许跨站请求携带 Cookie(需配合 Secure 属性)。

为什么 SameSite Cookie 能防范 CSRF?

CSRF(跨站请求伪造)攻击的核心在于,浏览器在跨站请求中会自动携带用户的 Cookie,这使得攻击者可以利用用户的身份向目标网站发送恶意请求。SameSite Cookie 的引入正是为了解决这一问题,通过控制跨站请求是否携带 Cookie,减少 CSRF 攻击的风险。

image.png

  1. 验证来源站点

    • 检查请求头中的 Origin 和 Referer 字段。

      • Origin:只包含域名信息。
      • Referer:包含具体的 URL 路径。
  2. CSRF Token

    • 后端生成一个唯一的 Token 并传递给前端。
    • 前端每次请求时携带该 Token,后端验证 Token 是否合法。
    • Token 可以存储在 Cookie 或 LocalStorage 中。
  3. 敏感操作确认

    • 对敏感操作增加额外的验证步骤(如二次密码验证,(短信验证码、生物识别))。
    • 缩短敏感信息的 Cookie 生命周期。

END

Web 安全没有银弹,唯有深入理解攻击原理,构建纵深防御体系,方能在攻防博弈中立于不败之地。