Skip to main content

External control of file name or path

Need

Prevention of unauthorized access and manipulation of file paths and names

Context

  • Usage of Java 8 for developing applications with enhanced features and performance
  • Usage of javax.servlet-api for Java Servlet development
  • Usage of java.io for input and output operations in Java programming

Description

Non compliant code

import javax.servlet.http.*;
import java.io.*;

public class FileUploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Part filePart = request.getPart("file");
String fileName = filePart.getSubmittedFileName();
InputStream fileContent = filePart.getInputStream();
File file = new File("/uploads/" + fileName);
filePart.write(file.getAbsolutePath());
}
}

The above code represents a servlet that handles file uploads. The servlet receives a file as a part of a multi-part form data POST request. The getPart("file") method is used to retrieve the uploaded file from the request.

The vulnerability lies in the line String fileName = filePart.getSubmittedFileName();. Here, the filename of the uploaded file is directly taken from the user input without any sanitization or validation. This filename is then used to create a new File object and the uploaded file is saved to this location.

The problem here is that a malicious user can manipulate the filename to point to a different directory. For example, they can use relative paths like ../../etc/passwd to overwrite important system files or access restricted directories. This is known as a path traversal attack.

Furthermore, if the application has any functionality that relies on the file that was overwritten, this can lead to further vulnerabilities being exploited. For example, if the application reads from the file and displays the contents to the user, the attacker could potentially view sensitive system information.

In summary, the code is vulnerable because it does not validate or sanitize the filename of the uploaded file, allowing an attacker to control the path to which the file is saved.

Steps

  • Validate and sanitize the file name before using it to construct the file path.
  • Use a secure file storage location that is not accessible by the user.
  • Implement access controls to restrict the types of files that can be uploaded.
  • Implement file extension validation to prevent uploading of malicious files.
  • Consider using a unique identifier for the file name instead of relying on the user-provided name.
  • Implement proper error handling and logging to detect any potential issues.

Compliant code

import javax.servlet.http.*;
import java.io.*;
import java.util.UUID;

public class FileUploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Part filePart = request.getPart("file");
String fileName = filePart.getSubmittedFileName();
String fileExtension = "";

// Get file extension
int i = fileName.lastIndexOf('.');
if (i > 0) {
fileExtension = fileName.substring(i+1);
}

// Validate file extension
if(!fileExtension.equals("jpg") && !fileExtension.equals("png")) {
throw new ServletException("Invalid file type");
}

// Generate a unique identifier for the file name
String uniqueID = UUID.randomUUID().toString();

// Sanitize the file name
fileName = uniqueID + "." + fileExtension;

// Use a secure file storage location that is not accessible by the user
String secureLocation = "/secure/uploads/";

File file = new File(secureLocation + fileName);
filePart.write(file.getAbsolutePath());
}
}

The code above is a secure version of the previous file upload servlet. The changes made to the code are as follows:

  1. File Extension Validation: The file extension is extracted from the original file name and validated. If the file is not a jpg or png, a ServletException is thrown. This prevents the uploading of potentially malicious files.

  2. Unique Identifier for File Name: A unique identifier is generated using UUID.randomUUID().toString(). This identifier is used as the new file name, ensuring that the user-provided name is not used in constructing the file path.

  3. Sanitize the File Name: The file name is sanitized by combining the unique identifier and the validated file extension. This prevents any potential path manipulation.

  4. Secure File Storage Location: The file is saved to a secure location (/secure/uploads/) that is not accessible by the user. This prevents any potential unauthorized access to the uploaded files.

By implementing these changes, the servlet is now secure against external control of file name or path vulnerabilities.

References