41
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.
Example Language: Java (Bad)
public class FileUploadServlet extends HttpServlet {
...
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String contentType = request.getContentType();
// the starting position of the boundary header
int ind = contentType.indexOf("boundary=");
String boundary = contentType.substring(ind+9);
String pLine = new String();
String uploadLocation = new String(UPLOAD_DIRECTORY_STRING); //Constant value
// verify that content type is multipart form data
if (contentType != null && contentType.indexOf("multipart/form-data") != -1) {
// extract the filename from the Http header
BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
...
pLine = br.readLine();
String filename = pLine.substring(pLine.lastIndexOf("\\"), pLine.lastIndexOf("\""));
...
// output the file to the local upload directory
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(uploadLocation+filename, true));
for (String line; (line=br.readLine())!=null; ) {
if (line.indexOf(boundary) == -1) {
bw.write(line);
bw.newLine();
bw.flush();
}
} //end of for loop
bw.close();
} catch (IOException ex) {...}
// output successful upload response HTML page
}
// output unsuccessful upload response HTML page
else
{...}
}
...
}
This code does not perform a check on the type of the file being uploaded (CWE-434). This could
allow an attacker to upload any executable file or other file with malicious code.
Additionally, the creation of the BufferedWriter object is subject to relative path traversal (CWE-23).
Since the code does not check the filename that is provided in the header, an attacker can use
"../" sequences to write to files outside of the intended directory. Depending on the executing
environment, the attacker may be able to specify arbitrary files to write to, leading to a wide variety
of consequences, from code execution, XSS (CWE-79), or system crash.
Example 6:
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.
CWE Version 4.14
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
CWE-22: Improper Limitation of a Pathname
to a Restricted Directory ('Path Traversal') 42
Example Language: Python (Bad)
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()
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.
Example Language: Python (Good)
import os
import sys
def main():
filename = sys.argv[1]
path = os.path.normpath(f"{os.getcwd()}{os.sep}{filename}")
try:
with open(path, 'r') as f:
file_data = f.read()
except FileNotFoundError as e:
print("Error - file not found")
main()
The constructed path string uses os.sep to add the appropriate separation character for the given
operating system (e.g. '\' or '/') and the call to os.path.normpath() removes any additional slashes
that may have been entered - this may occur particularly when using a Windows path. By putting
the pieces of the path string together in this fashion, the script avoids a call to os.path.join() and
any potential issues that might arise if an absolute path is entered. With this version of the script,
if the current working directory is /home/user/documents, and the user inputs /etc/passwd, the
resulting path will be /home/user/documents/etc/passwd. The user is therefore contained within the
current working directory as intended.
Observed Examples
Reference Description
CVE-2022-45918 Chain: a learning management tool debugger uses external input to locate
previous session logs (CWE-73) and does not properly validate the given
path (CWE-20), allowing for filesystem path traversal using "../" sequences
(CWE-24)
https://www.cve.org/CVERecord?id=CVE-2022-45918
CVE-2019-20916 Python package manager does not correctly restrict the filename specified in
a Content-Disposition header, allowing arbitrary file read using path traversal
sequences such as "../"
https://www.cve.org/CVERecord?id=CVE-2019-20916
CVE-2022-31503 Python package constructs filenames using an unsafe os.path.join call on
untrusted input, allowing absolute path traversal because os.path.join resets
the pathname to an absolute path that is specified as part of the input.
https://www.cve.org/CVERecord?id=CVE-2022-31503
CVE-2022-24877 directory traversal in Go-based Kubernetes operator app allows accessing
data from the controller's pod file system via ../ sequences in a yaml file
CWE Version 4.14
CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
CWE-22: Improper Limitation of a Pathname
to a Restricted Directory ('Path Traversal')