Skip to main content

Insecure or unset HTTP headers - Strict Transport Security

Need

Implementation of Strict Transport Security (HSTS) HTTP header

Context

  • Usage of PHP for server-side scripting and web development
  • Usage of Closure for JavaScript code optimization and minification

Description

Non compliant code

<?php
namespace App\\Http\\Middleware;

use Closure;

class SecureHeaders
{
public function handle($request, Closure $next)
{
$response = $next($request);

// Here is the vulnerability. The Strict-Transport-Security HTTP header is missing.
// Therefore, the server is not forcing the client to use HTTPS.

return $response;
}
}
?>

This piece of code is a middleware in a Laravel application. Middlewares are used to filter HTTP requests entering your application. In this case, it should be used to add secure HTTP headers to the response.

However, the Strict-Transport-Security HTTP header is missing from the response. This header is crucial for enforcing secure (HTTPS) connections. Without it, or if it's set with a too short max-age, the client is not forced to use HTTPS, which can lead to insecure communication.

The max-age directive of the Strict-Transport-Security header specifies the amount of time, in seconds, that the browser should remember that a site is only to be accessed using HTTPS.

Thus, the server is susceptible to man-in-the-middle attacks where the attacker can intercept the communication between the client and server.

Steps

  • Identify the middleware where the response headers are set.
  • Add the Strict-Transport-Security (STS) HTTP header to the response headers.
  • Set the max-age directive to a sufficiently long duration. This tells the browser to request the site via HTTPS for the specified number of seconds.
  • Consider adding the 'includeSubDomains' directive if all subdomains are also served over HTTPS.
  • Consider adding the 'preload' directive if you're sure that the site will be served over HTTPS for a long time. This will include your site in the STS preload list maintained by browsers.
  • Test the changes to ensure that the STS header is correctly set and that the site is loaded over HTTPS.

Compliant code

<?php
namespace App\\Http\\Middleware;

use Closure;

class SecureHeaders
{
public function handle($request, Closure $next)
{
$response = $next($request);

// Add the Strict-Transport-Security HTTP header to the response headers.
// Set the max-age directive to a sufficiently long duration.
// This tells the browser to request the site via HTTPS for the specified number of seconds.
// Consider adding the 'includeSubDomains' directive if all subdomains are also served over HTTPS.
// Consider adding the 'preload' directive if you're sure that the site will be served over HTTPS for a long time.
// This will include your site in the STS preload list maintained by browsers.
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');

return $response;
}
}
?>

The updated code now includes the Strict-Transport-Security HTTP header in the response headers. This header is crucial for enforcing secure (HTTPS) connections to the server.

The max-age directive is set to 31536000 seconds, which is equivalent to one year. This duration is generally considered to be sufficiently long. It instructs the browser to request the site via HTTPS for that number of seconds.

The includeSubDomains directive is also included. This means that the rule applies to all subdomains as well, ensuring that connections to any subdomain of the site will also be requested via HTTPS.

The preload directive is also included. This is a signal to browsers that the site owner consents to the inclusion of their domain in hard-coded lists of sites that should be only accessed over HTTPS.

After implementing these changes, it's important to test the application to ensure that the Strict-Transport-Security header is correctly set and that the site is loaded over HTTPS.

References