|
1 | | -FIXME: add a description |
2 | | - |
3 | | -// If you want to factorize the description uncomment the following line and create the file. |
4 | | -//include::../description.adoc[] |
| 1 | +Using `PhysicalFileResult` with dynamic file paths can expose ASP.NET applications to path traversal attacks. An attacker could inject specially crafted values, such as `../`, to access files outside the intended directory. |
5 | 2 |
|
6 | 3 | == Why is this an issue? |
7 | 4 |
|
8 | | -FIXME: remove the unused optional headers (that are commented out) |
| 5 | +When `PhysicalFileResult` is instantiated or its `FileName` property is set with a value that is not a static string, the application may become vulnerable to path injection. If this path ever becomes user-controlled, a malicious user could manipulate the path to read arbitrary files from the file system, potentially exposing sensitive data like configuration files or credentials. |
| 6 | + |
| 7 | +=== What is the potential impact? |
| 8 | + |
| 9 | +An attacker exploiting this vulnerability could read any file accessible to the application process. This may include: |
9 | 10 |
|
10 | | -//=== What is the potential impact? |
| 11 | +* Application configuration files containing secrets |
| 12 | +* Source code or binaries |
| 13 | +* General system files which may help an attacker gain further access to the system |
11 | 14 |
|
12 | 15 | == How to fix it |
13 | | -//== How to fix it in FRAMEWORK NAME |
| 16 | + |
| 17 | +In general, it is recommended to use File Providers to access files. This approach ensures that file access is restricted to a specific root directory and prevents path traversal attacks. It is generally good practice to use this rather than using the `PhysicalFileResult` class (even together with own sanitization logic). |
14 | 18 |
|
15 | 19 | === Code examples |
16 | 20 |
|
17 | 21 | ==== Noncompliant code example |
18 | 22 |
|
19 | 23 | [source,csharp,diff-id=1,diff-type=noncompliant] |
20 | 24 | ---- |
21 | | -FIXME |
| 25 | +public class FileController : Controller |
| 26 | +{ |
| 27 | + public IActionResult Download(string filename) |
| 28 | + { |
| 29 | + string path = Path.Combine("/var/www/files", filename); |
| 30 | + return new PhysicalFileResult(path, "application/octet-stream"); // Noncompliant |
| 31 | + } |
| 32 | +} |
22 | 33 | ---- |
23 | 34 |
|
24 | 35 | ==== Compliant solution |
25 | 36 |
|
26 | 37 | [source,csharp,diff-id=1,diff-type=compliant] |
27 | 38 | ---- |
28 | | -FIXME |
| 39 | +public class FileController : Controller |
| 40 | +{ |
| 41 | + private readonly IFileProvider _fileProvider = |
| 42 | + new PhysicalFileProvider("/var/www/files"); |
| 43 | +
|
| 44 | + public IActionResult Download(string filename) |
| 45 | + { |
| 46 | + IFileInfo fileInfo = _fileProvider.GetFileInfo(filename); |
| 47 | + if (!fileInfo.Exists) |
| 48 | + { |
| 49 | + return NotFound(); |
| 50 | + } |
| 51 | + return File(fileInfo.CreateReadStream(), "application/octet-stream"); |
| 52 | + } |
| 53 | +} |
29 | 54 | ---- |
30 | 55 |
|
31 | | -//=== How does this work? |
| 56 | +=== How does this work? |
32 | 57 |
|
33 | | -//=== Pitfalls |
| 58 | +`PhysicalFileProvider` restricts file access to a designated root directory. When `GetFileInfo` is called, the provider automatically prevents path traversal by ensuring the resolved path remains within the root directory. This built-in protection eliminates the risk of directory escape attacks. |
34 | 59 |
|
35 | | -//=== Going the extra mile |
| 60 | +== Resources |
36 | 61 |
|
| 62 | +=== Documentation |
37 | 63 |
|
38 | | -//== Resources |
39 | | -//=== Documentation |
40 | | -//=== Articles & blog posts |
41 | | -//=== Conference presentations |
42 | | -//=== Standards |
43 | | -//=== External coding guidelines |
44 | | -//=== Benchmarks |
| 64 | +* Microsoft Learn - https://learn.microsoft.com/en-us/aspnet/core/fundamentals/file-providers[File Providers in ASP.NET Core] |
| 65 | +* OWASP - https://owasp.org/www-community/attacks/Path_Traversal[Path Traversal] |
0 commit comments