Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

订阅源联系隐私© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
jellyfin-playlist-itemids — Jellyfin Server 12.2 - 高危 - 远程 - IDOR - 公共播放列表 ItemIds 遗留自 GHSA-9x85,随后可未授权串流 | Kitploit
工具/GitHubGitHub/abraxas/jellyfin-playlist-itemids
漏洞分析Web应用程序漏洞利用数据泄露信息收集Web安全渗透测试API 安全实验室与实践
GitHubabraxas/jellyfin-playlist-itemids

jellyfin-playlist-itemids

Jellyfin Server 12.2 - 高危 - 远程 - IDOR - 公共播放列表 ItemIds 遗留自 GHSA-9x85,随后可未授权串流

查看仓库
31天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Abraxas Labs - jellyfin-playlist-itemids

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  jellyfin-playlist-itemids

jellyfin-playlist-itemids

类别: IDOR 影响范围: 远程(任何能看到公开播放列表的用户)

Jellyfin Server v12.2(ca0f16eb7c195f720a1493ed469a27c4657db0c6)- Jellyfin

GHSA-9x85 为 GET /Playlists/{id}/Items 修补了 GetUserId 以及 Where(i => i.Item2.IsVisible(user))。GET /Playlists/{id} 却没有加上该过滤条件。ItemIds 来自 GetManageableItems(),对子项没有 IsVisible 检查。GetPlaylistForUser 只要求播放列表本身可见。

CreatePlaylistDto.IsPublic 默认为 true。OpenAccess 播放列表对其他用户是 IsVisible 的(HasParentalAllowedChild 仍允许第二个用户看到该播放列表)。未认证的 GET /Videos/{id}/stream 没有 [Authorize]。StreamingHelpers 加载 GetItemById 时不带用户上下文。

任何能看到公开播放列表的用户,都能从 ItemIds 中读取私有子项的 GUID,然后在没有令牌的情况下流式获取这些文件。

ID暂无 CVE
类别IDOR(播放列表 ItemIds 是 GHSA-9x85 的遗留问题,随后导致未认证流式访问)
影响范围远程(任何能看到公开播放列表的用户)
CWECWE-639、CWE-862
CVSS高危:6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
产品Jellyfin Server
受影响版本v12.2(ca0f16eb)镜像 jellyfin/jellyfin:12.2
认证获取播放列表需要认证;流式访问无需认证
许可证GNU Affero GPL v3.0
实验环境仅 127.0.0.1:18800

Jellyfin 12.2 遗留问题中的遗留问题 #3。遗留问题 #1(最重要):jellyfin-suggestions-idor。同一版本:jellyfin-svg-gzip · jellyfin-ffmpeg-colonslash。

攻击者能做什么

受害者和攻击者是同一服务器上的两个用户,各自拥有互不相交的媒体库(例如儿童库与成人库,或一个隐藏文件夹)。受害者将一部私有影片放入公开播放列表。通过请求体创建时 IsPublic 默认为 true,因此这是常见情况,而非共享行为。攻击者以受限账户登录,读取播放列表对象,然后在没有 Authorization 头的情况下获取文件。

这泄露的是攻击者未被分配到的媒体库中媒体的 GUID,随后可通过流式接口获取完整文件。这不是播放列表标题枚举。添加/创建操作仍会丢弃不可见的条目。

侦察(实验环境已验证)

方法路径权限
GET/Playlists/{playlistId}可见播放列表的子项 GUID(ItemIds 来自 GetManageableItems(),对子项没有 IsVisible 检查)。还包括 Shares[].UserId / CanEdit(共享接收者的 userId)。实验:B 的 GET /Playlists/{id}/Items 为空;同一 id 的 GET /Playlists/{id} 列出了私有 GUID a2bf95146e44897be6fb09020a82eb52。

GetPlaylistForUser 只要求播放列表本身可见。OpenAccess 加上 HasParentalAllowedChild(会跳过允许标签检查)就足够了。已修补的 Items 路由是对照组:它仍然会进行过滤。

机密性(实验环境已验证)

方法路径权限
GET/Videos/{itemId}/stream?static=true私有媒体字节。没有 [Authorize]。 StreamingHelpers 在没有用户的情况下执行 GetItemById<BaseItem>(id)。实验:未认证返回 200,1142 字节,响应体中包含见证字符串 JELLYFIN-PLAYLIST-ITEMIDS-WITNESS。
GET/Audio/{itemId}/stream音频的同一接收点。相同的辅助方法,相同的无作用域查找。

