CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

Export to Word

Description

The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.

Extended Description

Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.


ThreatScore

Threat Mapped score: 0.0

Industry: Finiancial

Threat priority: Unclassified


Observed Examples (CVEs)

Related Attack Patterns (CAPEC)


Attack TTPs

N/A

Modes of Introduction

Phase Note
Implementation N/A

Common Consequences

Potential Mitigations

Applicable Platforms


Demonstrative Examples

Intro: The following code could be for a social networking application in which each user's profile information is stored in a separate file. All files are stored in a single directory.

Body: While the programmer intends to access files such as "/users/cwe/profiles/alice" or "/users/cwe/profiles/bob", there is no verification of the incoming user parameter. An attacker could provide a string such as:

my $dataPath = "/users/cwe/profiles"; my $username = param("user"); my $profilePath = $dataPath . "/" . $username; open(my $fh, "<", $profilePath) || ExitError("profile read error: $profilePath"); print "<ul>\n"; while (<$fh>) { print "<li>$_</li>\n"; } print "</ul>\n";

Intro: In the example below, the path to a dictionary file is read from a system property and used to initialize a File object.

Body: However, the path is not validated or modified to prevent it from containing relative or absolute path sequences before creating the File object. This allows anyone who can control the system property to determine what file is used. Ideally, the path should be resolved relative to some kind of application or user home directory.

String filename = System.getProperty("com.domain.application.dictionaryFile"); File dictionaryFile = new File(filename);

Intro: The following code takes untrusted input and uses a regular expression to filter "../" from the input. It then appends this result to the /home/user/ directory and attempts to read the file in the final resulting path.

Body: Since the regular expression does not have the /g global match modifier, it only removes the first instance of "../" it comes across. So an input value such as:

my $Username = GetUntrustedInput(); $Username =~ s/\.\.\///; my $filename = "/home/user/" . $Username; ReadAndSendFile($filename);

Intro: The following code attempts to validate a given input path by checking it against an allowlist and once validated delete the given file. In this specific case, the path is considered valid if it starts with the string "/safe_dir/".

Body: An attacker could provide an input such as this:

String path = getInputPath(); if (path.startsWith("/safe_dir/")) { File f = new File(path); f.delete() }

Intro: The following code demonstrates the unrestricted upload of a file with a Java servlet and a path traversal vulnerability. The action attribute of an HTML form is sending the upload file request to the Java servlet.

Body: When submitted the Java servlet's doPost method will receive the request, extract the name of the file from the Http request header, read the file contents from the request and output the file to the local upload directory.

<form action="FileUploadServlet" method="post" enctype="multipart/form-data"> Choose a file to upload: <input type="file" name="filename"/> <br/> <input type="submit" name="submit" value="Submit"/> </form>

Intro: This script intends to read a user-supplied file from the current directory. The user inputs the relative path to the file and the script uses Python's os.path.join() function to combine the path to the current working directory with the provided path to the specified file. This results in an absolute path to the desired file. If the file does not exist when the script attempts to read it, an error is printed to the user.

Body: However, if the user supplies an absolute path, the os.path.join() function will discard the path to the current working directory and use only the absolute path provided. For example, if the current working directory is /home/user/documents, but the user inputs /etc/passwd, os.path.join() will use only /etc/passwd, as it is considered an absolute path. In the above scenario, this would cause the script to access and read the /etc/passwd file.

import os import sys def main(): filename = sys.argv[1] path = os.path.join(os.getcwd(), filename) try: with open(path, 'r') as f: file_data = f.read() except FileNotFoundError as e: print("Error - file not found") main()

Notes

← Back to CWE list