Enabling HSTS on Apache2: A Guide

14 February 2018
HTTP Strict Transport Security for All: Why It Matters and How to Enable It

One of the most important steps in securing your websites and web applications is enabling Secure Socket Layer (SSL) communication over HTTP Secure (HTTPS). This encrypts traffic bi-directionally between the server and client browser, protecting against eavesdropping and communication tampering.

What doesn’t get discussed enough is the very first communication from the browser to the server. Unless you’re exceptionally paranoid and meticulous about typing “https://” before every page you visit or utilizing a browser plugin such as HTTPS Everywhere (highly recommended), you may for a brief moment in time be communicating with the server over HTTP in what is essentially plain text. This is a small but critical point that is a vector for a number of different attacks.

One example would be connecting to your banking website from the airport’s free WiFi access point—only it’s not the advertised free WiFi, but rather an attacker’s laptop with a wireless card mimicking the open hotspot. It might be configured as a relay, meaning your traffic goes through the attackers machine and then to the real WiFi connection and the wider internet, which can be very difficult—almost impossible—to detect.

To the user, the access point appears as any other. Clever methods such as boosting transmission power of the attacker’s wireless card can make the compromised AP appear closer to your machine, making it automatically choose the attacker’s AP over the real one.

Once connected, an attacker can easily see all HTTP traffic being relayed. This means any messages, emails, or logins that you use on non-SSL sites are visible. HTTPS solves this with the bi-directional encryption, but what happens when you type just “myonlinebank.com” into the address bar?

A creative attacker can see the initial HTTP request for “myonlinebank.com” and redirect your browser to a fake webpage that looks pixel by pixel the same as your real bank. Only difference is that when you type in your credentials, you’re handing them over.

Even more crafty attacks are occuring where your real credentials and sessions are redirected to your bank, only after the attacker has a chance to copy them. In this scenario, you would have no visible way to be alerted to the attack as it happens and it would appear to login normally after a quick redirect.

Enter HSTS

HTTP Strict Transport Security prevents this attack on the server-side by refusing to communicate over HTTP. When you type “myonlinebank.com” the response isn’t a redirect to “https://myonlinebank.com”, instead it is a blanket response “This server does not communicate over HTTP, resend over HTTPS” embedded in the header.

It is then up to your browser to resend the initial communication over HTTPS. This is an important distinction, as the ‘redirect’ in this case happens on the client-side and not the server-side, meaning a potential attacker can’t issue the redirect and has no say over your browser’s next request.

The Basics: Get SSL

Nodeware’s cloud-based dashboard is hosted on Ubuntu servers running Apache2, secured with SSL certificates from Let’s Encrypt, the fantastic free and open Certificate Authority sponsored by the web’s biggest names. The certificates are easy to setup and auto-renew every 90 days.

If you have HTTP sites without SSL, Let’s Encrypt certificates are highly recommended and have helped the larger movement of internet traffic to HTTPS (almost a solid 25% as of today). As an added bonus, Google and other search providers prioritize SSL sites over non-SSL in results.

Once you’ve secured your Apache hosted website with HTTPS, adding the extra security of HSTS is simple.

Go Further: Enabling HSTS

To enable HSTS, you will need to enable the headers module. The “a2enmod” command makes this simple. All commands in this tutorial assume that the user has proper rights, otherwise sudo might be required to make the necessary changes.

1. Run the following command to enable headers:

a2enmod headers

2. Then restart Apache with the following command:

service apache2 restart

3. If your site tends to be busy with current requests, you may wish to use this command instead:

service apache2 graceful

4. Now that you have headers running, edit your Apache configuration files found in /etc/apache2/sites-enabled/, ending in .conf. Add the following to your VirtualHost section for SSL (Port 443) vHost only:

<VirtualHost example.com:443> 
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"

This will send the required headers to any HTTP requests, telling the browser to use HTTPS for the next 2 years worth of requests. This gets reset every request, so it should continue to be a date far in the future provided users of your site return with any frequency.

5. To redirect visitors to the HTTPS version, add the following to your port 80 virtual host configuration:

<VirtualHost *:80> 
ServerName example.com Redirect permanent / https://example.com/

There are other ways to enforce this redirect such as modrewrite, that will redirect to the secure version of the page requested instead of sending them to the root of your server (but we can cover that another time outside of this tutorial).

6. Now, one last restart of Apache using the command below and you’re all set. 

service apache2 restart

Testing Everything

Without a special plugin, it is difficult to see that HSTS worked from the browser. Still, it’s a good idea to make sure your site is still up and serving pages. With that out of the way, let’s verify HSTS is being used:

curl -I https://example.com/

If everything is configured correctly you should see the following output:

HTTP/1.1 200 OK
Date: Fri, 09 Feb 2018 16:00:02 GMT
Server: Apache/2.4.18 (Ubuntu)
Expires: Fri, 09 Feb 2018 16:00:02 GMT
Vary: Cookie,Accept-Encoding
Cache-Control: no-cache, no-store, must-revalidate, max-age=0
X-Frame-Options: SAMEORIGIN
Set-Cookie: csrftoken=[Redacted]; expires=Fri, 08-Feb-2019 16:00:02 GMT; Max-Age=31449600; Path=/; secure
Strict-Transport-Security: max-age=63072000; includeSubdomains;
Content-Length: 2192
Connection: close
Content-Type: text/html; charset=utf-8

The important piece to this is the secure Strict-Transport-Security section, that should match the max-age and subdomain parameters we set earlier, indicating that HSTS is being sent with each request.

Secure by Default

At IGI, we take security seriously and are constantly reevaluating how we deliver Nodeware and our other security solutions. As part of this initiative, all Nodeware servers now not only use HTTPS, but also employ HSTS to deliver a more secure experience to our users.