Website Hardening with HTTP Security Headers

One easy and good start to harden your website or web application is to configure the HTTP Security Headers. Those HTTP Headers are included in the response of the server and tell the browser how to deal with content on your website.

As an example, you can configure the HTTP Headers in a way, that only javascript code that is delivered by your website is allowed.

First step: Check your HTTP Headers

First step is to check which HTTP headers are already configured and which should be added. Scott Helme build a great site for that: https://securityheaders.com/

After that, you can configure all missing headers.

Recommended HTTP Security Headers

The configuration of the Headers ALWAYS depend on your website, your requirements, the features, the structure etc.. Therefore, it is always up to you to check the headers in detail.

In many cases, the following headers are a good starting point:

Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; base-uri 'self'; form-action 'self'
Referrer-Policy: strict-origin-when-cross-origin
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: deny
X-Permitted-Cross-Domain-Policies: none

Content-Security-Policy (CSP)

Defines, which resources the browser is allowed to load from which urls (sources). With CSP, you can e.g. specify, that images are allowed to load from your url and from cdn.example.com. You can also define, that JavaScript files are only allowed from your url and that no inline scripts are allowed. Such a config prevents loading scripts from other websites or injected javascripts.

If you set the CSP, be careful and make sure that your site still works afterwards! Especially google-analytics or other external scripts will probably not load anymore!

Examples

# Allow everything, but only from the same origin
default-src 'self';

# Allow scripts from origin and Google Analytics 
script-src 'self' www.google-analytics.com

# Allow scripts, ajax, form actions, css and images from the same origin. 
default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; base-uri 'self'; form-action 'self'

Check your Content-Security-Policy with: https://csp-evaluator.withgoogle.com/
Get more information at:

Referrer Policy

This policy defines how much referrer information is included in requests. If you tweet a link to your website and visitors click this link, the header will contain the referrer information. If someone clicks a link on your webpage, the referrer information is also included. Two examples:

Referrer-Policy: unsafe-url

Referrer-Policy: strict-origin-when-cross-origin

The second one only contains the root url, arminreiter.com, while the first one also has the page in it. Your referrer policy depends on which information you want to share with other websites, but it is at least recommended to only allow referrer information for websites that use HTTPS.

Note: The referrer policy can also be defined as meta tag in html or separately for each link:

<meta name="referrer" content="origin">
<!-- or -->
<a href="https://arminreiter.com" rel="noreferrer">

The following values are allowed:

Referrer-Policy: no-referrer
Referrer-Policy: no-referrer-when-downgrade
Referrer-Policy: origin
Referrer-Policy: origin-when-cross-origin
Referrer-Policy: same-origin
Referrer-Policy: strict-origin
Referrer-Policy: strict-origin-when-cross-origin
Referrer-Policy: unsafe-url

A description of the different options can be found here:

Set-Cookie

When the server returns a cookie to the client, the response contains a set-cookie header. This header can be extended with some attributes. The following one is a recommended Set-Cookie header:

Set-Cookie: name=value; Expires=date; Secure; HttpOnly; SameSite=Strict

The following attributes are allowed:

  • Secure: is set when the request is made with https scheme.
  • HttpOnly: If HttpOnly is set, javascript is not allowed to access the cookie (e.g. via Document.cookie).
  • SameSite=Strict: Browser sends cookie only for same-site request. Other options are Lax and None.

Find more information about Set-Cookie at:

Strict-Transport-Security

Tells the browser that the website should only be accessed via HTTPS.
Strict-Transport-Security: max-age=31536000 ; includeSubDomains

  • max-age: tells the browser to remember that the site is only accessible via HTTPS for this amount of time (in seconds). 31536000 = 1 year
  • includeSubDomains (optional): rule is applied also to subdomains
  • preload (optional): Google maintains an HSTS preload list (https://hstspreload.org/) which contains domains that have opted-in to HSTS and can therefore only be accessed over HTTPS.

see also:

X-Content-Type-Options

This options prevents the browser from doing MIME-type sniffing. Thats a technique which is used by some browsers to determine the type of a file and execute it, independent of the returned content-type. If the browser e.g. requests a script, but that script has an incorrect media type, the browser will “sniff” the content of the file, detect it as script and execute it. An attacker could for example upload a script file with content-type image (e.g. as profile image of a user). The browser would sniff the content of the “image”, will detect that it is a script and will execute it.
This can be prevented by using the HTTP header:

X-Content-Type-Options: nosniff

The “nosniff” option disables the sniffing and in the example above, it would block the script because the content-type would be image and not one of the javascript media types.

see also:

X-Frame-Options

Defines if the page can be rendered in an <embed>, <frame>, <iframe> or <object> tag. If someone creates a page with an iframe that embeds your webpage, then the options below will block the rendering of your page (by sure, it must be supported by the browsers, but most of them do). You can test this by creating a new page – e.g. index.html – on your desktop, and embed your website into an iframe:

<html>
  <body>
    <iframe src="https://arminreiter.com">
    </iframe>
  </body>
</html>

If you open this index.html, you will, instead of your webpage, see the following content in the iframe:

There are the following 2 options available (note: allow-from is deprecated and not supported by many browsers):

  • X-Frame-Options: DENY
    The page can not be displayed in a frame.
  • X-Frame-Options: SAMEORIGIN
    The site can only be displayed in a frame with the same origin.

see also:

X-Permitted-Cross-Domain-Policies

Prevents others to embed your website e.g. into adobe flash applications or PDF documents. This can be completely forbidden or controlled via a crossdomain.xml policy file. The allowed values are:

  • X-Permitted-Cross-Domain-Policies: none
    Do not allow any embedding.
  • X-Permitted-Cross-Domain-Policies: master-only
    Instructs Flash and other applications to only read the master crossdomain.xml file from the root website.
  • X-Permitted-Cross-Domain-Policies: by-content-type
    Only policy files served with content type “text/x-cross-domain-policy” are allowed.
  • X-Permitted-Cross-Domain-Policies: all
    All policy files on the domain are required.

see also:

Extra: remove headers that expose information

Beside the headers mentioned above, there are other standard headers e.g. X-Powered-By, Server, X-AspNet-Version and others. They expose information about your website/infrastructure and should therefore be removed.

other HTTP Headers

X-XSS-Protection instructs the browser to stop pages from loading when they detect cross-site scripting (xss). This header is not supported by Chrome, Firefox or Edge and is therefore not needed anymore. Value could be:
X-XSS-Protection: 1; mode=block

Further information

Categories:

No responses yet

Leave a Reply

Your email address will not be published. Required fields are marked *

About
about armin

Armin Reiter
Blockchain/Web3, IT-Security & Azure
Vienna, Austria

Reiter ITS Logo

Cryptix Logo

Legal information