Harden remaining path-construction sinks against traversal
This commit is contained in:
@@ -5,6 +5,7 @@ using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Api.Attributes;
|
||||
using Jellyfin.Api.Helpers;
|
||||
using Jellyfin.Extensions;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.MediaEncoding;
|
||||
@@ -63,8 +64,7 @@ public class HlsSegmentController : BaseJellyfinApiController
|
||||
var file = string.Concat(segmentId, Path.GetExtension(Request.Path.Value.AsSpan()));
|
||||
var transcodePath = _serverConfigurationManager.GetTranscodePath();
|
||||
file = Path.GetFullPath(Path.Combine(transcodePath, file));
|
||||
var fileDir = Path.GetDirectoryName(file);
|
||||
if (string.IsNullOrEmpty(fileDir) || !fileDir.StartsWith(transcodePath, StringComparison.InvariantCulture))
|
||||
if (!PathHelper.IsContainedIn(transcodePath, file))
|
||||
{
|
||||
return BadRequest("Invalid segment.");
|
||||
}
|
||||
@@ -89,8 +89,7 @@ public class HlsSegmentController : BaseJellyfinApiController
|
||||
var file = string.Concat(playlistId, Path.GetExtension(Request.Path.Value.AsSpan()));
|
||||
var transcodePath = _serverConfigurationManager.GetTranscodePath();
|
||||
file = Path.GetFullPath(Path.Combine(transcodePath, file));
|
||||
var fileDir = Path.GetDirectoryName(file);
|
||||
if (string.IsNullOrEmpty(fileDir) || !fileDir.StartsWith(transcodePath, StringComparison.InvariantCulture)
|
||||
if (!PathHelper.IsContainedIn(transcodePath, file)
|
||||
|| Path.GetExtension(file.AsSpan()).Equals(".m3u8", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return BadRequest("Invalid segment.");
|
||||
@@ -144,8 +143,7 @@ public class HlsSegmentController : BaseJellyfinApiController
|
||||
var transcodeFolderPath = _serverConfigurationManager.GetTranscodePath();
|
||||
|
||||
file = Path.GetFullPath(Path.Combine(transcodeFolderPath, file));
|
||||
var fileDir = Path.GetDirectoryName(file);
|
||||
if (string.IsNullOrEmpty(fileDir) || !fileDir.StartsWith(transcodeFolderPath, StringComparison.InvariantCulture))
|
||||
if (!PathHelper.IsContainedIn(transcodeFolderPath, file))
|
||||
{
|
||||
return BadRequest("Invalid segment.");
|
||||
}
|
||||
|
||||
@@ -125,7 +125,13 @@ public class ImageController : BaseJellyfinApiController
|
||||
{
|
||||
// Handle image/png; charset=utf-8
|
||||
var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
|
||||
var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username);
|
||||
var userConfigurationDirectoryPath = _serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath;
|
||||
var userDataPath = Path.Combine(userConfigurationDirectoryPath, user.Username);
|
||||
if (!PathHelper.IsContainedIn(userConfigurationDirectoryPath, userDataPath))
|
||||
{
|
||||
return BadRequest("Invalid user.");
|
||||
}
|
||||
|
||||
if (user.ProfileImage is not null)
|
||||
{
|
||||
await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false);
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Api.Attributes;
|
||||
using Jellyfin.Extensions;
|
||||
using Jellyfin.Extensions.Json;
|
||||
using MediaBrowser.Common.Api;
|
||||
using MediaBrowser.Common.Plugins;
|
||||
@@ -228,8 +229,8 @@ public class PluginsController : BaseJellyfinApiController
|
||||
|
||||
if (!string.IsNullOrEmpty(plugin.Manifest.ImagePath))
|
||||
{
|
||||
var imagePath = Path.Combine(plugin.Path, plugin.Manifest.ImagePath);
|
||||
if (!System.IO.File.Exists(imagePath))
|
||||
var imagePath = Path.GetFullPath(Path.Combine(plugin.Path, plugin.Manifest.ImagePath));
|
||||
if (!PathHelper.IsContainedIn(plugin.Path, imagePath) || !System.IO.File.Exists(imagePath))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
@@ -893,7 +893,7 @@ namespace Jellyfin.Server.Implementations.Users
|
||||
|
||||
internal static void ThrowIfInvalidUsername(string name)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(name) && ValidUsernameRegex().IsMatch(name))
|
||||
if (!string.IsNullOrWhiteSpace(name) && ValidUsernameRegex().IsMatch(name) && name != "." && name != "..")
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ namespace Jellyfin.Server.Implementations.Tests.Users
|
||||
[InlineData(" thishasaspaceatthestart")]
|
||||
[InlineData(" thishasaspaceatbothends ")]
|
||||
[InlineData(" this has a space at both ends and inbetween ")]
|
||||
[InlineData(".")]
|
||||
[InlineData("..")]
|
||||
public void ThrowIfInvalidUsername_WhenInvalidUsername_ThrowsArgumentException(string username)
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => UserManager.ThrowIfInvalidUsername(username));
|
||||
|
||||
Reference in New Issue
Block a user