Implementing a solid security layer for our applications and assuring necessary rules have become a required step for the web in the last decades. Of course, we can't claim that 100% of the web is protected against the myriad of threats popping up everywhere. Nevertheless, there is a real push from many fronts to keep perfecting security measures on the web.
That being said, not all security features are made the same way or have the same impact to protect our users. For example, one of the most essential features to protect our users is HTTP Strict Transport Security or HSTS.
This article aims to examine HSTS in the context of Ruby on Rails. First, we will briefly define what HSTS is and what makes it fundamental to secure communication between your server and the client. Additionally, we will explore how to enable the security feature on Rails. And finally, we will review some of the issues that might emerge.
Note that if your proficiency level with Ruby on Rails is weak or you are just dipping your toes in it, we recommend that you familiarize yourself with their guides to learn more. It is important to understand modern Ruby on Rails to follow the concepts we discuss in this article.
Defining HTTP Strict Transport Security
The most fundamental protection against eavesdropping over our data is encryption. Ensuring that we encrypt our transactions with the proper protocols is critical for any web platform, whether it requires user information or not. Yet, while the web depends on SSL/TLS protocols to encrypt and secure communications between client and server, guaranteeing that all transactions are secure is another matter entirely.
To illustrate, a conventional flow of communication with a website is to first make an HTTP request to the domain and, if the server is implementing SSL/TLS with a valid certificate and enforcing HTTPS rerouting, be redirected (301) to the same site with an HTTPS request. This process guarantees that all communication between the client and server is performed securely through encryption.
Except that it doesn't.
Consider the following scenario.
MITM Attack
If an unsuspecting user attempts to reach our server through a compromised network (a bogus access point disguised as legitimate), the introductory handshake can be a source of vulnerabilities.
Attackers can intercept the communication between client and server, acting as the go-between in the middle.
They can then rewrite all communication between themselves and the user to be unencrypted.
All transactions between the attackers and the server remain encrypted, fooling the server into believing the user is protected.
Meanwhile, the attackers intersect all data the user sends to our server.
Profit.
The attack we just described is known as SSL stripping. It works by basically stripping the client of any encryption security.
Not good. So what can we do?
The most crucial step in this attack is the initial handshake. To prevent this from happening, we must ensure that the browser exclusively communicates with our server using encryption. The best way to do that is to tell the browser to do so explicitly. That is, in principle, what HTTP Strict Transport Security is, and it is a keystone to secure the web.
Adding the HSTS Header on Rails
Our browsers, and the security features baked in them, do most of the work for us in order to keep us safe. All you need to do to implement a primary layer of security with HSTS is to add this header to your server responses.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Doing this on Rails would look like this:
# application.rb
...
config.ssl_options = { hsts: { preload: true, expires: 1.year, subdomains: true } }
...
HSTS headers contain three directives, one compulsory and two optional.
max-age: This states how long the browser will comply with the policy. Notice that we have set the value as 31536000, which equates to one year. You can put any value you consider appropriate, but remember that your clients will not have access to your site if there is an issue with your SSL certificate once the browser receives the HSTS policy.
includeSubDomains: This optional directive states whether the subdomains will need to comply with the policy. If you have mywebsite.com with an SSL certificate and set the header for clients who visit it, then www.mywebsite.com and subdomain.mywebsite.com will also be required to follow the same HSTS policy.
preload: This optional directive states that you want to add your site to the HSTS preload list included in the browser. This list essentially cements your website to follow HSTS for that client permanently.
Additionally, we recommend that you confirm that you are forcing Rails to redirect all transactions from HTTP to HTTPS. To do that in Rails, add the following:
# application.rb
...
config.force_ssl = true
config.ssl_options = { hsts: { preload: true, expires: 1.year, subdomains: true }, redirect: { status: 307, port: 81 } }
...
An understanding of the HSTS header is required, but we also need to be aware of what happens to our website when it's not ready to follow the policy.
An error in a Google Chrome browser that says the user's connection is not private.
Here we see an error in our browser, indicating that the server marked this website as working exclusively with encryption. Yet the browser detected something was not right, so it's displaying this error instead of loading the site.
HSTS Step by Step
We can read from the error what the possible sources of the problem are:
The suspicious activity could be from an attacker trying to impersonate the server.
A WiFi login screen could be interfering with the loading process.
The server doesn't have an adequate SSL/TLS configuration.
Now, we know what the problem is. We intentionally set up our website to fail the HSTS policy check, so our course of action should be to ensure that we set up encryption correctly. Additionally, if we are deploying HSTS for the first time, we must have a proper implementation plan.
Here is a checklist of steps to follow based on Scott Helme's HSTS tutorial:
Find all subdomains that belong to your site (consult DNS CNAME entries). Note that they might belong to third-party services.
Confirm that the root domain and its subdomains are accessible via HTTPS.
Make sure you configured proper redirection of HTTP to HTTPS.
Set a short expiration time. For example, "max-age=300" (five minutes).
Append the "includeSubDomains" directive if necessary.
Increment "max-age" in stages. Strive for two years' validity.
Once all is good, add the "preload" directive.
Submit your domain to Google's HSTS preload list, which will ensure that future versions of all major browsers have your domain preloaded and marked as secure-only. (This is optional.)
After you follow all these steps, you will have a site enforcing HTTPS communication only. From that point on, all users will obey the policy.
Great, right?
Yes! But also, not so much. As we know already, no solution is perfect, and there is still some possibility of a breach by highly complex attacks. Nevertheless, implementing SSL/TLS and HSTS policy goes a long way to protect 99.9% of the web.
Security Measures Going Forward
Implementing HTTP Strict Transport Security policy is a fundamental building block of security for the web. Having it placed is required to guarantee the protection of users accessing our platforms from many different sources.
Of course, we count on decades of work that have compounded over the advancements in security introduced at the time of conception of the web. Keeping our platforms secure is no easy task, and the threats out there keep getting more and more sophisticated. So we must close as many gaps as possible in our platforms to ensure that our users can safely consume our services and tools.
This post was written by Juan Reyes. Juan is an engineer by profession and a dreamer by heart who crossed the seas to reach Japan following the promise of opportunity and challenge. While trying to find himself and build a meaningful life in the east, Juan borrows wisdom from his experiences as an entrepreneur, artist, hustler, father figure, husband, and friend to start writing about passion, meaning, self-development, leadership, relationships, and mental health. His many years of struggle and self-discovery have inspired him and drive to embark on a journey for wisdom.