Skip to content

Commit 955e614

Browse files
committed
Add documentation of the Partial Path Traversal vuln
1 parent b5ca2c3 commit 955e614

3 files changed

Lines changed: 50 additions & 21 deletions

File tree

java/ql/src/Security/CWE/CWE-023/PartialPathTraversal.qhelp

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,56 @@
33
"qhelp.dtd">
44
<qhelp>
55
<overview>
6-
<p>Accessing paths controlled by users can allow an attacker to access unexpected resources. This
7-
can result in sensitive information being revealed or deleted, or an attacker being able to influence
8-
behavior by modifying unexpected files.</p>
6+
<p> User inputted file paths can often pose security risks if a program does not correctly handle them. In particular, if a user
7+
is meant to access files under a certain directory but does not enters a path under that directory, they can gain access to
8+
(and potentially modify/delete) unexpected, possibly sensitive resources. </p>
99

10-
<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>
10+
<p> Suppose a program is to only accept paths that point to files/folders within directory <code>DIR</code>.
11+
To ensure that a user inputted path, say <code>SUBDIR</code>, is a subdirectory of <code>DIR</code>, the
12+
program verifies that <code>DIR</code> is a prefix of <code>SUBDIR</code>.
13+
However, this check is not satisfactory: unless <code>DIR</code> is not slash-terminated,
14+
<code>SUBDIR</code> may be allowed to also access siblings of <code>DIR</code> and not
15+
just children of <code>DIR</code>, which is a security issue. </p>
1216

1317
</overview>
1418
<recommendation>
1519

16-
<p>Validate user input before using it to construct a file path. Ideally, follow these rules:</p>
17-
18-
<ul>
19-
<li>Do not allow more than a single "." character.</li>
20-
<li>Do not allow directory separators such as "/" or "\" (depending on the file system).</li>
21-
<li>Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to
22-
".../...//" the resulting string would still be "../".</li>
23-
<li>Ideally use a whitelist of known good patterns.</li>
24-
</ul>
20+
<p>If the user should only access items within a certain directory <code>DIR</code>, first ensure that <code>DIR</code> is slash-terminated,
21+
and then proceed (as normal) to verify that <code>DIR</code> is a prefix of the user-provided path, <code>SUBDIR</code>. Note, Java's <code>getCanonicalPath()</code>
22+
returns a <b>non</b>-slash-terminated path string, so a <code>"/"</code> must be added to <code>DIR</code> if that method is used. </p>
2523

2624
</recommendation>
2725
<example>
2826

29-
<p>In this example, a file name is read from a <code>java.net.Socket</code> and then used to access a file in the
30-
user's home directory and send it back over the socket. However, a malicious user could enter a file name which contains special
31-
characters. For example, the string "../../etc/passwd" will result in the code reading the file located at
32-
"/home/[user]/../../etc/passwd", which is the system's password file. This file would then be sent back to the user,
33-
giving them access to all the system's passwords.</p>
27+
<p>
28+
29+
30+
In this example, the <code>if</code> statement checks if <code>parent.getCanonicalPath()</code>
31+
is a prefix of <code>dir.getCanonicalPath()</dir>. However, <code>parent.getCanonicalPath()</code> is
32+
not slash-terminated. So, the user that supplies <code>dir</code> may be allowed to access siblings of <code>parent</code>
33+
and not just children of <code>parent</code>, which is a security issue.
34+
35+
</p>
36+
37+
<sample src="PartialPathTraversalBad.java" />
38+
39+
<p>
40+
41+
In this example, the <code>if</code> statement checks if <code>parent.getCanonicalPath() + File.separator </code>
42+
is a prefix of <code>dir.getCanonicalPath()</code>. Because <code>parent.getCanonicalPath() + File.separator</code> is
43+
indeed slash-terminated, the user supplying <code>dir</code> can only access children of
44+
<code>parent</code>, as desired.
45+
46+
</p>
3447

35-
<sample src="PartialPathTraversal.java" />
48+
<sample src="PartialPathTraversalGood.java" />
3649

3750
</example>
3851
<references>
3952

4053
<li>
4154
OWASP:
42-
<a href="https://owasp.org/www-community/attacks/Path_Traversal">Path Traversal</a>.
55+
<a href="https://owasp.org/www-community/attacks/Path_Traversal">Partial Path Traversal</a>.
4356
</li>
4457

4558
</references>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public class PartialPathTraversalBad {
2+
public void esapiExample(File dir, File parent) throws IOException {
3+
if (!dir.getCanonicalPath().startsWith(parent.getCanonicalPath())) {
4+
throw new IOException("Invalid directory: " + dir.getCanonicalPath());
5+
}
6+
}
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import java.io.File;
2+
3+
public class PartialPathTraversalBad {
4+
public void esapiExample(File dir, File parent) throws IOException {
5+
if (!dir.getCanonicalPath().startsWith(parent.getCanonicalPath() + File.separator)) {
6+
throw new IOException("Invalid directory: " + dir.getCanonicalPath());
7+
}
8+
}
9+
}

0 commit comments

Comments
 (0)