
Jellyfin Server 12.2 - Élevée - Distante après un dépôt .strm - Injection d'arguments FFmpeg - EncodingUtils -i résidu de GHSA-wwwm
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · jellyfin-ffmpeg-colonslash
Classe : injection d'arguments FFmpeg
Portée : distante après l'implantation d'un .strm dans une bibliothèque (auteur d'un dossier média scanné, puis flux non authentifié)
Jellyfin Server v12.2 (ca0f16eb7c195f720a1493ed469a27c4657db0c6) - Jellyfin. Image jellyfin/jellyfin:12.2.
GHSA-wwwm-px48-fpvq / PR 17685 ont ajouté EscapeProcessArgument sur l'argv de conversion et sur la branche -i file:. Le protocole non-File enveloppe toujours le chemin brut entre guillemets sans cet échappement (EncodingUtils.cs:14-71). ManagedFileSystem.IsPathFile est faux pour un :// qui n'est pas file://. TranscodeManager construit toujours ProcessStartInfo.Arguments sous forme d'une seule chaîne.
Un .strm de bibliothèque scanné dont la première ligne est une URL http contenant " est classé Http. Uri.TryCreate accepte cette URL. Un GET /Videos/{id}/stream non authentifié (sans static) démarre ffmpeg. Le journal du lab est :
-i "http://127.0.0.1/a" JELLYFIN-FFMPEG-COLONSLASH-WITNESS "x"
Le contrôle LabControl.mkv reste un seul argument : -i file:"/media/movies/LabControl.mkv".
Un nom de fichier POSIX contenant :// n'atteint pas ce sink. Le slash ne peut pas faire partie d'un nom de fichier. La plante de labo a://b"…"x.mkv est stockée sous la forme /media/movies/a:/b"…"x.mkv et emprunte la branche File échappée. Ne signalez pas de variante de nom de fichier avec deux-points-slash. Je ne prétends pas à une RCE par DLL de plugin. Le labo ne prouve que la séparation des argv.
Reliquat #4 de la série Jellyfin 12.2 leftovers.
| ID | pas encore de CVE |
| Classe | Injection d'arguments FFmpeg (CWE-88) |
| Portée | Distante après une plante .strm dans une bibliothèque, puis un flux non authentifié |
| CWE | CWE-88 |
| CVSS | Élevé : 7.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:N |
| Produit | Jellyfin Server |
| Affecté | v12.2 (ca0f16eb) image jellyfin/jellyfin:12.2 |
| Auth | écrivain de bibliothèque pour la plante ; le flux est non authentifié |
| Licence | GNU Affero GPL v3.0 |
| Labo | 127.0.0.1 uniquement |
Même modèle de plante que GHSA-wwwm : écrire un .strm dans un dossier média scanné (partage NAS / Samba / invité). Ensuite, quiconque peut ouvrir une connexion TCP vers le serveur peut faire GET /Videos/{id}/stream sans Authorization et sans static. C'est l'ensemble complet des privilèges. Rien dans cette liste n'est une RCE par shell ou par DLL de plugin.
| Axe | Méthode + chemin | Accorde | Provenance |
|---|---|---|---|
| Intégrité / argv | GET /Videos/{id}/stream non authentifié après une plante .strm dans une bibliothèque | Arguments ffmpeg supplémentaires hors des guillemets de -i | Prouvé en labo. Journal TranscodeManager |
| Reconnaissance | idem plus -vf drawtext=textfile= | Octets de fichiers de l'hôte dans le transcodage | Gadget déduit ; non exécuté |
| Intégrité | -attach / -dump_attachment | Écriture avec l'UID jellyfin | Déduit ; chargement de plugin non démontré |
| RCE | non revendiqué | - | - |
ProcessBuilder. Pas de RCE par DLL de plugin. L'ancienne chaîne GHSA-866x est historique et n'est pas montrée ici.:// devient un répertoire (a:) plus un fichier. Le Path canonique ne contient pas ://, il emprunte donc la branche -i file: échappée.level de GHSA-jh22 est fermé..strm locaux / file:// sont abandonnés (ProbeProvider ne conserve que http / https / rtsp / rtp).EncoderAppPath ne peut pas être défini via l'API de configuration d'encodage..strm d'envoi de sous-titres (GHSA-j2hf) reste fermé.J'ai épinglé jellyfin/jellyfin v12.2. Vingt recherches dans le code source, puis quatre labos indépendants en boucle locale. La PR 17685 a échappé l'argv de conversion et le -i file:. Les wrappers Http / rtsp ont été laissés en "%s". La première plante que j'ai essayée était un nom de fichier POSIX contenant ://. Cette plante est un répertoire. Le reliquat qui se déclenche est un .strm dont l'URL contient déjà :// et ".
Fausse piste, dans cet ordre : traiter le raccourci path.Contains("://") de GetFileInputArgument comme un bug de nom de fichier. Le slash est un séparateur. La branche File échappe déjà. La branche non-File ne le fait pas.
Voisins sur cet épinglage : jellyfin-suggestions-idor, jellyfin-svg-gzip, jellyfin-playlist-itemids.
Client en boucle locale : jellyfin-ffmpeg-colonslash-Abraxas-Labs.py. Pile : lab/ (docker-compose.yml, poc.py, run.sh). Labo autorisé uniquement. Il communique avec la boucle locale.
python3 jellyfin-ffmpeg-colonslash-Abraxas-Labs.py
Ou :
cd lab
./run.sh
Ciblez uniquement http://127.0.0.1:18810. Image jellyfin/jellyfin:12.2. Projet Compose jellyfin-ffmpeg-colonslash. Témoin JELLYFIN-FFMPEG-COLONSLASH-WITNESS.
poc.py écrit LabControl.mkv (contrôle, un seul -i file:"...") et LabPlant.strm dont l'URL est http://127.0.0.1/a" JELLYFIN-FFMPEG-COLONSLASH-WITNESS "x. Un GET /Videos/{id}/stream non authentifié (sans static) journalise la rupture de guillemet. Dernière ligne :
SUCCESS jellyfin-ffmpeg-colonslash argv-split=yes plant-i=quote-break control-id=f603a52f649bcf822b333c4d5f21cc86 plant-id=d7aabf0935bb524e1667b1ff9bb945d9 JELLYFIN-FFMPEG-COLONSLASH-WITNESS
Appeler EscapeProcessArgument sur chaque branche GetInputArgument, y compris Http et rtsp. Conserver l'enveloppement, mais échapper par guillemets la chaîne interne comme le fait déjà la branche file:.