Mallow's Blog

Thinking of Securing your Site? – Use HSTS

Connections start with http

Even if the web app is available with HTTPS some users may end up visiting HTTP thus losing the security that HTTPS provides. When the user visits the app with HTTP, the browser sends an HTTP request to the server and the server sends a 301 redirect response demanding a request to be sent over HTTPS and there is a chance for the SSL strip attack here. Let us see the way to avoid SSL stripe attack in this blog.

It would be nice if the server could tell the browser to send all subsequent requests over HTTPS for the current and future sessions, right?

That’s what HSTS does. HSTS stands for HTTP Strict Transport Security. HSTS header tells browsers that for all future requests to use HTTPS for say next 6 months. So now even if the user types http://domain.com then the browser itself will switch HTTP into HTTPS without contacting the server for a period of 6 months.

When the first request submitted from the client(HTTP or HTTPS), the server will send a response with a header named Strict-Transport-Security which will tell the browser to preload the HTTPS version of the request even if the request is visited through HTTP. 

HSTS Preloading using hstspreload.org:

Major browsers like Chrome, Firefox, Opera, Safari, IE supports HSTS preloading.  Any request made to any site listed in HSTS preload is always sent over HTTPS from the very first request even if the first request is HTTP.

For example “mail.google.com” is in the hstspreload list. Even if we visit the url http://mail.google.com, the request will be sent over HTTPS and not HTTP for the first visit of the request.

Any domain can be added to the HSTS preloaded list from this site(https://hstspreload.org/) and there you check the eligibility of a domain to be hstspreloaded.

Setting up HSTS in rails:

HSTS headers can be enabled in rails with the force_ssl configuration, Rails not only redirects to HTTPS but Rails also sets HSTS header in response. The default time period or age that rails added is 2 years.

HSTS can be enabled by switching force_ssl configuration in the application’s config:

# config/environment/production.rb
Rails.application.configure do
  ...
 config.force_ssl = true
  ...
end

Setting force_ssl to true inserts ActionDispatch::SSL middleware and the middleware is responsible for 3 things:

  • Redirecting http requests to https
  • Adding HSTS header to the response
  • Set a flag on cookies to send them through https only

HSTS options in force_ssl: This option tells the browser to remember this site as TLS-only. This is enabled by default. 

Set config.ssl_options with hsts: false to disable.

To configure HSTS options, Set config.ssl_options with hsts: { … }. Below are the options available.

  • expires:  To set lifespan in seconds. For the site to be added in preloaded list, the minimum value is 1 year. Defaults to 1 year (recommended).
  • subdomains: Set true to tell the browser to apply HSTS settings to all subdomains. Defaults is true.
  • preload: Enabling this option will add the domain to HSTS preloaded list. HSTS header protects the site on every visit except the first visit since it hasn’t seen your HSTS header first request.

    Preload option Defaults to false

To Skip/disable force_ssl for particular controller in Rails, use the below:

This option is available only for rails > 5 version

config.ssl_options = {
  redirect: {
    exclude: -> request { request.path =~ /healthcheck/ }
  }
}

Turn off HSTS:

To turn off HSTS, omitting the HSTS header is not enough. Browsers will remember the original HSTS till it expires. 

We should use the header to tell browsers to expire HSTS immediately. 

Setting hsts: false or hsts: { expires: 0 } will override the expiry as 0 seconds. So the HSTS will be turned off for further requests.

Check out the options available in ActionDispatch::SSL here(https://api.rubyonrails.org/v5.2.6/classes/ActionDispatch/SSL.html)

Saranya K,
ROR Team,
Mallow Technologies.

Leave a Comment

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