Skip to content

Commit 009d580

Browse files
author
Max Schaefer
committed
Address suggestions from review.
1 parent a46a7fa commit 009d580

File tree

3 files changed

+22
-19
lines changed

3 files changed

+22
-19
lines changed

java/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,28 @@ can result in sensitive information being revealed or deleted, or an attacker be
88
behavior by modifying unexpected files.</p>
99

1010
<p>Paths that are naively constructed from data controlled by a user may contain unexpected special characters,
11-
such as "..". Such a path may potentially point to any directory on the file system.</p>
11+
such as "..". Such a path may potentially point anywhere on the file system.</p>
1212

1313
</overview>
1414
<recommendation>
1515

1616
<p>Validate user input before using it to construct a file path.</p>
1717

18-
<p>The choice of validation depends on the use case.</p>
18+
<p>The choice of validation depends on whether you want to allow the user to specify complex paths with
19+
multiple components that may span multiple folders, or only simple filenames without a path component.</p>
1920

20-
<p>If you want to allow paths spanning multiple folders, a common strategy is to make sure that the constructed
21-
file path is contained within a safe root folder, for example by checking that the path starts with the root folder.
22-
Additionally, you need to ensure that the path does not contain any ".." components, since these would allow
23-
the path to escape the root folder.</p>
21+
<p>In the former case, a common strategy is to make sure that the constructed file path is contained within
22+
a safe root folder, for example by checking that the path starts with the root folder. Additionally,
23+
you need to ensure that the path does not contain any ".." components, since otherwise
24+
even a path that starts with the root folder could be used to access files outside the root folder.</p>
2425

25-
<p>A safer (but more restrictive) option is to use an allow list of safe paths and make sure that
26-
the user input is one of those paths.</p>
26+
<p>In the latter case, if you want to ensure that the user input is interpreted as a simple filename without
27+
a path component, you can remove all path separators ("/" or "\") and all ".." sequences from the input
28+
before using it to construct a file path. Note that it is <i>not</i> sufficient to only remove "../" sequences:
29+
for example, applying this filter to ".../...//" would still result in the string "../".</p>
30+
31+
<p>Finally, the simplest (but most restrictive) option is to use an allow list of safe patterns and make sure that
32+
the user input matches one of these patterns.</p>
2733

2834
</recommendation>
2935
<example>
@@ -34,12 +40,9 @@ such as "/etc/passwd".</p>
3440

3541
<sample src="TaintedPath.java" />
3642

37-
<p>Simply checking that the path is under a trusted location (such as the user's home directory) is not enough,
38-
however, since the path could contain relative components such as "..". For example, the string
39-
"/home/[user]/../../etc/passwd" starts with the user's home directory, but would still result in the code reading
40-
the file located at "/etc/passwd".</p>
41-
42-
<p>To fix this, we check that the user-provided path does not contain ".." and starts with the user's home directory.</p>
43+
<p>Simply checking that the path is under a trusted location (such as a known public folder) is not enough,
44+
however, since the path could contain relative components such as "..". To fix this, we check that the it does
45+
not contain ".." and starts with the public folder.</p>
4346

4447
<sample src="TaintedPathGood.java" />
4548

java/ql/src/Security/CWE/CWE-022/TaintedPathGood.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ public void sendUserFileGood(Socket sock, String user) {
33
new InputStreamReader(sock.getInputStream(), "UTF-8"));
44
String filename = filenameReader.readLine();
55
// GOOD: ensure that the file is in a designated folder in the user's home directory
6-
if (!filePath.contains("..") && filePath.startsWith("/home/" + user + "/public/")) {
7-
BufferedReader fileReader = new BufferedReader(new FileReader(filePath));
6+
if (!filename.contains("..") && filename.startsWith("/home/" + user + "/public/")) {
7+
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
88
String fileLine = fileReader.readLine();
99
while(fileLine != null) {
1010
sock.getOutputStream().write(fileLine.getBytes());

java/ql/test/query-tests/security/CWE-022/semmle/tests/TaintedPath.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ public void sendUserFile(Socket sock, String user) throws IOException {
2121

2222
public void sendUserFileGood(Socket sock, String user) throws IOException {
2323
BufferedReader filenameReader = new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
24-
String filePath = filenameReader.readLine();
24+
String filename = filenameReader.readLine();
2525
// GOOD: ensure that the file is in a designated folder in the user's home directory
26-
if (!filePath.contains("..") && filePath.startsWith("/home/" + user + "/public/")) {
27-
BufferedReader fileReader = new BufferedReader(new FileReader(filePath));
26+
if (!filename.contains("..") && filename.startsWith("/home/" + user + "/public/")) {
27+
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
2828
String fileLine = fileReader.readLine();
2929
while(fileLine != null) {
3030
sock.getOutputStream().write(fileLine.getBytes());

0 commit comments

Comments
 (0)