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
脆弱性分析ウェブアプリケーション悪用データ流出情報収集ウェブセキュリティペネトレーションテスト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 により、2人目のユーザーもプレイリストを閲覧できます)。未認証の GET /Videos/{id}/stream には [Authorize] がありません。StreamingHelpers はユーザーなしで GetItemById を読み込みます。

公開プレイリストを閲覧できるユーザーは、ItemIds からプライベートな子要素の GUID を読み取り、トークンなしでファイルをストリーミングできます。

IDCVE 未割当
クラスIDOR(GHSA-9x85 の残存であるプレイリスト ItemIds、続いて未認証ストリーム)
到達範囲リモート(公開プレイリストを閲覧できる任意のユーザー)
CWECWE-639, CWE-862
CVSSHigh: 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
認証プレイリスト GET には認証が必要、ストリームには不要
ライセンスGNU Affero GPL v3.0
ラボ127.0.0.1:18800 のみ

Jellyfin 12.2 leftovers の残存 #3。残存 #1(最重要): jellyfin-suggestions-idor。同じピン: jellyfin-svg-gzip · jellyfin-ffmpeg-colonslash。

攻撃者ができること

被害者と攻撃者は、ライブラリが重複しない(子供向けと大人向け、または隠しフォルダ)同一サーバー上の2ユーザーです。被害者がプライベートな映画を公開プレイリストに追加します。ボディ作成時の IsPublic はデフォルトで true であるため、これは共有ではなく通常のケースです。攻撃者は制限付きアカウントでログインし、プレイリストオブジェクトを読み取り、Authorization ヘッダーなしでファイルを取得します。

これは攻撃者が割り当てられていないライブラリ内のメディアの GUID、そしてストリーム経由の完全なファイルです。プレイリストタイトルの列挙ではありません。追加/作成は依然として非表示アイテムを除外します。

偵察(ラボで実証済み)

メソッドパス権限
GET/Playlists/{playlistId}可視プレイリストの子 GUID(GetManageableItems() からの ItemIds、子要素に 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 バイト、本文に witness 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))。
  • コレクション(EnableCollectionManagement はデフォルト false、FilterLinkedChildrenPerUser)。
  • GHSA-hw73 のトランスコードプレフィックス(ValidateTranscodePath はレガシー HLS セグメントをトランスコードディレクトリ内に留める)。
  • GHSA-9x85 の Items における userId なりすまし(GetUserId は外部の id に対して 403 を返す)。
  • プライベートな子要素の GET /Playlists/{id}/Items 一覧表示(パッチ済みのルート。ラボでは items-filtered=yes)。

パスワード/ポリシーの書き込みなし。プラグインのインストールなし。シェルなし。

このラボでは、フォルダ ACL(EnabledFolders)だけでは /Items 上の子要素を隠せなかった。AllowedTags=["lab-public"] を設定すると IsVisible がそれを破棄した。ItemIds と未認証ストリームはそのフィルターを参照しない。

発見の経緯

私は jellyfin/jellyfin v12.2(ca0f16eb)を固定した。12.0 の GHSA 波の残骸に対して 20 回のソース探索を行った。GHSA-9x85 は GetPlaylistItems に子要素をフィルタリングすることを教えた。私は GetPlaylist にも同じ Where が付いたのかを問うた。付いていなかった。ストリームエンドポイントはユーザースコープの GetItemById を決して受け取らなかった。

誤った方向: EnabledFolders を Items の隠蔽とみなしたこと。ムービーの IsVisible はペアレンタル/タグによるものであり、フォルダ ACL ではない。ラボでは、パッチ済みの Items ルートが空になるように AllowedTags を設定する必要があった。それが対照である。残骸はそれを使用しない。

ラボ

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 は2つの小さな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。

修正

GetPlaylistItems に合わせて、ItemIds を IsVisible(user) でフィルタリングします。ストリーム 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 を参照してください。ループバックラボ専用です。保証はありません。

ツールをダウンロード