Skip to main content

Excessive privileges - Access Mode

Need

Restrict access privileges to system files and directories

Context

  • Usage of Java 8 for developing applications with enhanced features and performance improvements
  • Usage of HttpServletRequest for handling HTTP requests in Java Servlets
  • Usage of java.io.File for file input/output operations
  • Usage of FileInputStream for reading data from a file in Java
  • Usage of java.io.OutputStream for writing data to an output stream

Description

Non compliant code

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

public class VulnerableServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String path = request.getParameter("file");
File file = new File(path);
if (file.exists()) {
response.setContentType("text/plain");
response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
try (FileInputStream fis = new FileInputStream(file);
OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[1024];
int b;
while ((b = fis.read(buffer)) != -1) {
os.write(buffer, 0, b);
}
}
}
}
}

The above code represents a servlet that is vulnerable to excessive privileges due to its access mode. This servlet is designed to serve files from the server's file system to the client. The client specifies the file they want to download by providing a file path as a parameter in their HTTP GET request.

The vulnerability lies in the fact that the servlet does not check the permissions of the file before serving it to the client. It simply checks if the file exists, and if it does, it serves the file to the client. This means that any file on the server's file system that is readable by the servlet can be downloaded by the client, regardless of whether the client should have access to that file or not.

For example, if the server's file system contains sensitive files that are readable by the servlet but should not be accessible to clients (e.g., configuration files containing passwords), a client could download these files by simply providing the correct file path in their request. This would be a serious security vulnerability, as it could lead to unauthorized access to sensitive information.

Furthermore, the servlet uses a FileInputStream to read the file, and an OutputStream to write the file to the response. These streams are not closed in a finally block or by using try-with-resources, which could lead to resource leaks if an exception is thrown while the streams are open.

Steps

  • Limit the access mode of the system files or directories to the minimum required permissions.
  • Validate and sanitize the 'file' parameter received from the user to prevent directory traversal attacks.
  • Implement proper error handling in case the file does not exist or cannot be accessed.
  • Consider implementing access control mechanisms to restrict access to sensitive files or directories.
  • Regularly review and update the access mode of system files and directories to ensure they are not overly permissive.

Compliant code

import javax.servlet.http.*;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class SecureServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String path = request.getParameter("file");

// Validate and sanitize the 'file' parameter to prevent directory traversal attacks
Path filePath = Paths.get(path).normalize().toAbsolutePath();
if (!filePath.startsWith("/base/directory/path")) {
throw new SecurityException("Invalid file path");
}

File file = filePath.toFile();
if (file.exists() && file.isFile()) {
// Limit the access mode of the system files or directories to the minimum required permissions
Files.setPosixFilePermissions(filePath, PosixFilePermissions.fromString("r--r-----"));

response.setContentType("text/plain");
response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
try (FileInputStream fis = new FileInputStream(file);
OutputStream os = response.getOutputStream()) {
byte[] buffer = new byte[1024];
int b;
while ((b = fis.read(buffer)) != -1) {
os.write(buffer, 0, b);
}
}
} else {
// Implement proper error handling in case the file does not exist or cannot be accessed
throw new FileNotFoundException("File does not exist");
}
}
}

The above code fixes the vulnerability by implementing the following steps:

  1. Limit the access mode of the system files or directories to the minimum required permissions: This is done using the Files.setPosixFilePermissions method, which sets the file permissions to read-only for the owner and group, and no permissions for others.

  2. Validate and sanitize the 'file' parameter received from the user to prevent directory traversal attacks: This is done by normalizing and converting the file path to an absolute path, and then checking if it starts with the base directory path. If it doesn't, a SecurityException is thrown.

  3. Implement proper error handling in case the file does not exist or cannot be accessed: This is done by checking if the file exists and is a file (not a directory) before trying to access it. If it doesn't exist or is a directory, a FileNotFoundException is thrown.

Please note that this code does not implement access control mechanisms to restrict access to sensitive files or directories, and it does not regularly review and update the access mode of system files and directories. These steps should be implemented as part of the system's security policy and procedures.

References