Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
jellyfin-playlist-itemids — Jellyfin Server 12.2 - Alta - Remota - IDOR - ItemIds de listas de reproducción públicas remanentes de GHSA-9x85, luego transmisión no autenticada | Kitploit
Herramientas/GitHubGitHub/abraxas/jellyfin-playlist-itemids
Análisis de VulnerabilidadesExplotación de Aplicaciones WebExfiltración de DatosRecopilación de InformaciónSeguridad WebPruebas de PenetraciónSeguridad de APIsLabs y Práctica
GitHubabraxas/jellyfin-playlist-itemids

jellyfin-playlist-itemids

Jellyfin Server 12.2 - Alta - Remota - IDOR - ItemIds de listas de reproducción públicas remanentes de GHSA-9x85, luego transmisión no autenticada

Ver Repositorio
3hace 1 díaAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Abraxas Labs - jellyfin-playlist-itemids

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

jellyfin-playlist-itemids

Clase: IDOR Alcance: Remoto (cualquier usuario que pueda ver una lista de reproducción pública)

Jellyfin Server v12.2 (ca0f16eb7c195f720a1493ed469a27c4657db0c6) - Jellyfin

GHSA-9x85 parcheó GET /Playlists/{id}/Items con GetUserId más Where(i => i.Item2.IsVisible(user)). A GET /Playlists/{id} no se le aplicó ese filtro. ItemIds es GetManageableItems() sin IsVisible en los hijos. GetPlaylistForUser solo requiere que la lista de reproducción sea visible.

CreatePlaylistDto.IsPublic tiene como valor predeterminado true. Las listas de reproducción OpenAccess son IsVisible para otros usuarios (HasParentalAllowedChild todavía permite que un segundo usuario vea la lista de reproducción). GET /Videos/{id}/stream sin autenticación no tiene [Authorize]. StreamingHelpers carga GetItemById sin un usuario.

Un usuario que puede ver una lista de reproducción pública lee los GUID de hijos privados desde ItemIds y luego transmite los archivos sin token.

IDaún sin CVE
ClaseIDOR (resto de ItemIds de la lista de reproducción de GHSA-9x85, luego stream sin autenticación)
AlcanceRemoto (cualquier usuario que pueda ver una lista de reproducción pública)
CWECWE-639, CWE-862
CVSSAlto: 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
ProductoJellyfin Server
Afectadov12.2 (ca0f16eb) imagen jellyfin/jellyfin:12.2
Autenticaciónautenticado para el GET de la lista de reproducción; ninguno para el stream
LicenciaGNU Affero GPL v3.0
Laboratoriosolo 127.0.0.1:18800

Resto #3 de Jellyfin 12.2 leftovers. Resto #1 (el más importante): jellyfin-suggestions-idor. Misma versión fijada: jellyfin-svg-gzip · jellyfin-ffmpeg-colonslash.

Qué puede hacer un atacante

La víctima y el atacante son dos usuarios en un mismo servidor con bibliotecas disjuntas (niños vs adultos, o una carpeta oculta). La víctima coloca una película privada en una lista de reproducción pública. IsPublic en la creación del cuerpo tiene como valor predeterminado true, así que ese es el caso habitual, no un recurso compartido. El atacante inicia sesión como una cuenta restringida, lee el objeto de la lista de reproducción y luego obtiene el archivo sin cabecera Authorization.

Se trata de GUID de medios en bibliotecas a las que el atacante no está asignado, y luego el archivo completo mediante stream. No es enumeración de títulos de listas de reproducción. Añadir/crear todavía descarta los elementos no visibles.

Reconocimiento (probado en laboratorio)

MétodoRutaPrivilegio
GET/Playlists/{playlistId}GUID de hijos de una lista de reproducción visible (ItemIds de GetManageableItems(), sin IsVisible en los hijos). También Shares[].UserId / CanEdit (userId de los destinatarios del recurso compartido). Laboratorio: el GET /Playlists/{id}/Items de B vacío; el GET /Playlists/{id} del mismo id listó el GUID privado a2bf95146e44897be6fb09020a82eb52.

GetPlaylistForUser solo requiere que la propia lista de reproducción sea visible. OpenAccess más HasParentalAllowedChild (que omite la comprobación de etiquetas permitidas) es suficiente. La ruta Items parcheada es el control: sigue filtrando.

Confidencialidad (probado en laboratorio)

MétodoRutaPrivilegio
GET/Videos/{itemId}/stream?static=trueBytes de medios privados. Sin [Authorize]. StreamingHelpers hace GetItemById<BaseItem>(id) sin un usuario. Lab: 200 sin autenticación, 1142 bytes, testigo JELLYFIN-PLAYLIST-ITEMIDS-WITNESS en el cuerpo.
GET/Audio/{itemId}/streamMismo sink para audio. Mismo helper, misma búsqueda sin alcance.

El HLS autenticado GET /Videos/{itemId}/master.m3u8 es la misma ruta GetItemById (DynamicHlsController tiene [Authorize] a nivel de clase). El lab ejercitó el stream progresivo sin autenticación, no HLS.

Integridad (cerrado)

MétodoRutaPrivilegio
POST/Playlists/{id}/Items y crear IdsCerrado. Playlist.GetPlaylistItems ejecuta IsVisible. Los GUID privados se descartan, no se enlazan.

Superficie adyacente que permanece cerrada

  • Añadir GUID privados a tu propia playlist.
  • InstantMix (GetItemById(id, user) con alcance de usuario).
  • Colecciones (EnableCollectionManagement por defecto false; FilterLinkedChildrenPerUser).
  • Prefijo de transcodificación GHSA-hw73 (ValidateTranscodePath mantiene los segmentos HLS heredados dentro del directorio de transcodificación).
  • Suplantación de userId de GHSA-9x85 en Items (GetUserId devuelve 403 para un id ajeno).
  • Listado de hijos privados en GET /Playlists/{id}/Items (la ruta parcheada; lab items-filtered=yes).

Sin escritura de contraseña/política. Sin instalación de plugins. Sin shell.

La ACL de carpeta (EnabledFolders) por sí sola no ocultó el hijo en /Items en este lab. AllowedTags=["lab-public"] hizo que IsVisible lo descartara. ItemIds y el stream sin autenticación no consultan ese filtro.

Cómo lo encontré

Fijé jellyfin/jellyfin v12.2 (ca0f16eb). Veinte búsquedas en el código fuente sobre los restos de la oleada de GHSA de la 12.0. GHSA-9x85 enseñó a GetPlaylistItems a filtrar hijos. Pregunté si GetPlaylist recibió el mismo Where. No lo hizo. Los endpoints de stream nunca recibieron un GetItemById con alcance de usuario.

Falso camino: tratar EnabledFolders como el ocultamiento de Items. IsVisible de Movie es parental/etiquetas, no ACL de carpeta. El lab tuvo que establecer AllowedTags para que la ruta parcheada de Items quedara vacía. Ese es el control. El resto no lo usa.

Lab

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

O:

cd lab
./run.sh

Apunta solo a http://127.0.0.1:18800. Imagen jellyfin/jellyfin:12.2. run.sh siembra dos mp4 diminutos (nombre de archivo testigo PrivateA, dummy PublicB). El asistente crea labadmin, ambas carpetas, luego labuser con EnableAllFolders=false, EnabledFolders=PublicB, AllowedTags=["lab-public"]. El administrador coloca la película privada en una lista de reproducción pública. Loopback. Solo testigo. Requiere Docker y ffmpeg para sembrar.

Descargar herramienta