{"cve": [{"lastseen": "2022-03-23T13:40:45", "description": "Jellyfin is a Free Software Media System. In Jellyfin before version 10.7.1, with certain endpoints, well crafted requests will allow arbitrary file read from a Jellyfin server's file system. This issue is more prevalent when Windows is used as the host OS. Servers that are exposed to the public Internet are potentially at risk. This is fixed in version 10.7.1. As a workaround, users may be able to restrict some access by enforcing strict security permissions on their filesystem, however, it is recommended to update as soon as possible.", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "MEDIUM", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "NONE", "integrityImpact": "NONE", "privilegesRequired": "LOW", "baseScore": 6.5, "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", "version": "3.1", "userInteraction": "NONE"}, "impactScore": 3.6}, "published": "2021-03-23T20:15:00", "type": "cve", "title": "CVE-2021-21402", "cwe": ["CWE-22"], "bulletinFamily": "NVD", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "NONE", "integrityImpact": "NONE", "baseScore": 4.0, "vectorString": "AV:N/AC:L/Au:S/C:P/I:N/A:N", "version": "2.0", "accessVector": "NETWORK", "authentication": "SINGLE"}, "impactScore": 2.9, "acInsufInfo": false, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-21402"], "modified": "2021-03-27T02:16:00", "cpe": [], "id": "CVE-2021-21402", "href": "https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2021-21402", "cvss": {"score": 4.0, "vector": "AV:N/AC:L/Au:S/C:P/I:N/A:N"}, "cpe23": []}], "githubexploit": [{"lastseen": "2021-12-10T15:21:28", "description": "#CVE-2021-21402 Jellyfin\u4efb\u610f\u6587\u4ef6\u8bfb\u53d6 \n\n\u6f0f\u6d1e\u7b80\u4ecb\n\njellyfin\u662f\u4e00\u4e2a\u81ea\u7531\u7684\u8f6f\u4ef6\u5a92\u4f53\u7cfb\u7edf\uff0c\u7528\u4e8e\u63a7\u5236...", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "MEDIUM", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "NONE", "integrityImpact": "NONE", "baseScore": 6.5, "privilegesRequired": "LOW", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", "userInteraction": "NONE", "version": "3.1"}, "impactScore": 3.6}, "published": "2021-04-15T15:32:39", "type": "githubexploit", "title": "Exploit for Path Traversal in Jellyfin", "bulletinFamily": "exploit", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "NONE", "integrityImpact": "NONE", "baseScore": 4.0, "vectorString": "AV:N/AC:L/Au:S/C:P/I:N/A:N", "version": "2.0", "accessVector": "NETWORK", "authentication": "SINGLE"}, "acInsufInfo": false, "impactScore": 2.9, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-21402"], "modified": "2021-10-24T07:20:40", "id": "11F37628-699D-5923-ADFD-BEC25F3FDA9E", "href": "", "cvss": {"score": 4.0, "vector": "AV:N/AC:L/Au:S/C:P/I:N/A:N"}, "privateArea": 1}, {"lastseen": "2022-02-10T03:54:41", "description": "# CVE-2021-21402\nJellyfin\u7cfb\u7edf\u5b58\u5728\u4efb\u610f\u6587\u4ef6\u8bfb\u53d6\u6f0f\u6d1e\u3002\n\n\n## \u6f0f\u6d1e\u7f16\u53f7\n\nCVE-2021-214...", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "MEDIUM", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "NONE", "integrityImpact": "NONE", "baseScore": 6.5, "privilegesRequired": "LOW", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", "userInteraction": "NONE", "version": "3.1"}, "impactScore": 3.6}, "published": "2021-04-08T07:41:40", "type": "githubexploit", "title": "Exploit for Path Traversal in Jellyfin", "bulletinFamily": "exploit", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "NONE", "integrityImpact": "NONE", "baseScore": 4.0, "vectorString": "AV:N/AC:L/Au:S/C:P/I:N/A:N", "version": "2.0", "accessVector": "NETWORK", "authentication": "SINGLE"}, "acInsufInfo": false, "impactScore": 2.9, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-21402"], "modified": "2022-02-10T01:59:03", "id": "B155D8FC-65C7-58BE-A3C8-9CB1B24153F1", "href": "", "cvss": {"score": 4.0, "vector": "AV:N/AC:L/Au:S/C:P/I:N/A:N"}, "privateArea": 1}, {"lastseen": "2021-12-10T15:22:12", "description": "# CVE-2021-21402-J...", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "MEDIUM", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "NONE", "integrityImpact": "NONE", "baseScore": 6.5, "privilegesRequired": "LOW", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", "userInteraction": "NONE", "version": "3.1"}, "impactScore": 3.6}, "published": "2021-04-09T08:54:55", "type": "githubexploit", "title": "Exploit for Path Traversal in Jellyfin", "bulletinFamily": "exploit", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "NONE", "integrityImpact": "NONE", "baseScore": 4.0, "vectorString": "AV:N/AC:L/Au:S/C:P/I:N/A:N", "version": "2.0", "accessVector": "NETWORK", "authentication": "SINGLE"}, "acInsufInfo": false, "impactScore": 2.9, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-21402"], "modified": "2021-04-10T03:10:17", "id": "AF1D074D-495F-5872-9EA2-7443D7FFAC25", "href": "", "cvss": {"score": 4.0, "vector": "AV:N/AC:L/Au:S/C:P/I:N/A:N"}, "privateArea": 1}], "seebug": [{"lastseen": "2021-07-24T15:44:03", "description": "# GHSL-2021-050: Unauthenticated abritrary file read in Jellyfin - CVE-2021-21402\n\n[Jaroslav Lobacevski](https://github.com/jarlob)\n\n## Coordinated Disclosure Timeline\n\n- 2021-03-19: Issue reported to maintainers.\n- 2021-03-22: Version 10.7.1 with fixes was released.\n\n## Summary\n\nJellyfin allows unauthenticated arbitrary file read.\n\n## Product\n\nJellyfin\n\n## Tested Version\n\nThe latest 10.7.0 and older\n\n## Details\n\n### Issue 1: Unauthenticated arbitrary file read in `/Audio/itemId/hls/segmentId/stream.mp3` and `/Audio/itemId/hls/segmentId/stream.aac`\n\nBoth the `/Audio/{Id}/hls/{segmentId}/stream.mp3` and `/Audio/{Id}/hls/{segmentId}/stream.aac` routes allow unauthenticated [1] arbitrary file read on Windows. It is possible to set the `{segmentId}` part of the route to a relative or absolute path using the Windows path separator `\\` (`%5C` when URL encoded). Initially, it may seem like an attacker would only be able to read files ending with `.mp3` and `.aac` [2]. However, by using a trailing slash in the URL path it is possible to make `Path.GetExtension(Request.Path)` return an empty extension, thus obtaining full control of the resulting file path. The `itemId` doesn\u2019t matter as it is not used. The issue is not limited to Jellyfin files as it allows reading any file from the file system.\n\n```\n// Can't require authentication just yet due to seeing some requests come from Chrome without full query string\n// [Authenticated] // [1]\n[HttpGet(\"Audio/{itemId}/hls/{segmentId}/stream.mp3\", Name = \"GetHlsAudioSegmentLegacyMp3\")]\n[HttpGet(\"Audio/{itemId}/hls/{segmentId}/stream.aac\", Name = \"GetHlsAudioSegmentLegacyAac\")]\n//...\npublic ActionResult GetHlsAudioSegmentLegacy([FromRoute, Required] string itemId, [FromRoute, Required] string segmentId)\n{\n // TODO: Deprecate with new iOS app\n var file = segmentId + Path.GetExtension(Request.Path); //[2]\n file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file);\n\n return FileStreamResponseHelpers.GetStaticFileResult(file, MimeTypes.GetMimeType(file)!, false, HttpContext);\n}\n```\n\nThe following request for example would download the `jellyfin.db` database with passwords from the server:\n\n```\nGET /Audio/anything/hls/..%5Cdata%5Cjellyfin.db/stream.mp3/ HTTP/1.1\n```\n\n#### Impact\n\nThis issue may lead to unauthorized access to the system especially when Jellyfin is [configured to be accessible from the Internet](https://jellyfin.org/docs/general/networking/index.html#running-jellyfin-behind-a-reverse-proxy).\n\n### Issue 2: Unauthenticated arbitrary file read in `/Videos/Id/hls/PlaylistId/SegmentId.SegmentContainer`\n\nThe `/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.{SegmentContainer}` route allows unauthenticated [1] arbitrary file read on Windows. It is possible to set the `{SegmentId}.{SegmentContainer}` part of the route to a relative or absolute path using the Windows path separator `\\` (`%5C` when URL encoded). The `SegmentId` and file extension from `Path` are concatenated [2]. The resulting `file` is used as the second parameter to `Path.Combine` [3]. However, if the second parameter is an absolute path, the first parameter to `Path.Combine` is ignored and the resulting path is just the absolute path `file`.\n\nA pre-requisite for the attack is that the `jellyfin/transcodes` directory contains at least one `.m3u8` file [4] (i.e. some user started streaming a video or it is left there since the last stream). The `itemId` doesn\u2019t matter as it is not used and `PlaylistId` must be a substring of the `m3u8` file [5]. It can be just `m` as it is always in the `*.m3u8` file name.\n\n```\n// Can't require authentication just yet due to seeing some requests come from Chrome without full query string\n// [Authenticated] //[1]\n[HttpGet(\"Videos/{itemId}/hls/{playlistId}/{segmentId}.{segmentContainer}\")]\n//...\npublic ActionResult GetHlsVideoSegmentLegacy(\n [FromRoute, Required] string itemId,\n [FromRoute, Required] string playlistId,\n [FromRoute, Required] string segmentId,\n [FromRoute, Required] string segmentContainer)\n{\n var file = segmentId + Path.GetExtension(Request.Path); //[2]\n var transcodeFolderPath = _serverConfigurationManager.GetTranscodePath();\n\n file = Path.Combine(transcodeFolderPath, file); //[3]\n\n var normalizedPlaylistId = playlistId;\n\n var filePaths = _fileSystem.GetFilePaths(transcodeFolderPath);\n // Add . to start of segment container for future use.\n segmentContainer = segmentContainer.Insert(0, \".\");\n string? playlistPath = null;\n foreach (var path in filePaths)\n {\n var pathExtension = Path.GetExtension(path);\n if ((string.Equals(pathExtension, segmentContainer, StringComparison.OrdinalIgnoreCase)\n || string.Equals(pathExtension, \".m3u8\", StringComparison.OrdinalIgnoreCase)) //[4]\n && path.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1) //[5]\n {\n playlistPath = path;\n break;\n }\n }\n\n return playlistPath == null\n ? NotFound(\"Hls segment not found.\")\n : GetFileResult(file, playlistPath);\n}\n```\n\nPoC:\n\n```\nGET /Videos/anything/hls/m/..%5Cdata%5Cjellyfin.db HTTP/1.1\n```\n\n#### Impact\n\nThis issue may lead to unauthorized access to the system especially when Jellyfin is [configured to be accessible from the Internet](https://jellyfin.org/docs/general/networking/index.html#running-jellyfin-behind-a-reverse-proxy).\n\n### Issue 3: Authenticated arbitrary file read in `/Videos/Id/hls/PlaylistId/stream.m3u8`\n\n`/Videos/{Id}/hls/{PlaylistId}/stream.m3u8` allows arbitrary file read on Windows. In this case it requires authentication. It may seem like an attacker would only be able to read files ending with `.m3u8`[1]. However, by using a trailing slash in the URL path it is possible to make `Path.GetExtension(Request.Path)` return an empty extension, thus obtaining full control of the resulting file path. The `itemId` doesn\u2019t matter as it is not used.\n\n```\n[HttpGet(\"Videos/{itemId}/hls/{playlistId}/stream.m3u8\")]\n[Authorize(Policy = Policies.DefaultAuthorization)]\n//...\npublic ActionResult GetHlsPlaylistLegacy([FromRoute, Required] string itemId, [FromRoute, Required] string playlistId)\n{\n var file = playlistId + Path.GetExtension(Request.Path); //[1]\n file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file);\n\n return GetFileResult(file, file);\n}\n```\n\nPoC:\n\n```\nGET /Videos/anything/hls/..%5Cdata%5Cjellyfin.db/stream.m3u8/?api_key=4c5750626da14b0a804977b09bf3d8f7 HTTP/1.1\n```\n\n#### Impact\n\nThis issue may lead to privilege elevation.\n\n### Issue 4: Unauthenticated arbitrary image file read in `/Images/Ratings/theme/name`, `/Images/MediaInfo/theme/name` and `Images/General/name/type`\n\nThe `/Images/Ratings/{theme}/{name}`, `/Images/MediaInfo/{theme}/{name}` and `/Images/General/{name}/{type}` routes allow unauthenticated arbitrary *image* file read on Windows. It is possible to set the `{theme}`[1] or `{name}`[2] part of the route to a relative or absolute path using the Windows path separator `\\` (`%5C` when URL encoded). The route automatically appends the following allowed extensions, so it is only possible to read image files [3]: `.png`, `.jpg`, `.jpeg`, `.tbn`, `.gif`.\n\n```\n[HttpGet(\"MediaInfo/{theme}/{name}\")]\n[AllowAnonymous]\n//...\npublic ActionResult GetMediaInfoImage(\n [FromRoute, Required] string theme,\n [FromRoute, Required] string name)\n{\n return GetImageFile(_applicationPaths.MediaInfoImagesPath, theme, name);\n}\n//...\nprivate ActionResult GetImageFile(string basePath, string theme, string? name)\n{\n var themeFolder = Path.Combine(basePath, theme); //[1]\n if (Directory.Exists(themeFolder))\n {\n var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(themeFolder, name + i)/*[2]*/) //[3]\n .FirstOrDefault(System.IO.File.Exists);\n\n if (!string.IsNullOrEmpty(path) && System.IO.File.Exists(path))\n {\n var contentType = MimeTypes.GetMimeType(path);\n return PhysicalFile(path, contentType);\n }\n }\n```\n\nPoCs to download `c:\\temp\\filename.jpg`:\n\n```\nGET /Images/Ratings/c:%5ctemp/filename HTTP/1.1\nGET /Images/Ratings/..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5ctemp/filename HTTP/1.1\n```\n\n#### Impact\n\nThis issue may lead to unauthorized access to image files especially when Jellyfin is [configured to be accessible from the Internet](https://jellyfin.org/docs/general/networking/index.html#running-jellyfin-behind-a-reverse-proxy).\n\n### Issue 5: Authenticated arbitrary file overwrite in `/Videos/itemId/Subtitles` not limited to Windows\n\n`Videos/{itemId}/Subtitles` allows arbitrary file overwrite by an elevated user. Since it requires administrator permissions, it is not clear if this crosses security boundaries.\n\nPoC:\n\n```\nPOST /Videos/d7634eb0064cce760f3f0bf8282c16cd/Subtitles HTTP/1.1\n...\nX-Emby-Authorization: MediaBrowser DeviceId=\"...\", Version=\"10.7.0\", Token=\"...\"\n...\n\n{\"language\":\".\\\\..\\\\\",\"format\":\".\\\\..\\\\test.bin\",\"isForced\":false,\"data\":\"base64 encoded data\"}\n```\n\n#### Impact\n\nThis issue may lead to post-authenticated arbitrary remote code execution.", "cvss3": {}, "published": "2021-04-02T00:00:00", "type": "seebug", "title": "Jellyfin \u4efb\u610f\u6587\u4ef6\u8bfb\u53d6\u6f0f\u6d1e\uff08CVE-2021-21402\uff09", "bulletinFamily": "exploit", "cvss2": {}, "cvelist": ["CVE-2021-21402"], "modified": "2021-04-02T00:00:00", "id": "SSV:99176", "href": "https://www.seebug.org/vuldb/ssvid-99176", "sourceData": "", "sourceHref": "", "cvss": {"score": 4.0, "vector": "AV:N/AC:L/Au:S/C:P/I:N/A:N"}}], "dsquare": [{"lastseen": "2021-07-28T14:33:45", "description": "Directory traversal vulnerability in Jellyfin\n\nVulnerability Type: File Disclosure", "cvss3": {"exploitabilityScore": 2.8, "cvssV3": {"baseSeverity": "MEDIUM", "confidentialityImpact": "HIGH", "attackComplexity": "LOW", "scope": "UNCHANGED", "attackVector": "NETWORK", "availabilityImpact": "NONE", "integrityImpact": "NONE", "baseScore": 6.5, "privilegesRequired": "LOW", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", "userInteraction": "NONE", "version": "3.1"}, "impactScore": 3.6}, "published": "2021-04-08T00:00:00", "type": "dsquare", "title": "Jellyfin < 10.7.1 Directory Traversal", "bulletinFamily": "exploit", "cvss2": {"severity": "MEDIUM", "exploitabilityScore": 8.0, "obtainAllPrivilege": false, "userInteractionRequired": false, "obtainOtherPrivilege": false, "cvssV2": {"accessComplexity": "LOW", "confidentialityImpact": "PARTIAL", "availabilityImpact": "NONE", "integrityImpact": "NONE", "baseScore": 4.0, "vectorString": "AV:N/AC:L/Au:S/C:P/I:N/A:N", "version": "2.0", "accessVector": "NETWORK", "authentication": "SINGLE"}, "acInsufInfo": false, "impactScore": 2.9, "obtainUserPrivilege": false}, "cvelist": ["CVE-2021-21402"], "modified": "2021-04-08T00:00:00", "id": "E-726", "href": "", "sourceData": "For the exploit source code contact DSquare Security sales team.", "cvss": {"score": 4.0, "vector": "AV:N/AC:L/Au:S/C:P/I:N/A:N"}}]}