CodeQL documentation

Partial path traversal vulnerability from remote

ID: java/partial-path-traversal-from-remote
Kind: path-problem
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-023
Query suites:
   - java-code-scanning.qls
   - java-security-extended.qls
   - java-security-and-quality.qls

Click to see the query in the CodeQL repository

A common way to check that a user-supplied path SUBDIR falls inside a directory DIR is to use getCanonicalPath() to remove any path-traversal elements and then check that DIR is a prefix. However, if DIR is not slash-terminated, this can unexpectedly allow accessing siblings of DIR.

See also java/partial-path-traversal, which is similar to this query, but may also flag non-remotely-exploitable instances of partial path traversal vulnerabilities.

Recommendation

If the user should only access items within a certain directory DIR, ensure that DIR is slash-terminated before checking that DIR is a prefix of the user-provided path, SUBDIR. Note, Java’s getCanonicalPath() returns a non-slash-terminated path string, so a slash must be added to DIR if that method is used.

Example

In this example, the if statement checks if parent.getCanonicalPath() is a prefix of dir.getCanonicalPath(). However, parent.getCanonicalPath() is not slash-terminated. This means that users that supply dir may be also allowed to access siblings of parent and not just children of parent, which is a security issue.

public class PartialPathTraversalBad {
    public void example(File dir, File parent) throws IOException {
        if (!dir.getCanonicalPath().startsWith(parent.getCanonicalPath())) {
            throw new IOException("Invalid directory: " + dir.getCanonicalPath());
        }
    }
}

In this example, the if statement checks if parent.getCanonicalPath() + File.separator is a prefix of dir.getCanonicalPath(). Because parent.getCanonicalPath().toPath() is indeed slash-terminated, the user supplying dir can only access children of parent, as desired.

public class PartialPathTraversalGood {
    public void example(File dir, File parent) throws IOException {
        if (!dir.getCanonicalPath().toPath().startsWith(parent.getCanonicalPath().toPath())) {
            throw new IOException("Invalid directory: " + dir.getCanonicalPath());
        }
    }
}

References

  • © GitHub, Inc.
  • Terms
  • Privacy