Enforce SSL and use HSTS in .Net Core: .Net Core security Part I

ssl6

Note – You can find the source code of my sample application here(sample does not include HSTS changes)

You can find my all .Net core posts here.

In these series of posts, we will see how to secure your .Net Core applications.

In this post, we will see how to enforce SSL to your .Net Core applications along with adding HSTS to your .Net production site.

From .Net Core 2.1 onwards, HTTPS is enabled by default in every template which is one of the features of .Net Core 2.1

What is SSL?

  • SSL (Secure Sockets Layer) is a standard security protocol for establishing encrypted links between a web server and a browser in an online communication
  • The usage of SSL technology ensures that all data transmitted between the web server and browser remains encrypted hence secured

To secure your .Net Core applications, you can now enforce the browser to use HTTPS

What is HTTPS?

  • Hyper Text Transfer Protocol Secure (HTTPS) is the secure version of HTTP, the protocol over which data is sent between your browser and the website that you are connected to. The ‘S’ at the end of HTTPS stands for ‘Secure’.
  • It means all communications between your browser and the website are encrypted.

Let us start.

Prerequisite:

  • Visual studio 2017 community edition, download here
  • .Net Core 2.0 SDK from here (I have written a post to install SDK here)

Create the MVC Application using .Net Core 2.0 template in VS 2017

Once you have all these installed, open your Visual Studio 2017 -> Create New Project -> Select Core Web application:

ssl1

Click on Ok and in next window, select Web Application(MVC) as shown below:

ssl2

Visual Studio will create a well-structured application for you.

Enforcing SSL on Controllers

Enforcing SSL on Controllers is very easy. You just need to add RequireHttps attribute above the controller:


[RequireHttps]
public class HomeController: Controller
{}

Enforcing SSL globally

As you might have so many controllers and with Controller enforcing you need to make the changes in so many controllers. There is a different approach where you can enforce the SSL globally by making changes in Startup.cs class.

Add below lines in the ConfigureService method:


public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();

services.Configure(options =>
{
options.Filters.Add(new RequireHttpsAttribute());
});
}

Above code requires all requests to useHTTPS therefore HTTP requests are ignored.

Side Note: Enforcing SSL globally is a good practice and more secure than adding attributes on the controller level. Even if new controllers are added, you would have a headache to add the attributes above all new controllers.

Redirect HTTP to HTTPS

Applications typically need to listen to both HTTP and HTTPS but then it is required to redirect all HTTP traffic to HTTPS.

Add below code in Configure method in Startup.cs class which will redirect all HTTP calls to HTTPS:


public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var options = new RewriteOptions()
.AddRedirectToHttps(StatusCodes.Status301MovedPermanently, 63423);
app.UseRewriter(options);
app.UseMvc();
}

That is it.

Run above application on IIS Express

Please note that if you will run above application on IISExpress then it will throw an error.

This error comes because you have not yet configured your IIS Express settings to allow SSL. You need to Enable SSL.

For that open the properties of the application and then open Debug tab.

Under Web Server setting, check the Enable SSL checkbox as shown below:

ssl3

Note – You can find the source code of my sample application here.(sample does not include HSTS changes)

HTTP Strict Transport Security (HSTS)

Sometimes just redirecting HTTP to HTTPS is not enough, so there is need of something which can instruct the browsers to always access the site via HTTPS.

What is HSTS?

  • HTTP Strict Transport Security (HSTS) is a web security policy mechanism which helps to protect websites against protocol downgrade attacks and cookie hijacking
  • It allows web servers to declare that web browsers (or other complying user agents) should only interact with it using secure HTTPS connections, and never via the insecure HTTP protocol
  • Typically used only in non-dev scenarios

For example, when you try to access Google with http://www.google.com, the browser will give us 307 status code and will redirect http to https:

ssl4

For this, we need to tell the application to send below header to the browser when the first time application hits the browser:

Strict-Transport-Security: max-age=31536000

