Skip to main content

Security implications of HTTP response headers

Escrito por:
wordpress-sync/security-champions-guide

3 de maio de 2023

0 minutos de leitura

When a web server receives an HTTP request, it is processed and sent back with a response containing the requested resource and any additional information in the form of HTTP response headers. These headers provide important data, such as last-modified dates, content types, and cache-control settings. The browser then uses this information to determine how to display or store that particular resource. This process helps ensure efficient communication between web servers and browsers.

From a cybersecurity perspective, HTTP response headers represent potential attack vectors and opportunities for enacting extra layers of defense. They can contain sensitive data like authentication tokens, cookies, and session IDs that, once accessed, enable attackers to bypass authorization controls or hijack user accounts. But we can also use them to control caching, specify the type of content returned, and prevent attacks like cross-site scripting (XSS) and clickjacking.

HTTP response headers provide several security features — including authentication, user agent tracking, preventing XSS, and enforcing HTTPS use. While certain HTTP headers like Etag, Last-Modified, and Content-Type aren’t useful for security purposes, the Content Security Policy (CSP), HTTP Strict Transport Security (HSTS), and X-Frame Options headers offer opportunities to reinforce our servers.

This article spotlights several HTTP headers that impact security and suggests best practices for leveraging HTTP response headers to secure web applications.

Leveraging HTTP response headers for security

We can use HTTP response headers to mitigate several types of exploitable vulnerabilities. 

Vulnerabilities to consider for HTTP response headers

The right HTTP response headers mitigate direct exploits and extend to vulnerabilities that don’t directly involve them. Some examples of different types of exploits and vulnerabilities include:

  • Cross-site request forgery (CSRF): Attackers can use CSRF, also known as one-click attacks, to force a user’s web browser to perform unwanted actions on their behalf.

  • Session hijacking: Attackers gain unauthorized access by stealing session IDs from authenticated users and hijacking their existing sessions without credentials like usernames-password pairs — bypassing traditional authentication systems.

  • Data leakage: HTTP response headers can contain passwords, credit card numbers, and other sensitive information that could be potentially leaked if not configured properly.

  • Man-in-the-middle (MITM) attacks: Attackers use MITM attacks to intercept, modify, and block communications between two parties during a transaction. Neither is aware that the other is communicating with an unauthorized third party.

  • Clickjacking attacks: By exploiting weaknesses in HTML framesets within a website, attackers can send users spoofed content. When clicked, this leads them to perform unintended actions or divulge confidential information unknowingly.

Maintaining web application security is crucial, especially with so many potential attack avenues. In the last several years, we’ve seen an uptick in high-profile, high-impact security breaches. For example:

With attacks occurring so frequently and on such a significant scale, it’s clear that increasing and maintaining security — including through HTTP headers — is non-negotiable. 

HTTP response headers that impact security

Data leakage is a vulnerability directly related to HTTP response headers. CSRF, session hijacking, and MITM attacks don’t necessarily involve HTTP response headers. However, we can still mitigate them by using secure HTTP headers — like CSP and HTTP Strict Transport Security (HSTS) — and following best practices when using other security-impacting headers, like the ones outlined below.

HTTP Strict Transport Security header

The HSTS response header protects applications from MITM attacks, data leakage, and clickjacking. This header forces all communication between the browser and server to occur over HTTPS connections instead of plain HTTP. It prevents attackers from redirecting traffic through their malicious proxy servers to access or manipulate sensitive data sent back and forth without either party being aware.

HSTS contains information about a website’s security policies, such as:

  • How long the connection will remain active (max age).

  • Whether its scope of protection includes subdomains.

  • What type of certificates to accept.

To best use the HSTS response header, we should always set up a maximum age value. It should correspond with the time we want clients to remember to connect securely before passing another request through the TLS/SSL tunnel.

Content-Security-Policy header

CSP is important in defending against different types of attacks. It allows developers to safelist allowed resources and their origins, define directives, determine whether to allow inline scripts or eval(), and decide whether to permit style attributes in HTML.

The HTTP Content-Security-Policy response header allows us to specify the domains and resources allowed or blocked in a website’s content. It protects against XSS and the aforementioned vulnerabilities — as well as other malicious activities such as clickjacking, data injection, code injection, CSRF, and unauthorized access to sensitive information. CSP contains directives dictating how browsers should handle requests from untrusted sources outside our domain that extend to loading scripts, images, and other exploitable assets.

Here are some guidelines for configuring the CSP header to proactively defend against vulnerabilities:

  • Stick with policies that block activity rather than allow them whenever possible. This will block requests from untrusted sources outside of your domain by default.

  • Use wildcard subdomains (*.<your-domain-name> prefix before your main domain name).

  • Limit access only to known trusted sources rather than opening up requests broadly across any random source. Also, include directives dictating how browsers must handle certain requests from untrusted sources outside our domain — such as loading scripts, images, and other exploitable assets.

