Sitecore Security #2: Secure connections and how to force the browser to use the secure connection
Secure connections? Why would I even bother? It’s expensive, slow, complex and I’ve got a firewall anyway? On the SUGCON in Copenhagen I showed off how easy it is to intercept, modify and redirect unencrypted traffic and what can be done against this threat. This blogpost is all about why you should serve your website always and fully over HTTPS and how the browser can be forced to use this HTTPS connection. This blogpost will not show off how to configure HTTPS and will not tell about all the benefits of https. The technique to achieve this is bu adding a HSTS header for your domain, google recently announced that they will introduce this for the complete www.google.com domain as well!
Note: Some other great articles have been written about this subject, but I intentionally wrote this article to reach out the Sitecore (and SharePoint) community!
The configuration is included in the blogpost below, it will also be released as a XDT as part of a bigger security project
It’s not only about the login page
As the Sitecore hardening guide describes:
Make the login page available only to SSL requests
This is not true. This guideline suggests that the login page is the only page taht needs to be exposed via https, but e_very_ page should be served over SSL. And when SSL is mentioned, the technique that should be spoken about is TLS, Transport Layer Security. SSL is completely insecure, while TLS is the improved version of SSL and is nowadays on version 1.2.
Why is this not true? When people are connected to insecure Wi-Fi networks data can often easily be sniffed, which means, all traffic can be captured by other devices. This means that all the data that flows over the (virtual) wire, can be captured. When the data is send over HTTP, this data is unencrypted and can by the persons who are capturing this traffic. Personal interests, details, and-so-forth can be captured. Imagine what happens when login credentials would be send over HTTP?
Things get even worse, when someone manages to intercept the connection, which is called a “Man in the Middle”. This person would be able to intercept the traffic, monitor it, transform it or even redirect it to another location, while the visitor wouldn’t have any indication on what’s currently happening.
During my session on the SUGCON in Copenhagen, I brought a small device with me which is called a “rogue access point”, which tries to trick devices to automatically connect to this wireless access point. See what happened in a few minutes, before my session even started and almost no visitors were in the room:
You have been #robbertHACK 'ed- #SUGCON @BasLijten @seanholmesby - ps I removed the Mac address- you r welcome! pic.twitter.com/qS9dBbkK6m
— Akshay Sura (@akshaysura13) April 25, 2016
But my credentials are posted over HTTPS, right?
That’s true. That might be true. But at the moment that someone would be able to intercept the initial request for serving the loginpage, which would be over HTTP, that person would be able to alter or redirect that request and prevent the initial request from ever landing on it’s initial destination:
I could redirect traffic to any site, fishing email, passwords, et cetera.
Forcing the browser to use HTTPS
To prevent this kind of attack, even the initial request, must be send over HTTPS. Most visitors enter the address of the website that they want to visit in their browser:
mention that no protocol has been specified. Browsers initially send this request over HTTP and BAM: you’re vulnerable.
To solve this, the “Strict-Transport-Security” header can be used. When this header has been set, the browser will know that they should never visit that website over HTTP, but always use the HTTPS variant of the address. Pretty much all major browsers support this header.
Trust On First Use (TOFU)
Please note that this solution is a TOFU-solution – Trust-On-First-Use. When you have never, ever visited this website, it’s very likely that the website will be requested over HTTP - At this part, the visitor still vulnerable and the request could be intercepted/altered/redirected. But let’s assume that this first request is safe.
Setting the Http Strict-Transport-Security header (HSTS)
After this initial request, The website should 301-redirect the request immediately to the https-equivalent, together with the following header: Strict-transport-security: max-age=31536000. The browser will cache this value and now knows that for every request, even if it has been initiated over http, the secure equivalent has to be used.
To show off what exactly happens, I included that images below:
The inital request
[caption id="attachment_18941" align="alignnone" width="605"] The initial request is over http and responds with a 301 -> https://insurco\[/caption\]
The page gets redirected
[caption id="attachment_18951" align="alignnone" width="605"] The page that is served securely, has the strict-transport-security header added to the response[/caption]
The next time the user tries to visit the webpage over http
[caption id="attachment_18961" align="alignnone" width="605"] An internal redirect (status code 307) to the secure page, no network traffic is involved in this step[/caption]
Cool, I want this, how do I do that?
First, a secure connection is needed. After that one, you can configure your proxy to inject this header on every request, or configure the IIS Rewrite module of Microsoft Internet Information Server to use this one. My advice would be to configure this rule on the the proxy, but I you don’t have any access to this proxy or it takes too long, it’s also possible to configure IIS using the following rule. It forces the website to be visited over https and sends the Strict transport security header along with it.
<rewrite> <rules> <rule name="Http Redirect to HTTPS" enabled="true" stopProcessing="true"> <match url="(.\*)" ignoreCase="true" /> <conditions logicalGrouping="MatchAny"> <add input="{HTTPS}" pattern="off" ignoreCase="true" /> </conditions> <action type="Redirect" url="https://{HTTP\_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" /> </rule> </rules> <outboundRules> <rule name="Add Strict-Transport-Security when HTTPS" enabled="true"> <match serverVariable="RESPONSE\_Strict\_Transport\_Security" pattern=".\*" /> <conditions> <add input="{HTTPS}" pattern="on" ignoreCase="true" /> </conditions> <action type="Rewrite" value="max-age=31536000" /> </rule> </outboundRules> </rewrite> ```
# Securing the Initial request
It is possible, for several browsers, to secure the initial request as well. Most major browsers work with a HSTS preload list. A domain can be submitted to this list on https://hstspreload.appspot.com/ which will put into the preload list of all browsers.
## Be cautious! Things may break!
This preload list requires a very important setting for the preload list: _includeSubdomains._ This setting forces that _every_ subdomain should be served over https as well. If any subdomains exist that are only accessible over HTTP, they will break.
# Summary
Serving sites over HTTP is _not_ safe. Although you might only serve content, attackers may use unsafe connections to inject malicious forms, redirect requests, phish usernames and passwords. To force browsers (and thus, their users) to connect over HTTPS, the Strict-Transport-Security header should be used.