An absolute path may sometimes contain aliases, shadows, symbolic links and shortcuts as opposed to canonical paths, which refer to actual files or directories that these point to. The process of canonicalizing file names makes it safer to verify a path, directory, or file name by making it easier to compare names.
Noncompliant Code Example
This noncompliant code example accepts the file path as a command line argument. Let argv[0]
be the string java
, where /tmp/java
is a symbolic link that points to another file in some directory of the local file system. On POSIX based systems, the getAbsolutePath()
method includes /tmp/java
(name of the symbolic link) in the path that it returns. An adversary who can create symbolic links can cause the program to pass validation checks but operate on the wrong target file. On Windows and Macintosh systems, this behavior is not observed. The symbolic link is fully resolved on these platforms. This implies implementation defined behavior.
public static void main(String[] args) { File f = new File("/tmp/" + args[0]); String absPath = f.getAbsolutePath(); if(!absPath.equals("/tmp/java")) { // Validation throw new IllegalArgumentException(); } // }
Compliant Solution
This compliant solution uses the getCanonicalPath()
method, introduced in Java 2, because it resolves the aliases, shortcuts or symbolic links consistently, across all platforms. The value of the alias is not included in the returned value. Moreover, relative references like the double period (..) are also removed so that the input is reduced to a canonicalized form before validation is carried out. The getCanonicalPath()
method throws a security exception when used within applets as it reveals too much information about the host machine. The getCanonicalFile()
method behaves like getCanonicalPath()
but returns a new File
object instead of a String
.
public static void main(String[] args) throws IOException { File f = new File("/tmp/" + args[0]); String canonicalPath = f.getCanonicalPath(); if(!canonicalPath.equals("/tmp/java")) { // Validation throw new IllegalArgumentException(); } }
This compliant solution is also compliant with IDS18-J. Prevent against directory traversal attacks.
Risk Assessment
Using path names from untrusted sources without first canonicalizing the filenames may result in operations being carried out on the wrong files.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
FIO00- J |
medium |
unlikely |
medium |
P4 |
L3 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Other Languages
This rule appears in the C Secure Coding Standard as FIO02-C. Canonicalize path names originating from untrusted sources.
This rule appears in the C++ Secure Coding Standard as FIO02-CPP. Canonicalize path names originating from untrusted sources.
References
[[API 06]] method getCanonicalPath()
[[API 06]] method getCanonicalFile()
[[Harold 99]]
[[MITRE 09]] CWE ID 171 "Cleansing, Canonicalization, and Comparison Errors", CWE ID 647 "Use of Non-Canonical URL Paths for Authorization Decisions"
09. Input Output (FIO) 09. Input Output (FIO) FIO01-J. Do not let Runtime.exec() fail or block indefinitely