Important Note – The .Net team has announced  HSTS middleware with .Net Core 2.1 that supports options for max age, subdomains, and the HSTS preload list. Currently, there are not any straightforward instructions on how to use this with .Net Core 2.1 so we will use NWebSec for HSTS.

Update on 1st March 2018 – .Net Core 2.1 preview 1 is finally out and now the things are clear regarding the use of HSTS with .Net Core. More details here.

Just need to add below lines for HSTS:

app.UseHsts();

We can add some code to the .Net Core application which will do above thing for us.

NWebsec lets you configure quite a few security headers.

Add NWebsec.AspNetCore.Middleware from the Nuget:

ssl5

Once the Nuget package is installed, add below line of code under Configure method:


app.UseHsts(h=> h.MaxAge(days:365)

Then, You need to submit your domain details on this site HSTS Preload site 

and after that add preload as shown below:


app.UseHsts(h=> h.MaxAge(days:365).preload());

Important Note: Note that once you do this, the browser will refuse non-secure requests for your domain, so the only https version of your site will be called. But somehow if your site would not support https in the future then your site would not be accessed once you make above configuration with HSTS. Use it carefully.

Hope it helps.

 

 

 

 

26 thoughts on “Enforce SSL and use HSTS in .Net Core: .Net Core security Part I

  1. I believe your code listed under the Redirect HTTP to HTTPS section is missing a part. It should be:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    var options = new RewriteOptions()
    .AddRedirectToHttps(StatusCodes.Status301MovedPermanently, 63423);
    app.UseRewriter(options);

    Like

  2. I believe your code in the Redirect HTTP to HTTPS section is missing a necessary line. It should be the following:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    var options = new RewriteOptions()
    .AddRedirectToHttps(StatusCodes.Status301MovedPermanently, 63423);
    app.UseRewriter(options);

    Liked by 1 person

    1. Oh god, yes you are right Caleb. Important code line with the end bracket was cut somehow. Thanks a lot for pointing this. I really appreciate this.

      Like

  3. One thing I don’t understand, though: Why is this the responsibility of the framework? Shouldn’t this be purely implemented in the IIS?

    Like

  4. One thing I don’t understand, though: Why is this the responsibility of the framework? Shouldn’t this be purely implemented in the IIS?

    Like

    1. Hey, sorry for late reply. Yes I agree with you and I guess we can do that using IIS as well. But still some configurations are required in the framework.

      Like

    2. When you have an application that is deployed on multiple platforms you might end up with a multiple of webservers. IIS, Nginx, plain kestrel etc. From a business to customers perspective it is wise to do it in the application middleware so a deployment never ends up with a possible vulnerability. As .NET Core is platform independent you might not know to what platform it might be deployed. So unless there is only one deployment that is managed by yourself, best practice is to do it from the app.

      Liked by 1 person

    3. Great question,

      The foremost reason to do it from the app middleware is to ensure that deployment will not leave room for vulnerabilities.

      Let’s say you have an application that you host in the cloud but is also deployed in a customer’s cloud, or maybe even on premises and you’re not the one deploying the app. When the person deploying doesn’t take care of security headers like HSTS the customer might end up with a vulnerable deployment. From my experience the customer will point his finger at you for not supplying a secure app.

      So for a small effort in your middleware you end up not being dependent on the deployment for security. Specifically for HSTS you force the person deploying to use a valid certificate because you only allow HTTPS.

      Cheers

      Liked by 1 person

      1. Wow, very nice explanation Bert. You covered almost everything. Our code should be smart enough to work in any environment. Thanks a lot for your comment.

        Like

  5. I got it working in Edge. Chrome changes the HTTP to HTTP on port 63009, but when I try HTTP on port 44320, it just hangs.

    Also, cannot get any redirection working with IIS with any browser.

    Like

      1. I have no idea. Redirection doesn’t work; it just hangs in both browsers when project runs on IIS. I don’t even know where to start.

        Like

Leave a comment