Skip to content

Commit a240618

Browse files
committed
generate the new rendered markdown
1 parent 8160291 commit a240618

File tree

1 file changed

+67
-15
lines changed

1 file changed

+67
-15
lines changed

csharp/ql/src/Security Features/CWE-022/TaintedPath.md

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
# Uncontrolled data used in path expression
22
Accessing paths controlled by users can allow an attacker to access unexpected resources. This can result in sensitive information being revealed or deleted, or an attacker being able to influence behavior by modifying unexpected files.
33

4-
Paths that are naively constructed from data controlled by a user may contain unexpected special characters, such as "..". Such a path may potentially point to any directory on the file system.
4+
Paths that are naively constructed from data controlled by a user may be absolute paths, or may contain unexpected special characters such as "..". Such a path could point anywhere on the file system.
55

66

77
## Recommendation
8-
Validate user input before using it to construct a file path. Ideally, follow these rules:
8+
Validate user input before using it to construct a file path.
9+
10+
Common validation methods include checking that the normalized path is relative and does not contain any ".." components, or checking that the path is contained within a safe folder. The method you should use depends on how the path is used in the application, and whether the path should be a single path component.
11+
12+
If the path should be a single path component (such as a file name), you can check for the existence of any path separators ("/" or "\\"), or ".." sequences in the input, and reject the input if any are found.
13+
14+
Note that removing "../" sequences is *not* sufficient, since the input could still contain a path separator followed by "..". For example, the input ".../...//" would still result in the string "../" if only "../" sequences are removed.
15+
16+
Finally, the simplest (but most restrictive) option is to use an allow list of safe patterns and make sure that the user input matches one of these patterns.
917

10-
* Do not allow more than a single "." character.
11-
* Do not allow directory separators such as "/" or "\\" (depending on the file system).
12-
* Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to ".../...//" the resulting string would still be "../".
13-
* Use a whitelist of known good patterns.
14-
* Sanitize potentially tainted paths using `HttpRequest.MapPath`.
1518

1619
## Example
17-
In the first example, a file name is read from a `HttpRequest` and then used to access a file. However, a malicious user could enter a file name which is an absolute path - for example, "/etc/passwd". In the second example, it appears that the user is restricted to opening a file within the "user" home directory. However, a malicious user could enter a filename which contains special characters. For example, the string "../../etc/passwd" will result in the code reading the file located at "/home/\[user\]/../../etc/passwd", which is the system's password file. This file would then be sent back to the user, giving them access to all the system's passwords.
20+
In this example, a user-provided file name is read from a HTTP request and then used to access a file and send it back to the user. However, a malicious user could enter a file name anywhere on the file system, such as "/etc/passwd" or "../../../etc/passwd".
1821

1922

2023
```csharp
@@ -26,16 +29,65 @@ public class TaintedPathHandler : IHttpHandler
2629
{
2730
public void ProcessRequest(HttpContext ctx)
2831
{
29-
String path = ctx.Request.QueryString["path"];
32+
String filename = ctx.Request.QueryString["path"];
3033
// BAD: This could read any file on the filesystem.
31-
ctx.Response.Write(File.ReadAllText(path));
34+
ctx.Response.Write(File.ReadAllText(filename));
35+
}
36+
}
37+
38+
```
39+
If the input should only be a file name, you can check that it doesn't contain any path separators or ".." sequences.
40+
3241

33-
// BAD: This could still read any file on the filesystem.
34-
ctx.Response.Write(File.ReadAllText("/home/user/" + path));
42+
```csharp
43+
using System;
44+
using System.IO;
45+
using System.Web;
46+
47+
public class TaintedPathHandler : IHttpHandler
48+
{
49+
public void ProcessRequest(HttpContext ctx)
50+
{
51+
String filename = ctx.Request.QueryString["path"];
52+
// GOOD: ensure that the filename has no path separators or parent directory references
53+
if (filename.Contains("..") || filename.Contains("/") || filename.Contains("\\"))
54+
{
55+
ctx.Response.StatusCode = 400;
56+
ctx.Response.StatusDescription = "Bad Request";
57+
ctx.Response.Write("Invalid path");
58+
return;
59+
}
60+
ctx.Response.Write(File.ReadAllText(filename));
61+
}
62+
}
63+
64+
```
65+
If the input should be within a specific directory, you can check that the resolved path is still contained within that directory.
66+
67+
68+
```csharp
69+
using System;
70+
using System.IO;
71+
using System.Web;
72+
73+
public class TaintedPathHandler : IHttpHandler
74+
{
75+
public void ProcessRequest(HttpContext ctx)
76+
{
77+
String filename = ctx.Request.QueryString["path"];
78+
79+
string publicFolder = Path.GetFullPath("/home/" + user + "/public");
80+
string filePath = Path.GetFullPath(Path.Combine(publicFolder, filename));
3581

36-
// GOOD: MapPath ensures the path is safe to read from.
37-
string safePath = ctx.Request.MapPath(path, ctx.Request.ApplicationPath, false);
38-
ctx.Response.Write(File.ReadAllText(safePath));
82+
// GOOD: ensure that the path stays within the public folder
83+
if (!filePath.StartsWith(publicFolder + Path.DirectorySeparatorChar))
84+
{
85+
ctx.Response.StatusCode = 400;
86+
ctx.Response.StatusDescription = "Bad Request";
87+
ctx.Response.Write("Invalid path");
88+
return;
89+
}
90+
ctx.Response.Write(File.ReadAllText(filename));
3991
}
4092
}
4193

0 commit comments

Comments
 (0)