Skip to main content

Unverifiable files

Need

Ensuring verifiability of files in the repository

Context

  • Usage of Java for building robust and scalable applications
  • Usage of javax.servlet for building Java web applications
  • Usage of java.io for input and output operations in Java programming

Description

Non compliant code

import javax.servlet.*;
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 = Paths.get(filePart.getSubmittedFileName()).getFileName().toString();
InputStream fileContent = filePart.getInputStream();
File file = new File("/uploads/" + fileName);
Files.copy(fileContent, file.toPath());
}
}

The above Java servlet is vulnerable to unverifiable files vulnerability. The servlet is designed to handle file uploads from a user. When a file is uploaded, the servlet retrieves the file from the request, extracts the file name and the content, and then saves the file to a specified directory.

The vulnerability lies in the fact that the servlet does not verify if the content of the file matches its extension. This means that a user can upload a file with an extension .jpg, but the actual content of the file could be malicious executable code.

Not verifying the file content against its extension can lead to several security risks including:

  • Code Execution: If the application later uses these files and interprets them based on their extension, it might inadvertently execute malicious code.
  • Content Spoofing: The application's users can be tricked into opening a file expecting one type of content, while the file actually contains a different type of content.
  • System Crashes: If the application expects a file of a certain format and tries to process a file with the same extension but different content, it can cause the application to crash.

In this code, the vulnerability could be exploited if a user uploads a file with an image extension (like .jpg or .png), but the file is actually a Java .class file containing malicious code. If this file is later used by the application and interpreted as an image file, the malicious code could be executed causing harm to the system.

Steps

  • Validate the file extension before saving it to the server.
  • Use a whitelist approach to only allow specific file extensions that are considered safe.
  • Implement server-side file type verification to ensure that the file content matches its extension.
  • Consider using a secure file storage solution or database instead of saving files directly to the server.
  • Implement proper access controls and permissions to restrict unauthorized access to the uploaded files.
  • Regularly update and patch the server and libraries used to prevent known vulnerabilities.

Compliant code

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.nio.file.*;
import java.util.*;

public class FileUploadServlet extends HttpServlet {
private static final Set<String> ALLOWED_FILE_EXTENSIONS = new HashSet<>(Arrays.asList("jpg", "png", "txt")); // Add more safe file extensions as needed

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Part filePart = request.getPart("file");
String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString();
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();

// Validate file extension
if (!ALLOWED_FILE_EXTENSIONS.contains(fileExtension)) {
throw new ServletException("Invalid file extension");
}

InputStream fileContent = filePart.getInputStream();

// Verify file content
// This is a simple example, you may need a more complex logic based on your needs
if (fileExtension.equals("txt") && !fileContent.markSupported()) {
throw new ServletException("Invalid file content");
}

File file = new File("/uploads/" + fileName);
Files.copy(fileContent, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
}

The updated code now includes a whitelist of allowed file extensions. When a file is uploaded, the servlet first extracts the file extension and checks if it is in the allowed list. If the file extension is not allowed, a ServletException is thrown.

The file content is also verified to match its extension. In this example, if the file is a text file, we check if the content is markable, which is a simple way to verify that the content is text. If the content does not match the file extension, a ServletException is thrown.

The file is then saved to the server using Files.copy(), with the StandardCopyOption.REPLACE_EXISTING option to overwrite any existing file with the same name. This is a simple way to handle file name collisions, but you may need a more complex logic based on your needs.

Please note that this is a basic example and may not cover all possible file types and content verification methods. Depending on your specific needs, you may need to implement more complex file type verification and handle other potential issues such as file size limit, file name collisions, and security permissions.

References