...
During this time the canonical path name may have been modified and may no longer be referencing a valid file. The canonical path name can be used to determine if the referenced file name is in a secure directory (see FIO00-J. Do not operate on files in shared directories). If the referenced file is in a secure directory, then by definition, an attacker cannot tamper with it, and cannot exploit the race condition.
This rule is a specific instance of IDS01-J. Normalize strings before validating them.
...
This noncompliant code example accepts a file path as a command line argument and uses the File.getAbsolutePath() method to obtain the absolute file path. This method It also uses the isInSecureDir() method defined in FIO00-J. Do not operate on files in shared directories to ensure that the file is in a secure directory. But it does not resolve file links or eliminate equivalence errors.
| Code Block | ||
|---|---|---|
| ||
public static void main(String[] args) {
File f = new File("/tmphome/me/" + args[0]);
String absPath = f.getAbsolutePath();
if (!isInSecureDir(Paths.get( absPath))) {
throw new IllegalArgumentException();
}
if (!validate(absPath)) { // Validation
throw new IllegalArgumentException();
}
}
|
| Wiki Markup |
|---|
The application intends to restrict the user from operating on files outside the {{/tmphome/me}} directory and uses a {{validate()}} method to enforce this condition. The path name validation can be easily circumvented. For example, if the directory were not seucre, an attacker who can create symbolic links in {{/tmphome/me}} can cause the program to pass validation checks by supplying the unresolved path. All file operations performed are reflected in the file pointed to by the symbolic link. If the string {{filename}} is passed as {{argv\[0\]}} and {{/tmphome/me/filename}} is a symbolic link that refers to {{/dirname/filename}} the validation passes. This is because the root directory of the compiled path name is still {{/tmphome/me}}, but the operations are carried out on the file {{/dirname/filename}}. |
...
| Code Block | ||
|---|---|---|
| ||
public static void main(String[] args) throws IOException {
File f = new File("/tmphome/me/" + args[0]);
String canonicalPath = f.getCanonicalPath();
if (!isInSecureDir(Paths.get(canonicalPath))) {
throw new IllegalArgumentException();
}
if (!validate(canonicalPath)) { // Validation
throw new IllegalArgumentException();
}
}
|
...
A comprehensive way of handling this issue is to grant the application the permissions to operate only on files present within the intended directory — /tmphome/me in this example. This compliant solution specifies the absolute path of the program in its security policy file, and grants java.io.FilePermission with target /tmphome/me and actions read and write.
| Code Block | ||
|---|---|---|
| ||
grant codeBase "file:/home/programpath/" {
permission java.io.FilePermission "/tmphome/me", "read, write";
};
|
See rule ENV02-J. Create a secure sandbox using a Security Manager for additional information on using security managersThis solution does require that /home/me must be a secure directory, and associated code should check this requirement and abort if it is not met.
Noncompliant Code Example
...
Noncompliant Code Example
The following code examples assume that /img and /img/java are secure directories.
This noncompliant code example attempts to mitigate the issue by using the File.getCanonicalPath() method, which fully resolves the argument and constructs a canonicalized path. For example, the path /img/../etc/passwd resolves to /etc/passwd. Validation without canonicalization remains insecure because the user can specify files outside the intended directory.
...
| Code Block | ||
|---|---|---|
| ||
// All files in /img/java can be read
grant codeBase "file:/home/programpath/" {
permission java.io.FilePermission "/img/java", "read";
};
|
See rule ENV02-J. Create a secure sandbox using a Security Manager for additional information on using security managers.
Risk Assessment
Using path names from untrusted sources without first canonicalizing them and then validating them can result in directory traversal and path equivalence vulnerabilities.
...
FIO02-C. Canonicalize path names originating from untrusted sources | ||||
FIO02-CPP. Canonicalize path names originating from untrusted sources | ||||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="8dd8939a5e50f6a0-fd7c6c78-47c8491a-83c2b718-d1ac5de2578ad92fc740a874"><ac:plain-text-body><![CDATA[ | [[MITRE 2009 | AA. Bibliography#MITRE 09]] | [CWE ID 171 | http://cwe.mitre.org/data/definitions/171.html] "Cleansing, Canonicalization, and Comparison Errors"]]></ac:plain-text-body></ac:structured-macro> |
| CWE ID 647 "Use of Non-Canonical URL Paths for Authorization Decisions" |
...
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="af925a6b5681f28c-9058c19f-4d7540c9-9666a12a-e9e7923be933b02c10fe2039"><ac:plain-text-body><![CDATA[ | [[API 2006 | AA. Bibliography#API 06]] | [method getCanonicalPath() | http://java.sun.com/javase/6/docs/api/java/io/File.html#getCanonicalPath()] | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="4dbee4a7bb0ac3ea-6bf4eea0-448c43a1-aa3c92d9-5ec83d8047c352ec5b08d763"><ac:plain-text-body><![CDATA[ | [[Harold 1999 | AA. Bibliography#Harold 99]] |
| ]]></ac:plain-text-body></ac:structured-macro> |
...