HSTS In IIS

Adrian Jenkins
6 min readJul 25, 2022

--

What is HSTS?

The HTTP Strict-Transport-Security is a response header that tells a browser that it should only access the site through HTTPS.

Why do we need HSTS?

HTTP Strict-Transport-Security header is used to prevent SSL Stripping attack. Basically, a man-in-the-middle that intercepts your HTTP request.

We rarely type“https://” when we browse to a website. Besides, sometimes, we visit sites through a link without even knowing which protocol it is using underneath.

We want to avoid HTTP requests, as this is an insecure protocol. In order to avoid this, HSTS header was created. This header is sent through HTTPS, once a client connects to the site through HTTPS, the site will send HSTS header with a specific time.

From now on, the Browser will memorize to only connect through HTTPS for the specified time. If you try to connect through HTTP, the Browser will do a 307 — Internal Redirect to the HTTPS version of the site.

Keep in mind this header should/is only sent through HTTPS, meaning the user has to do at least one request to the HTTPS version of the site in order for this header to take effect.

Once the time sent by the header expires, the Browser will forget that it should only access the site through HTTPS. Making HTTP requests possible again.

Typically, servers have redirection from HTTP to HTTPS, so once the HSTS header expires, the next request in HTTP is redirected to HTTPS and the header will be sent and Browser will know that it should only access the site through HTTPS.

Remember, the Browser will only honor HSTS header in HTTPS requests.

Now, you might think: “well, this header expires. Sure you have an HTTP redirection to HTTPS, so that the header will be sent. But you are still vulnerable in that first HTTP request”. You are right, we will talk about this later on.

Structure of HSTS Response Header

  • max-age: time in seconds that the Browser will remember to always connect through HTTPS to a site.
  • includeSubdomains: optional directive that determines if this rule should apply to subdomains as well.
  • preload: we will get to this directive later on.

Example:

  • Strict-Transport-Security: max-age=31536000; includeSubDomains

What Exactly Do We Need To Enable HSTS?

  1. Send this response header with the directives and values that you want.
  2. HTTPS support for our website with the correct certificate.
  3. As we need to make sure that the user visits the HTTPS version of our website at least once, having HTTP redirection to HTTPS is expected.

One advantage of HSTS is that it won’t let you click through certificate warnings. So, if the certificate is not correct, HSTS won’t work.

Let Us Experiment With HSTS

#1 Sending HSTS Response Header — Correct Certificate — No HTTP To HTTPS Redirection

HTTP Request to “awesomedefaultwebsite.space” it does nothing as we need to visit the HTTPS version of the website at least once.

HTTPS request to “awesomedefaultwebsite.space”. HSTS sent and Browser will remember to only make HTTPS request for this website for the following 120 seconds.

HTTP Request, Browser know to only connect in HTTPS. The Browser will do an internal redirect and make a request to the HTTPS versions of the site.

Once 2 minutes have passed, HTTP requests will be possible, and user will need to visit the HTTPS version of the site at least once.

#2 Sending HSTS Response Header — Correct Certificate — HTTP To HTTPS Redirection

HTTP request will be redirected to HTTPS and HSTS header will be sent.

HTTP request will get an internal redirect and will consult the HTTPS version of the site.

Once the header expires, this dance will keep on happening as, with our redirect, we will make sure user consult the HTTPS version and will get the response header.

#3 Sending HSTS Response Header — Incorrect Certificate — No HTTP To HTTPS Redirection

I will change the certificate of my site just to understand that HSTS won’t work if the certificate is not the appropriate one. I will also disable my HTTP to HTTPS redirection.

A normal HTTP request would get me my site in HTTP. Nothing new here.

Let us visit HTTPS so we get the HSTS response header.

The Browser should remember, for the next 120 seconds, to only connect through HTTPS to my site. However, as the certificate is not valid, the Browser won’t honor the HSTS, and no internal redirect to the HTTPS version of the site will happen.

It is a good practice to have HTTP to HTTPS redirection. However, eventually an HTTP connection will be made. That is, when HSTS header expires. This is a problem. The solution for this is the “preload” directive. Browsers have a built-in static list of millions of sites that should always be connected through HTTPS.

To get included in the HSTS list, you can apply here. Keep in mind, you should be absolutely sure your website fully supports HTTPS. You sure can ask to be removed from the list, but this can take a while.

How To Enable HSTS In IIS

IIS 10.0 Version 1709

First make sure you have the HTTPS binding with the appropriate certificate.

Now, go to your website > action pane > configure > hsts

You can modify the siteDefaults so all new sites created have hsts.

IIS 10.0 And Earlier Versions

Understanding that HSTS is to send this response header and having a HTTP to HTTPS redirection (as a good practice), there are a couple ways we can achieve this.

We will do it with URL Rewrite module. This can be done at Server or Site level.

First, we need an Inbound redirection rule from HTTP to HTTPS and then we need an outbound rule to add this response header.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="HTTP To HTTPS" enabled="true" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="^off$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:0}" redirectType="Permanent" />
</rule>
</rules>
<outboundRules>
<rule name="Add Strict-Transport-Security when HTTPS">
<match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
<conditions>
<add input="{HTTPS}" pattern="^on$" />
</conditions>
<action type="Rewrite" value="max-age=31536000l;includeSubDomains" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>

If you want to reset the “max-age” either clear browser data or resend the header with a value of “0”.

Resources

--

--