Skip to main content

Insecure or unset HTTP headers - Cache Control

Need

Implementation of secure and appropriate Cache Control headers

Context

  • Usage of Java for building cross-platform applications
  • Usage of javax.servlet for building Java web applications
  • Usage of javax.servlet.http for handling HTTP requests and responses in Java web applications

Description

Non compliant code

import javax.servlet.*;
import javax.servlet.http.*;

public class InsecureServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>Hello, World!</h1>");
out.println("</body></html>");
}
}

This servlet responds to a GET request by sending a simple HTML page to the client. However, it does not set any HTTP headers related to caching, such as Cache-Control. This can lead to security issues as sensitive data might be cached by intermediate proxies or the client browser, which can then be accessed by unauthorized users.

The Cache-Control HTTP header is used to specify directives for caching mechanisms in both requests and responses. The lack of this header can lead to sensitive information being stored in cache, and potentially being retrieved later by an unauthorized user.

In the provided code snippet, the doGet method sets the Content-Type header to "text/html", but it does not set the Cache-Control header. This means that the response can be cached by any cache, including the browser cache and any intermediate proxies, potentially leading to information disclosure.

Steps

  • Set the Cache-Control header in the HTTP response.
  • Use a secure value for the Cache-Control header to prevent caching of sensitive information.
  • Consider using other HTTP headers like Pragma and Expires to provide additional cache control.
  • Implement proper caching strategies based on the specific requirements of the application.
  • Test the application to ensure that the Cache Control header is set correctly and caching behavior is as expected.

Compliant code

import javax.servlet.*;
import javax.servlet.http.*;

public class SecureServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html");
// Set the Cache-Control header
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
// Set the Pragma header to no-cache to support HTTP 1.0
response.setHeader("Pragma", "no-cache");
// Set the Expires header to 0 to prevent caching at the proxy server
response.setDateHeader("Expires", 0);

PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>Hello, World!</h1>");
out.println("</body></html>");
}
}

The above code fixes the vulnerability by setting the Cache-Control, Pragma, and Expires headers in the HTTP response.

The Cache-Control header is set to "no-store, no-cache, must-revalidate, max-age=0" to instruct the browser and all intermediate caches that they must not store a copy of the resource under any circumstances, they must not use a cached copy without successful validation on the origin server, and they must not use the cached copy after the amount of time specified in the max-age directive (0 in this case).

The Pragma header is set to "no-cache" to support HTTP 1.0 caches which do not recognize the Cache-Control header.

The Expires header is set to 0 to indicate that the resource is already expired and should not be cached by the browser or any intermediate caches.

These headers together ensure that sensitive information is not cached, thereby mitigating the risk of information leakage through caching.

References