Increasing security of Express applications with the Helmet middleware

Uncategorized

Making sure that the application is secure is one of the most important tasks of a developer. This is a vast topic, and in this article, we tackle it by adding a set of HTTP headers.

The Helmet is a middleware for Express applications. It sets many different HTTP headers and aims to make applications more secure. Adding it to our application is very straightforward:

The above is a wrapper for eleven smaller middlewares. Using it sets quite a bit of different HTTP headers for us. Let’s break this set of middleware one by one.

Content-Security-Policy

The purpose of the header is to add a security layer reducing the risk of attacks such as Cross-Site Scripting (XSS). With it, we state which dynamic sources the browser is allowed to load.

The person performing the XSS attack exploits the fact that the browser can’t tell the difference between a script that is a part of our application and the one injected maliciously. When we define a header, we can tell the browser which URLs to trust.

The header in the above example tells the browser not to load any scripts from origins different than the opened page. It also blocks all inline scripts and inline event handlers. If you want to use external sources of code such as CDN, you can specify its URL here.

There are many more rules than we can specify, and the Helmet middleware sets quite a lot of them. Running , or , gets us the following:

If you want to check all available policies, MDN is a great resource.

X-DNS-Prefetch-Control

While DNS requests cost little bandwidth-wise, the latency might be significant. If we can predict which hostnames will be needed, we can perform a lookup beforehand.

Thanks to doing the above, the domain is resolved before it is needed.

Unfortunately, some attackers might take advantage of the DNS prefetching. The header is responsible for controlling the DNS prefetching feature. If we don’t utilize it, we might as well turn it off to improve the security of our page slightly. This is the default behavior of and .

Expect-CT

The Certificate Transparency (CT) is an open-source framework for monitoring digital certificates. Public logs aim to contain all certificates issued by trusted certificate authorities. This allows for the identification of maliciously created certificates.

By enabling the header, the site requests that the browsers check if the site’s certificates appear in public CT logs. The header might become obsolete in June 2021 because, at that point, every certificate will be expected to be submitted to the CT logs.

We can set this header either with or .

Referrer-Policy

The browser sends the address of the page through the request header. For example, when our application makes HTTP requests to the API, the header contains the URL of the application.

The header is actually a misspeling of the word referrer.

The header might be useful for various things such as loggings and analytics. Unfortunately, it might also lead to malicious data tracking or information leakage. Due to that, browsers send the when an HTTPS site tries to communicate with an HTTP destination.

With the header, we have the opportunity to specify the desired behavior. We have quite a few options to choose from. However, running or sets the header to . It gets rid of the header completely from requests.

If we need the header, we can pass some additional arguments to the Helmet middleware.

Strict-Transport-Security

When we visit a site using HTTPS and the header, the browse remembers it. If we ever try to load the same site through HTTP, we are automatically switched to HTTPS.

This might prevent a sort of the man-in-the-middle attack. The hacker can intercept our HTTP request and redirect us to a clone of the site we intend to use. This can lead to exposing very sensitive data. If the header is used, the above scenario is impossible if we visited the original site at least once.

If we use or , there is a set of default options chosen for us. For example, the header takes an effect for 180 days and includes subdomains.

X-Content-Type-Options

Browsers can fetch many different resources for an application, such as stylesheets, images, and JavaScript files. Each of those should include a response header. An example of a valid header value is  or .

Unfortunately, sometimes the value of the can be wrong or be missing. In this situation, the browser can perform MIME sniffing and attempt to guess the correct MIME type based on the resource.

This might prove to be problematic. When our site allows some data to be uploaded to the server, the attacker can disguise an HTML file with the MIME type of , for example. If our users late fetch this file, it opens up a possibility for an XSS attack.

To avoid that, and set the header to . This causes the browser not to analyze the file. Therefore, we need to make sure that we always send the correct response header.

X-Download-Options

With the Helmet middleware, we even have some improvements for Internet Explorer 8. The issue is when the IE8 user downloads an HTML file and chooses to open it directly instead of saving it to drive. This causes the HTML file to execute in the context of the website the user downloaded it from.

Setting the header to prevents the IE8 users from directly opening a file before download. We can achieve this with or .

X-Frame-Options

Clickjacking is an attack that utilizes iframes. Imagine the attacker preparing a website with some buttons. On top of them, a transparent iframe is placed that renders our page that we want to protect.

The attacker can line up the invisible iframe to line up with some of the buttons on the malicious website. When the victim tries to click them, it results in clicking on an invisible button instead. This hijacks the user’s click, and this is why we call it clickjacking.

With the header, we can tell the browser whether it can render the page in an iframe. The default value set by and is . This causes the webpage to displayable in iframes on the same origin as the page itself. We could also use to block our page from being displayed in iframes completely.

This applies also to the , and elements.

X-Permitted-Cross-Domain-Policies

Software such as Adobe Flash Player and Adobe Acrobat can embed content from websites in documents. They block all cross-domain requests by default, such as browsers block cross-domain requests. This can be changed by providing a prepared policy file. If an attacker finds a way to inject this file, it changes the cross-domain policy for some Adobe clients.

A way to override that is to provide the set to . We can do it by running , or .

X-Powered-By

The is a response header that specifies the technology behind our application. If you are using Express, all endpoints return the header by default.

It is always better if our potential attackers don’t know the technology we are using. Even though there are more ways for the attackers to identify that we use Express, the Helmet library decided to remove this header by default. It happens when we run or .

If you want to know more about the discussion about removing this header from Express, check this GitHub issue

X-XSS-Protection

The header is a feature in some older browsers. It aims to stop a page from loading when a browser detects an XSS attack. Nowadays, this is no longer necessary, especially with the use of the header. Also, it turned out that it causes some issues. All modern browsers aside from Safari no longer support this functionality.

By running or we set to . This disables this functionality for browsers that still support it.

Summary

In this article, we’ve gone through all of the headers that the Helmet library sets up for us. We’ve described what each one of them does and why. All of them help us make our application a little bit more secure. Adding those headers can help us avoid attacks such as XSS or clickjacking. Caring for that aspect of an app is a significant part of the job of every developer.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments