Skip to main content

Insecure or unset HTTP headers - Accept

Need

Enforcement of secure and restricted HTTP headers

Context

  • Usage of Java 8 for developing applications with enhanced features and performance improvements
  • Usage of javax.servlet-api for building Java web applications with Servlets

Description

Non compliant code

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public void doGet(HttpServletRequest request, HttpServletResponse response) {
String acceptHeader = request.getHeader("Accept");
if (acceptHeader == null || acceptHeader.equals("*/*")) {
// process the request
}
}

In the above Java servlet code, the Accept HTTP header is retrieved from the request and checked if it is null or if it equals "/". If either of these conditions is true, the application proceeds to process the request.

The Accept HTTP header is used by HTTP clients to tell the server what content types they'll accept. The server will then send back a response, which will include a Content-Type header to tell the client what the content type of the returned content actually is.

In the provided code, if the Accept header is not set (null) or if it is set to accept any MIME type ("/"), the server will process the request. This is a vulnerability because it allows for potential attacks where the client can send a request with a malicious MIME type. The server would then process this request and potentially cause unexpected behaviors or vulnerabilities.

For example, an attacker could send a request with a MIME type that causes the server to interpret the content in a way that leads to code execution, information disclosure, or any number of other potential vulnerabilities.

The server should be validating the Accept header to ensure it only processes requests with expected and safe MIME types.

Steps

  • Validate and restrict the allowed MIME types in the Accept header.
  • Set a default Accept header if it is not provided by the client.
  • Implement proper error handling for unsupported or unexpected MIME types.
  • Consider implementing content negotiation to ensure the server and client agree on the acceptable content types.

Compliant code

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public void doGet(HttpServletRequest request, HttpServletResponse response) {
String acceptHeader = request.getHeader("Accept");
String defaultAcceptHeader = "application/json"; // Default MIME type
List<String> allowedMimeTypes = Arrays.asList("application/json", "text/html"); // Allowed MIME types

if (acceptHeader == null) {
response.setHeader("Accept", defaultAcceptHeader);
acceptHeader = defaultAcceptHeader;
}

if (!allowedMimeTypes.contains(acceptHeader)) {
throw new IllegalArgumentException("Unsupported MIME type: " + acceptHeader);
}

if (acceptHeader.equals("*/*")) {
response.setHeader("Accept", defaultAcceptHeader);
acceptHeader = defaultAcceptHeader;
}

// process the request
}

The fixed code first sets a default MIME type (application/json) and a list of allowed MIME types (application/json and text/html).

If the Accept header is not provided by the client, the server sets it to the default MIME type.

Then, the server checks if the provided Accept header is in the list of allowed MIME types. If it is not, an IllegalArgumentException is thrown, indicating that the provided MIME type is not supported. This is an example of proper error handling for unsupported or unexpected MIME types.

If the Accept header is set to */* (which means any MIME type is acceptable), the server sets it to the default MIME type. This is a way of restricting the allowed MIME types in the Accept header.

This way, the server ensures that it only processes requests with acceptable content types, thereby preventing unexpected behaviors when interpreting incorrect content types. This is an example of implementing content negotiation.

References