已认证的 HLS GET /Videos/{itemId}/master.m3u8 走的是同一条 GetItemById 路径(DynamicHlsController 在类级别带有 [Authorize])。实验验证的是未认证的渐进式流,而非 HLS。

完整性(已关闭)

方法路径权限
POST/Playlists/{id}/Items 以及创建 Ids已关闭。Playlist.GetPlaylistItems 会执行 IsVisible。私有 GUID 会被丢弃,而不会被关联。

保持关闭的相邻攻击面

  • 将私有 GUID 添加到自己的播放列表。
  • InstantMix(用户作用域的 GetItemById(id, user))。
  • Collections(EnableCollectionManagement 默认为 false;FilterLinkedChildrenPerUser)。
  • GHSA-hw73 转码前缀(ValidateTranscodePath 将旧版 HLS 分片保留在转码目录内)。
  • GHSA-9x85 在 Items 上的 userId 冒充(GetUserId 对外来 id 返回 403)。
  • GET /Playlists/{id}/Items 列出私有子项(即已修补的路由;实验 items-filtered=yes)。

没有密码/策略写入。没有插件安装。没有 shell。

在本实验中,仅靠文件夹 ACL(EnabledFolders)并未在 /Items 上隐藏子项。AllowedTags=["lab-public"] 使 IsVisible 将其丢弃。ItemIds 和未认证流不会查询该过滤器。

我是如何发现的

我固定了 jellyfin/jellyfin v12.2(ca0f16eb)。针对 12.0 GHSA 浪潮遗留问题进行了二十次源码排查。GHSA-9x85 让 GetPlaylistItems 过滤子项。我追问 GetPlaylist 是否也获得了同样的 Where。它并没有。流端点从未获得用户作用域的 GetItemById。

错误方向:将 EnabledFolders 视为 Items 的隐藏机制。影片的 IsVisible 是家长控制/标签,而非文件夹 ACL。实验必须设置 AllowedTags,才能让已修补的 Items 路由返回空。那是对照组。遗留问题并不使用它。

实验

git clone https://github.com/abraxas/jellyfin-playlist-itemids
cd jellyfin-playlist-itemids
python3 jellyfin-playlist-itemids-Abraxas-Labs.py

或:

cd lab
./run.sh

仅针对 http://127.0.0.1:18800。镜像 jellyfin/jellyfin:12.2。run.sh 会生成两个极小的 mp4 文件(PrivateA 作为见证文件名,PublicB 作为占位文件)。向导会创建 labadmin、两个文件夹,然后创建 labuser,其配置为 EnableAllFolders=false、EnabledFolders=PublicB、AllowedTags=["lab-public"]。管理员将私有影片放入一个公开播放列表。仅限回环地址。仅用于见证。需要 Docker 和 ffmpeg 来生成种子文件。

SUCCESS JELLYFIN-PLAYLIST-ITEMIDS items-filtered=yes itemids-leak=yes unauth-stream=200 openAccess=yes playlist=e4798134497195ff4733dde62428e8d8 private=a2bf95146e44897be6fb09020a82eb52 witness-in-stream=yes witness-in-playlist-json=yes JELLYFIN-PLAYLIST-ITEMIDS-WITNESS

复现:python3 jellyfin-playlist-itemids-Abraxas-Labs.py。

修复

使用 IsVisible(user) 过滤 ItemIds,与 GetPlaylistItems 保持一致。将流 GetItemById 限定到某个用户,或在 VideosController.GetVideoStream(以及对应的音频接口)上添加 [Authorize]。

参考资料

  • github.com/jellyfin/jellyfin 标签 v12.2 提交 ca0f16eb7c195f720a1493ed469a27c4657db0c6
  • PlaylistsController.GetPlaylist(:163-182)· GetPlaylistItems(:524-541)
  • Playlist.GetManageableItems · CreatePlaylistDto.IsPublic
  • StreamingHelpers · VideosController.GetVideoStream
  • 附近已修补(非此 GET):GHSA-9x85-gx46-6522 播放列表 Items userId IDOR
  • 同一固定版本:jellyfin-suggestions-idor · jellyfin-svg-gzip · jellyfin-ffmpeg-colonslash
  • 系列文章:Jellyfin 12.2 leftovers
  • CWE-639 · CWE-862

许可证

GNU Affero GPL v3.0。参见 LICENSE。仅限回环实验环境。不提供任何担保。

下载工具