improve file name and extension validation

This commit is contained in:
sbwalker 2024-08-12 17:02:07 -04:00
parent 515c6402b9
commit 16215847cd

View File

@ -170,6 +170,8 @@ namespace Oqtane.Controllers
if (ModelState.IsValid && folder != null && folder.SiteId == _alias.SiteId) if (ModelState.IsValid && folder != null && folder.SiteId == _alias.SiteId)
{ {
if (_userPermissions.IsAuthorized(User, folder.SiteId, EntityNames.Folder, file.FolderId, PermissionNames.Edit)) if (_userPermissions.IsAuthorized(User, folder.SiteId, EntityNames.Folder, file.FolderId, PermissionNames.Edit))
{
if (HasValidFileExtension(file.Name) && file.Name.IsPathOrFileValid())
{ {
var filepath = _files.GetFilePath(file); var filepath = _files.GetFilePath(file);
if (System.IO.File.Exists(filepath)) if (System.IO.File.Exists(filepath))
@ -187,6 +189,13 @@ namespace Oqtane.Controllers
} }
} }
else else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Name Is Invalid Or Contains Invalid Extension {File}", file.Name);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
file = null;
}
}
else
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Post Attempt {File}", file); _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Post Attempt {File}", file);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
@ -212,6 +221,8 @@ namespace Oqtane.Controllers
if (ModelState.IsValid && file.Folder.SiteId == _alias.SiteId && file.FileId == id && File != null // ensure file exists if (ModelState.IsValid && file.Folder.SiteId == _alias.SiteId && file.FileId == id && File != null // ensure file exists
&& _userPermissions.IsAuthorized(User, file.Folder.SiteId, EntityNames.Folder, File.FolderId, PermissionNames.Edit) // ensure user had edit rights to original folder && _userPermissions.IsAuthorized(User, file.Folder.SiteId, EntityNames.Folder, File.FolderId, PermissionNames.Edit) // ensure user had edit rights to original folder
&& _userPermissions.IsAuthorized(User, file.Folder.SiteId, EntityNames.Folder, file.FolderId, PermissionNames.Edit)) // ensure user has edit rights to new folder && _userPermissions.IsAuthorized(User, file.Folder.SiteId, EntityNames.Folder, file.FolderId, PermissionNames.Edit)) // ensure user has edit rights to new folder
{
if (HasValidFileExtension(file.Name) && file.Name.IsPathOrFileValid())
{ {
if (File.Name != file.Name || File.FolderId != file.FolderId) if (File.Name != file.Name || File.FolderId != file.FolderId)
{ {
@ -238,6 +249,13 @@ namespace Oqtane.Controllers
_logger.Log(LogLevel.Information, this, LogFunction.Update, "File Updated {File}", file); _logger.Log(LogLevel.Information, this, LogFunction.Update, "File Updated {File}", file);
} }
else else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Name Is Invalid Or Contains Invalid Extension {File}", file.Name);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
file = null;
}
}
else
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Put Attempt {File}", file); _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Put Attempt {File}", file);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
@ -289,38 +307,21 @@ namespace Oqtane.Controllers
folder = _folders.GetFolder(FolderId); folder = _folders.GetFolder(FolderId);
} }
var _UploadableFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "UploadableFiles")?.SettingValue;
_UploadableFiles = (string.IsNullOrEmpty(_UploadableFiles)) ? Constants.UploadableFiles : _UploadableFiles;
if (folder != null && folder.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.Edit, folder.PermissionList)) if (folder != null && folder.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.Edit, folder.PermissionList))
{ {
string folderPath = _folders.GetFolderPath(folder);
CreateDirectory(folderPath);
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
{ {
name = url.Substring(url.LastIndexOf("/", StringComparison.Ordinal) + 1); name = url.Substring(url.LastIndexOf("/", StringComparison.Ordinal) + 1);
} }
// check for allowable file extensions
if (!_UploadableFiles.Split(',').Contains(Path.GetExtension(name).ToLower().Replace(".", "")))
{
_logger.Log(LogLevel.Error, this, LogFunction.Create, "File Could Not Be Downloaded From Url Due To Its File Extension {Url}", url);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
return file;
}
if (!name.IsPathOrFileValid()) if (HasValidFileExtension(name) && name.IsPathOrFileValid())
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Create, $"File Could Not Be Downloaded From Url Due To Its File Name Not Allowed {url}");
HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
return file;
}
try try
{ {
string targetPath = Path.Combine(folderPath, name); string folderPath = _folders.GetFolderPath(folder);
CreateDirectory(folderPath);
// remove file if it already exists string targetPath = Path.Combine(folderPath, name);
if (System.IO.File.Exists(targetPath)) if (System.IO.File.Exists(targetPath))
{ {
System.IO.File.Delete(targetPath); System.IO.File.Delete(targetPath);
@ -350,6 +351,13 @@ namespace Oqtane.Controllers
} }
} }
else else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Name Is Invalid Or Contains Invalid Extension {File}", name);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
file = null;
}
}
else
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Download Attempt {FolderId} {Url}", folderid, url); _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Download Attempt {FolderId} {Url}", folderid, url);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
@ -368,21 +376,11 @@ namespace Oqtane.Controllers
return; return;
} }
// Get the UploadableFiles extensions
string _UploadableFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "UploadableFiles")?.SettingValue;
_UploadableFiles = (string.IsNullOrEmpty(_UploadableFiles)) ? Constants.UploadableFiles : _UploadableFiles;
// ensure filename is valid // ensure filename is valid
string token = ".part_"; string token = ".part_";
if (!formfile.FileName.IsPathOrFileValid() || !formfile.FileName.Contains(token)) if (!formfile.FileName.IsPathOrFileValid() || !formfile.FileName.Contains(token) || !HasValidFileExtension(formfile.FileName.Substring(0, formfile.FileName.IndexOf(token))))
{
return;
}
// check for allowable file extensions (ignore token)
var extension = Path.GetExtension(formfile.FileName.Substring(0, formfile.FileName.IndexOf(token))).Replace(".", "");
if (!_UploadableFiles.Split(',').Contains(extension.ToLower()))
{ {
_logger.Log(LogLevel.Error, this, LogFunction.Security, "File Name Is Invalid Or Contains Invalid Extension {File}", formfile.FileName);
return; return;
} }
@ -843,5 +841,12 @@ namespace Oqtane.Controllers
return file; return file;
} }
private bool HasValidFileExtension(string fileName)
{
var _uploadableFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "UploadableFiles")?.SettingValue;
_uploadableFiles = (string.IsNullOrEmpty(_uploadableFiles)) ? Constants.UploadableFiles : _uploadableFiles;
return _uploadableFiles.Split(',').Contains(Path.GetExtension(fileName).ToLower().Replace(".", ""));
}
} }
} }