Fix disk traversal issue

This commit is contained in:
Neo 2020-10-24 05:06:35 +01:00
parent ceea825fa2
commit d3dc8cf77d
3 changed files with 21 additions and 9 deletions

View File

@ -9,6 +9,7 @@
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.1.8" /> <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.1.8" />
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="3.1.7" /> <PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="3.1.7" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.4" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.4" />
<PackageReference Include="Quartz.AspNetCore" Version="3.2.2" />
<PackageReference Include="RestSharp" Version="106.11.5" /> <PackageReference Include="RestSharp" Version="106.11.5" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" /> <PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="serilog.sinks.console" Version="3.1.1" /> <PackageReference Include="serilog.sinks.console" Version="3.1.1" />

View File

@ -38,13 +38,13 @@ namespace KamihamaWeb.Services
public async Task<DiskCacheItem> Get(string cacheItem, string versionMd5, bool forceOrigin = false) public async Task<DiskCacheItem> Get(string cacheItem, string versionMd5, bool forceOrigin = false)
{ {
// Remember: don't allow directory traversal attacks...
var filename = CryptUtil.CalculateSha256(cacheItem + "?" + versionMd5); var filename = CryptUtil.CalculateSha256(cacheItem + "?" + versionMd5);
var filePath = Path.Combine(CacheDirectory, filename); var filePath = Path.Combine(CacheDirectory, filename);
if (!forceOrigin && cacheItem.StartsWith("scenario/json/general")) if (!forceOrigin && cacheItem.StartsWith("scenario/json/general"))
{ {
var generalJson = Path.Combine(CacheDirectory, cacheItem + versionMd5); var generalJson = Path.Combine(ScenarioCacheDirectory, filename);
if (File.Exists(generalJson)) if (File.Exists(generalJson))
{ {
return new DiskCacheItem() return new DiskCacheItem()
@ -110,7 +110,8 @@ namespace KamihamaWeb.Services
{ {
case StoreType.ScenarioGeneral: case StoreType.ScenarioGeneral:
var md5 = CryptUtil.CalculateMd5Bytes(storeContents); var md5 = CryptUtil.CalculateMd5Bytes(storeContents);
storePath = Path.Combine(CacheDirectory, filepath + md5); var filename = CryptUtil.CalculateSha256(filepath + "?" + md5);
storePath = Path.Combine(ScenarioCacheDirectory, filename);
await File.WriteAllBytesAsync(storePath, storeContents); await File.WriteAllBytesAsync(storePath, storeContents);
break; break;
default: default:

View File

@ -63,6 +63,8 @@ namespace KamihamaWeb.Services
public async Task<bool> UpdateMasterLists() public async Task<bool> UpdateMasterLists()
{ {
Log.Information("Updating master lists."); Log.Information("Updating master lists.");
UpdateIsRunning = true;
var workGamedataAssets = new Dictionary<string, List<GamedataAsset>>(); var workGamedataAssets = new Dictionary<string, List<GamedataAsset>>();
foreach (var assetToMod in ModdedAssetLists) foreach (var assetToMod in ModdedAssetLists)
{ {
@ -78,12 +80,10 @@ namespace KamihamaWeb.Services
workGamedataAssets.Add(assetToMod, masterJson); workGamedataAssets.Add(assetToMod, masterJson);
} }
IsReady = false;
GamedataAssets.Clear();
Log.Information("Configuring master list..."); Log.Information("Configuring master list...");
var postProcessingGeneralScenario = new Dictionary<string, GamedataAsset>(); var postProcessingGeneralScenario = new Dictionary<string, GamedataAsset>();
var newGamedataAssets = new Dictionary<string, Dictionary<string, GamedataAsset>>();
long counterReplace = 0; long counterReplace = 0;
long counterSkip = 0; long counterSkip = 0;
@ -123,7 +123,7 @@ namespace KamihamaWeb.Services
counterNew++; counterNew++;
} }
} }
GamedataAssets.Add(assetType.Key, readyAssets); newGamedataAssets.Add(assetType.Key, readyAssets);
} }
Log.Information($"Finished setting up. {counterReplace} replaced assets, {counterSkip} duplicate assets, {counterNew} new assets, {counterPost} assets for post processing."); Log.Information($"Finished setting up. {counterReplace} replaced assets, {counterSkip} duplicate assets, {counterNew} new assets, {counterPost} assets for post processing.");
@ -135,7 +135,7 @@ namespace KamihamaWeb.Services
var split = asset.Key.Split("/").Last(); var split = asset.Key.Split("/").Last();
var scenario = split[0..^5]; // Trim .json from end var scenario = split[0..^5]; // Trim .json from end
//Log.Debug($"Adding script {scenario}."); //Log.Debug($"Adding script {scenario}.");
GamedataAssets.Add($"asset_scenario_{scenario}", new Dictionary<string, GamedataAsset>() newGamedataAssets.Add($"asset_scenario_{scenario}", new Dictionary<string, GamedataAsset>()
{ {
{scenario,asset.Value} {scenario,asset.Value}
}); });
@ -147,9 +147,13 @@ namespace KamihamaWeb.Services
{ {
var builtJson = await _builder.BuildScenarioGeneralJson(asset.Value, EnglishMasterAssets); var builtJson = await _builder.BuildScenarioGeneralJson(asset.Value, EnglishMasterAssets);
GamedataAssets["asset_main"].Add(builtJson.Path, builtJson); newGamedataAssets["asset_main"].Add(builtJson.Path, builtJson);
} }
IsReady = false;
GamedataAssets = newGamedataAssets;
IsReady = true; IsReady = true;
UpdateIsRunning = false;
return true; return true;
} }
@ -193,6 +197,7 @@ namespace KamihamaWeb.Services
} }
public bool IsReady { get; set; } = false; public bool IsReady { get; set; } = false;
public bool UpdateIsRunning { get; set; } = false;
public long AssetsCurrentVersion { get; set; } public long AssetsCurrentVersion { get; set; }
public Dictionary<string, GamedataAsset> EnglishMasterAssets { get; set; } public Dictionary<string, GamedataAsset> EnglishMasterAssets { get; set; }
public Dictionary<string, Dictionary<string, GamedataAsset>> GamedataAssets { get; set; } public Dictionary<string, Dictionary<string, GamedataAsset>> GamedataAssets { get; set; }
@ -210,6 +215,11 @@ namespace KamihamaWeb.Services
} }
} }
public async Task<bool> RunUpdate()
{
return true;
}
public async Task<string> ProvideJson(string which) public async Task<string> ProvideJson(string which)
{ {
if (which == "asset_config") if (which == "asset_config")