Jellyfin Server 12.2 – Hoch – Remote – IDOR – GET /Items/Suggestions omit-userId gibt versteckten Bibliothekspfad und IDs preis
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · jellyfin-suggestions-idor
Jellyfin Server 12.2 – Jellyfin
Klasse: IDOR. Reichweite: Remote (jeder authentifizierte Nicht-Admin).
GET /Items/Suggestions ist nur [Authorize]. Wenn userId weggelassen wird, setzt SuggestionsController.GetSuggestions user = null und ruft niemals RequestHelpers.GetUserId auf. InternalItemsQuery(null) ruft nicht SetUser auf. LibraryManager.GetItemsResult überspringt AddUserToQuery. new DtoOptions() enthält ItemFields.Path. GetBaseItemDtos(..., user: null) überspringt IsVisible.
GHSA-9x85 lehrte GetUserId (Weglassen führt zu Claims; eine fremde GUID ergibt 403). ItemsController.GetItems verwendet es immer. Suggestions nicht. Das Legacy-GET /Users/{userId}/Suggestions hat immer eine Route-GUID, daher geht dieser Verwandte durch GetUserId.
Ein eingeschränktes Konto gibt Titel, IDs, Übersichten, Provider-IDs und Dateisystem-Pfad für Bibliotheken aus, denen es nicht zugewiesen ist. Diese GUIDs spielen bei unauthentifiziertem GET /Videos/{id}/stream.
| ID | noch keine CVE |
| CWE | CWE-639 / CWE-862 |
| CVSS | Hoch: 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| Produkt | Jellyfin Server |
| Betroffen | v12.2 (ca0f16eb7c195f720a1493ed469a27c4657db0c6), Image jellyfin/jellyfin:12.2 |
| Auth | authentifiziert (jeder Nicht-Admin, einschließlich eines Kinder-/versteckte-Bibliothek-Kontos) |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1:18790 |
Überbleibsel Nr. 1 von Jellyfin 12.2 leftovers. Gleicher Pin, andere Pakete: jellyfin-svg-gzip (GHSA-cf3c-Überbleibsel gzip data:image/png), jellyfin-playlist-itemids (GHSA-9x85-Überbleibsel ItemIds + unauthentifizierter Stream), jellyfin-ffmpeg-colonslash (GHSA-wwwm-Überbleibsel .strm-URL-Anführungszeichen). Dieses Paket ist dasjenige, das die versteckte Bibliothek ausgibt.
Jeder authentifizierte Nicht-Admin, einschließlich eines Kinder-/versteckte-Bibliothek-/MaxParentalRating-Kontos. Benötigt ein normales Benutzertoken. Kein Admin, kein API-Schlüssel. Er ändert keine Passwörter. Er erzeugt keine Admin-Rechte. Er inventarisiert Bibliotheken, denen er nicht zugewiesen wurde, einschließlich Dateisystem-Pfad, und spielt dann diese GUIDs ab.
Privilegientabelle (vollständig). Gleiche Messlatte wie Signal-Server Dropwizard admin: Methode + Pfad, was dieser Aufruf gewährt, Recon vs. Integrität vs. Verfügbarkeit, im Lab nachgewiesen vs. abgeleitet, angrenzende Oberfläche, die geschlossen bleibt.
| Achse | Methode + Pfad | Gewährt | Provenienz |
|---|---|---|---|
| Recon | GET /Items/Suggestions ohne userId (optional limit / mediaType / type) | Nicht eingegrenzte rekursive Elementliste: Name, Id, Overview, Provider-IDs, Dateisystem-Pfad, Bild-Metadaten von Bibliotheken, denen der Aufrufer nicht zugewiesen ist, einschließlich Ordnern, die nur einem versteckten Benutzer zugewiesen sind. Ordner-ACL, Altersfreigabe und erlaubte Tags werden nicht angewendet. | Im Labor nachgewiesen. Eingeschränkter labuser (EnableAllFolders=false, EnabledFolders=PublicB nur): GET /Items witness=0; Suggestions witness=1 |
| Recon | Dasselbe mit ausgelassenem limit | InternalItemsQuery.Limit bleibt ungesetzt; das Repository gibt die vollständige Treffermenge zurück (gesamte Elementtabelle, zufällige Reihenfolge) | Quelle (SuggestionsController.cs:70-95) |
| Recon | unauth GET /Videos/{itemId}/stream mit einer GUID aus dieser Liste | Bytes dieser Datei als jellyfin-UID | Quelle (VideosController hat kein Klassen-[Authorize]; StreamingHelpers GetItemById ohne Benutzer). Stream im verwandten Leftover jellyfin-playlist-itemids gelabbt, nicht in diesem Pack |
| Integrität | keine bei Suggestions | Kein Passwort-, Policy-, Favoriten- oder Session-Schreibzugriff | Geschlossen |
| Verfügbarkeit | keine bei Suggestions | Kein DoS über die gewöhnlichen Abfragekosten hinaus | Geschlossen |
Bleibt bei diesem Pin geschlossen
| Achse | Methode + Pfad | Warum es geschlossen ist |
|---|---|---|
| Recon | GET /Items?userId= und GET /Items?parentId=<hiddenFolder> | Immer GetUserId + IsVisible (ItemsController.cs:265, 342-350) |
| Recon | GET /Playlists/{id}/Items?userId= | GetUserId (PlaylistsController.cs:524). GHSA-9x85-Klasse, gepatcht |
| Recon | GET /Items/Suggestions?userId=<other> | Fremde GUID trifft weiterhin GetUserId und liefert 403 für einen Nicht-Admin. Im Labor nachgewiesen (impersonate-403=yes) |
| Recon | Legacy GET /Users/{userId}/Suggestions | Route-GUID ist erforderlich, daher wird doch GetUserId aufgerufen |
| Integrität | POST /Users/Password?userId= | AssertCanUpdateUser |
| Integrität | POST /Users/{id}/Policy | RequiresElevation |
| Integrität | Geräte, Sitzungen, AddAdditionalUser | nur Elevation oder eigene Sitzung |
| Recon | GET /Users / GET /Users/{id} | UserDto + Policy (Ordner-GUIDs, Admin-Bit), nicht Bibliotheksinhalte oder Hashes. Haushalts-Enum, nicht dieses Leftover |
Ich behaupte nicht Plugin-DLL-RCE, eine Reverse Shell oder Passwortdiebstahl. Der Dump ist der Katalog (und Path) der Bibliotheken, denen der Aufrufer nicht zugewiesen wurde. Das Stream-by-GUID-Follow-on ist seit Langem bestehendes Jellyfin-HTML5/DLNA-Verhalten; dieses Leftover ist das, was die IDs aufzählt.
v12.2 schloss die GHSA-Welle von 12.0. Ich blieb trotzdem auf diesem Tag und las jede userId-Abfrage neben RequestHelpers.GetUserId. Items verwendet sie immer. Suggestions verzweigt: leere userId -> user = null, nie GetUserId. Das ist das Leftover.
run.sh legt zwei Filmbibliotheken an (PrivateA mit dem Witness im Namen, PublicB), schließt den Wizard ab, erstellt labuser mit EnableAllFolders=false und EnabledFolders=PublicB nur und vergleicht dann GET /Items mit GET /Items/Suggestions.
Bereits festgehaltene Irrwege: GET /Items als Leck zu behandeln (es ist eingegrenzt); Suggestions?userId=<admin> als Leck zu behandeln (403); die Legacy-Route /Users/{userId}/Suggestions als Lücke zu behandeln (sie hat eine GUID, also ruft sie GetUserId auf); unauth stream als Bug dieses Packs zu bezeichnen (verwandtes Leftover); eine Reverse Shell. Theater.