Skip to content

GetCombinedStreamAsync > GetRequiredFileInfo exception should be handled gracefully to prevent DDoS #199

@LennardF1989

Description

@LennardF1989

Upon inspecting logs of an Umbraco website, we saw an unhandled exception similar to below occur quite often:

System.IO.FileNotFoundException: No such file exists 202303303/019e3e65.js (mapped from 202303303/019e3e65.js)

File name: '202303303/019e3e65.js'
   at Smidge.InMemory.MemoryCacheFileSystem.GetRequiredFileInfo(String filePath)
   at System.Linq.Enumerable.SelectListPartitionIterator`2.MoveNext()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.ToList()
   at Smidge.Controllers.SmidgeController.GetCombinedStreamAsync(IEnumerable`1 files, BundleContext bundleContext)
   at Smidge.Controllers.SmidgeController.Composite(CompositeFileModel file)

After investigation, this is relatively easy to trigger by taking the URL and purposely including a wrong file-id, for example:
https://domain.tld/sc/598e8198.1234abcd.js.v202303303 where 1234abcd is a non-existing file.

This code currently throws an exception, but is never properly handled, causing a 500:

throw new FileNotFoundException($"No such file exists {fileInfo.PhysicalPath ?? fileInfo.Name} (mapped from {filePath})", fileInfo.PhysicalPath ?? fileInfo.Name);

(This is also the case for other FileSystem types).

This particular line seems to be the reason for the actual 500 happening:

var files = file.ParsedPath.Names.Select(filePath =>
_fileSystem.CacheFileSystem.GetRequiredFileInfo(
$"{file.ParsedPath.CacheBusterValue}/{filePath + file.Extension}"));

GetCombinedStreamAsync tries to do an if-Exists check, but you can't check .Exists on something that is not there. A possible solution instead of throwing an Exception is just logging that it occured, but returning a default FileInfo.

While this particular issue may seem like a non-issue and only occurs when caching is out of sync with the actual smidge files, being able to consistently trigger a 500 can be considered a DDoS vulnerability. As a lot of exceptions in a row will make IIS go into panic mode and restart the website.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions