Better validate file names

This commit is contained in:
nicolas.dorier 2021-03-19 18:55:07 +09:00
parent fc78eacf8f
commit 73d70aa5e5
No known key found for this signature in database
GPG key ID: 6618763EF09186FE
7 changed files with 39 additions and 2 deletions

View file

@ -3117,6 +3117,22 @@ namespace BTCPayServer.Tests
return name;
}
[Fact(Timeout = TestTimeout)]
[Trait("Fast", "Fast")]
public void CanCheckFileNameValid()
{
var tests = new[]
{
("test.com", true),
("/test.com", false),
("\\test.com", false),
};
foreach(var t in tests)
{
Assert.Equal(t.Item2, t.Item1.IsValidFileName());
}
}
[Fact(Timeout = TestTimeout)]
[Trait("Fast", "Fast")]
public async Task CanCreateSqlitedb()

View file

@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;

View file

@ -117,7 +117,7 @@ namespace BTCPayServer.Controllers
public async Task<IActionResult> UploadPlugin([FromServices] PluginService pluginService,
List<IFormFile> files)
{
foreach (var formFile in files.Where(file => file.Length > 0))
foreach (var formFile in files.Where(file => file.Length > 0).Where(file => file.FileName.IsValidFileName()))
{
await pluginService.UploadPlugin(formFile);
pluginService.InstallPlugin(formFile.FileName.TrimEnd(PluginManager.BTCPayPluginSuffix,

View file

@ -146,6 +146,15 @@ namespace BTCPayServer.Controllers
[HttpPost("server/files/upload")]
public async Task<IActionResult> CreateFile(IFormFile file)
{
if (!file.FileName.IsValidFileName())
{
this.TempData.SetStatusMessageModel(new StatusMessageModel()
{
Message = "Invalid file name",
Severity = StatusMessageModel.StatusSeverity.Error
});
return RedirectToAction(nameof(Files));
}
var newFile = await _FileService.AddFile(file, GetUserId());
return RedirectToAction(nameof(Files), new
{

View file

@ -46,6 +46,11 @@ namespace BTCPayServer
return endpoint != null;
}
public static bool IsValidFileName(this string fileName)
{
return !fileName.ToCharArray().Any(c => Path.GetInvalidFileNameChars().Contains(c));
}
public static bool IsSafe(this LightningConnectionString connectionString)
{
if (connectionString.CookieFilePath != null ||

View file

@ -57,7 +57,11 @@ namespace BTCPayServer.Plugins
throw new Exception("Plugin not found on remote");
}
var filedest = Path.Combine(dest, ext.Name);
if (!ext.Name.IsValidFileName())
{
throw new Exception("Invalid file name");
}
var filedest = Path.Join(dest, ext.Name);
Directory.CreateDirectory(Path.GetDirectoryName(filedest));
new WebClient().DownloadFile(new Uri(ext.DownloadUrl), filedest);
}

View file

@ -30,6 +30,8 @@ namespace BTCPayServer.Storage.Services
var settings = await _SettingsRepository.GetSettingAsync<StorageSettings>();
if (settings is null)
throw new InvalidOperationException("StoreSettings not configured");
if (!file.FileName.IsValidFileName())
throw new InvalidOperationException("Invalid file name");
var provider = GetProvider(settings);
var storedFile = await provider.AddFile(file, settings);