An aggressive security stance ensures that only authorized clients can view sensitive information while preventing data leakage via unintended downstream routes. We can also utilize strict validation mechanisms such as Subresource Integrity (SRI) that help verify the integrity of a website’s resources and ensure an attacker hasn’t tampered with them. 

By combining SRI with CSP, we can ensure that only trusted, uncorrupted third-party resources are loaded into our web pages.

X-Content-Type-Options header

We can leverage the X-Content-Type-Options header to instruct browsers to never try andautomatically detect the type of file or content served. Doing so makes it much harder for an attacker to inject malicious code into a website, as the browser won’t be able to parse/execute any arbitrary script files sent along with it. In this way, the X-Content Type-Options header is a frontline defense against malicious content and XSS attacks.

When configuring and utilizing this header, you should ensure that all sites serve content with strict MIME types specified. Avoid using wildcards (*) wherever possible within those values. Specifying actual file types tells browsers precisely what kind of assets they should expect, avoiding the requirement to detect them altogether. 

X-Frame-Options header

X-Frame-Options protects web applications from clickjacking attacks. It contains a directive that tells the browser whether to display its contents within an <iframe> element on a third-party website. 

There are two commonly used directives. DENY prevents any attempts at framing the requested resource in other sites. SAMEORIGIN only allows the request if both pages are hosted under the same origin policy. This setup helps defend against clickjacking and other XSS security vulnerabilities.

It’s best to ensure that all resources served by the web application always include X-Frame-Options — DENY instead of SAMEORIGIN. We should also use the maximum level of protection as a default, as we can never be certain when and how content can make it outside of our origin policy. 

Referrer-Policy header

The Referrer-Policy header controls the circulation of referrer information from one application/website source to another. It contains four primary directives — none, no-referrer, no-referrer-when-downgrade, and origin — that dictate how a browser shares its referring URL with other sites or applications during navigation. 

We can configure this header based on our individual needs to ensure that sensitive data isn’t accidentally exposed while users traverse multiple web properties or domains.

It’s ideal to set the Referrer-Policy to no-referrer so that request headers don’t include referral information when users click external links. This setting preserves their privacy by preventing any personal data from leaking into unintended channels.

Setting security headers in JavaScript 

The following section highlights three tools we can use to set security headers when developing with JavaScript. Note that you can also apply the following to other languages and ecosystems.

After reviewing each tool, we’ll walk through a hands-on example of how to use it to set security headers.

Helmet for Express.js

Helmet is a collection of security-related HTTP response headers that help protect web applications from attacks and vulnerabilities. Helmet for Express.js is an extension of the Helmet package specifically designed to work with the Express.js framework. It provides nine smaller middleware functions that set specific security-related HTTP response headers for applications.

Setting up Helmet for Express.js is straightforward. First, install Helmet using this command:

1npm install helmet

Then, use the following code to require both the Express framework and the Helmet package to use their middleware functions. This allows us to set the response headers:

1const express = require("express");
2const helmet = require("helmet");

Next, use this code to create an instance of an Express application, assign it to a variable, and start using Helmet’s middleware functions:

1const app = express();
2app.use(helmet());

Initializing Helmet sets several security headers, including the five we discussed above. We can customize individual header options in Helmet for Express.js by adding them to the helmet() middleware using the following code:

1app.use(
2  helmet({
3    X-Frame-Options: { policy: "DENY" },
4  })
5);

Helmet for Fastify

Helmet for Fastify is a middleware package that lets us add important security headers to the Fastify web framework. It’s essentially a wrapper around Helmet and accepts the same options.

Install Helmet for Fastify by running:

1npm i @fastify/helmet.

Then, require the Fastify framework and Helmet for Fastify using this code:

1const fastify = require('fastify');
2const helmet = require('@fastify/helmet');

Next, register the Helmet plugin with our application by running this code:

1fastify.register(helmet);

This command will set the basic security headers automatically.

check-my-headers

Check-my-headers is a free CLI tool we can use to quickly test our website’s HTTP headers for any potential vulnerabilities. It’s both free and framework agnostic, meaning it checks our headers without minding what we used to set them.

We can install it globally via npm install -g check-my-headers and run a quick one-off scan by inputting npx check-my-headers https://yourwebsite.com in the CLI.

Conclusion 

Several key HTTP response headers impact web security, and leveraging best practices for using them creates an added layer of security for web applications. The five headers discussed here help protect against various vulnerabilities, like CSRF attacks, session hijacking, data leakage, MITM, and clickjacking — attacks that can result in significant, often irreparable, damage. Understanding how HTTP response headers weaken or contribute to security is an important step toward mitigating these popular attack vectors.

Properly leveraged and configured response headers are essential for web security. They safeguard users’ privacy and allow for greater flexibility when securing communication between web servers and clients.

wordpress-sync/security-champions-guide