Strict Transport Security (HSTS)

Written by Ulises Gascón

Apr 08, 20202 min read

The attack

As we are not forcing the HTTPS traffic to be keep using HTTPS. The users can use the HTTP (vanilla) protocol to access our site.

As a result of this protocol downgrade we will expose sensitive information (ajax payloads, cookies, tokens...) in plain text.

Our users are vulnerable to person-in-the-middle attacks as nothing sent is encrypted.

The header

The Strict-Transport-Security HTTP header tells browsers to stick with HTTPS and never visit the insecure HTTP version. Once a browser sees this header, it will only visit the site over HTTPS for the next 60 days:

Strict-Transport-Security: max-age=5184000

Limitations

The initial request remains unprotected from active attacks if it uses an insecure protocol such as plain HTTP or if the URI for the initial request was obtained over an insecure channel. The same applies to the first request after the activity period specified in the advertised HSTS Policy max-age (sites should set a period of several days or months depending on user activity and behavior). Google Chrome, Mozilla Firefox and Internet Explorer/Microsoft Edge address this limitation by implementing a "HSTS preloaded list", which is a list that contains known sites supporting HSTS.

Privacy issues

HSTS can be used to near-indelibly tag visiting browsers with recoverable identifying data (supercookies) which can persist in and out of browser "incognito" privacy modes. See

The code

You can use this module as part of Helmet:

const helmet = require('helmet')

// Sets "Strict-Transport-Security: max-age=5184000; includeSubDomains".
const sixtyDaysInSeconds = 5184000
app.use(helmet.hsts({
  maxAge: sixtyDaysInSeconds
}))

Disable for subdomains

// Sets "Strict-Transport-Security: max-age=5184000".
app.use(helmet.hsts({
  maxAge: sixtyDaysInSeconds,
  includeSubDomains: false
}))

Preloading HSTS in Chrome

Some browsers let you submit your site’s HSTS to be baked into the browser. You can add preload to the header with the following code. You can check your eligibility and submit your site at hstspreload.org.

app.use(helmet.hsts({
  // Must be at least 1 year to be approved
  maxAge: 31536000,

  // Must be enabled to be approved
  includeSubDomains: true,
  preload: true
}))

Refs: