DEV Community

Thomas Ardal
Thomas Ardal

Posted on • Edited on • Originally published at blog.elmah.io

Improving security in ASP.NET MVC using custom headers

I recently discovered securityheaders.io, produced by the hyper productive Scott Helme. securityheaders.io scans your website and make suggestions to which HTTP response headers to add in order to improve security.

securityheaders.io

This post is a sum up of not only elmah.io headers added recently, but how to make it more difficult for hackers to compromise your ASP.NET (MVC, Web API, Core) website in general. In the following paragraphs, I have listed a number of HTTP headers that are easily configured and that everyone should implement.

X-Frame-Options

The X-Frame-Options header ensures, that hackers don't iframe your site, in order to trick you into clicking links which you never intended to. If you are using ASP.NET MVC 5 or newer, this header is added automatically. Adding the header in previous versions or other web frameworks is easy using web.config:



<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="X-Frame-Options" value="DENY" />
    </customHeaders>
  </httpProtocol>
</system.webServer>


Enter fullscreen mode Exit fullscreen mode

In this example, I deny any possibility of iframing the website. If you are using iframes on the same domain, you can change the value to SAMEORIGIN.

X-Xss-Protection

The X-Xss-Protection is a feature implemented in most modern browsers, which will stop loading the page when a cross-site scripting attack is detected. Adding the header happens through web.config as well:



<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="X-Xss-Protection" value="1; mode=block" />
    </customHeaders>
  </httpProtocol>
</system.webServer>


Enter fullscreen mode Exit fullscreen mode

The value if 1 simply marks the protection as enabled.

X-Content-Type-Options

To avoid MIME type sniffing, you can add the X-Content-Type-Options header. This makes it harder for hackers to guess the right mime type, by inspecting the content. Adding the header is easily done through web.config:



<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="X-Content-Type-Options" value="nosniff" />
    </customHeaders>
  </httpProtocol>
</system.webServer>


Enter fullscreen mode Exit fullscreen mode

Referrer-Policy

Browsers automatically add the Referer header, when a user clicks a link on your site. This means that a linked website will be able to see where the users are coming from. While this is a great feature for Analytics, you may have sensitive information in your URLs, which you don't want to forward to other domains. To remove the referrer entirely, add the following header to web.config:



<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Referrer-Policy" value="no-referrer" />
    </customHeaders>
  </httpProtocol>
</system.webServer>


Enter fullscreen mode Exit fullscreen mode

In real life, you may want another value for Referrer-Policy. Removing the referrer entirely makes it impossible to see the internal traffic flow on your website. Check out Referrer-Policy on mozilla.org for a list of possible values.

X-Permitted-Cross-Domain-Policies

To restrict Flash components to make cross-origin requests, you should disable it entirely (unless you are using Flash of course). To do so, add the X-Permitted-Cross-Domain-Policies to web.config:



<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="X-Permitted-Cross-Domain-Policies" value="none" />
    </customHeaders>
  </httpProtocol>
</system.webServer>


Enter fullscreen mode Exit fullscreen mode

Strict-Transport-Security

If you haven't implemented HTTPS on your website, you should. After doing so, you can prevent any communication happening over HTTP using the Strict-Transport-Security header:



<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains" />
    </customHeaders>
  </httpProtocol>
</system.webServer>


Enter fullscreen mode Exit fullscreen mode

The max-age value tells browsers to use this setting for the specified number of seconds. In this case a year. The includeSubDomains part can be excluded if you are hosting non-HTTPS websites on subdomains (like a blog).

X-Powered-By

The X-Powered-By header is automatically added by ASP.NET. To make it less obvious which technology you are using to host your website, you should remove this header through web.config:



<system.webServer>
  <httpProtocol>
    <customHeaders>
        <remove name="X-Powered-By" />
    </customHeaders>
  </httpProtocol>
</system.webServer>


Enter fullscreen mode Exit fullscreen mode

X-AspNetMvc-Version

Much like X-Powered-By, X-AspNetMvc-Version is a header automatically added by the framework. To avoid telling hackers that you use MVC and which version, you should remove it. X-AspNetMvc-Version cannot be removed through web.config, but you can disable it from code. Add the following to your Startup.cs or Global.asax.cs:



MvcHandler.DisableMvcResponseHeader = true;


Enter fullscreen mode Exit fullscreen mode

Server

ASP.NET also reveals the server hosting the application. If a hacker knows that you are using IIS, this narrows the number of weaknesses that he/she needs to try. To remove the Server header, remove it from code in either a filter or through Global.asax.cs:



protected void Application_PreSendRequestHeaders()
{
    if (HttpContext.Current != null)
    {
        HttpContext.Current.Response.Headers.Remove("Server");
    }
}


Enter fullscreen mode Exit fullscreen mode

Feature-Policy

The Feature-Policy header, is a recent addition to the range of security-related headers. When specifying the header, you tell the browser which features your site uses or not. This is a great feature, especially if you embed other websites. To add the header, make the following change in web.config:



<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Feature-Policy" value="accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'" />
    </customHeaders>
  </httpProtocol>
</system.webServer>


Enter fullscreen mode Exit fullscreen mode

Here, we tell the browser that our site shouldn't allow use of the accelerometer, camera, and more. Which features you need to add, totally depend on your site. For more information, check out the specification.

Content-Security-Policy

Using the Content-Security-Policy header requires a bit more explanation. Check out the next post in this series for details: Content-Security-Policy in ASP.NET MVC.

Would your users appreciate fewer errors?

elmah.io is the easy error logging and uptime monitoring service for .NET. Take back control of your errors with support for all .NET web and logging frameworks.

➡️ Error Monitoring for .NET Web Applications ⬅️

This article first appeared on the elmah.io blog at https://blog.elmah.io/improving-security-in-asp-net-mvc-using-custom-headers/

Top comments (6)

Collapse
 
dotnetcoreblog profile image
Jamie

Security headers are things of the best things you can add to a site to increase the security. They have a low time vs benefit cost, and they can streamline your webapp building process. The majority of this line MageCart can be prevented by spending 20 minutes writing a CSP, for example.

Plus, if you're team then up with something online Report URI (also created by Scott Helme) you'll get notifications when someone makes a change to your webapp which violates the security headers.

And for those of an ASP NET persuasion, I have a middleware component specifically for helping you get started called OwaspHeaders.Core

Collapse
 
thomasardal profile image
Thomas Ardal

Good input, Jamie. I can see that quite a lot happened since I originally wrote that post. I also use Report URI now. Maybe I should give the post an overhaul :) Thanks!

Collapse
 
dotnetcoreblog profile image
Jamie

I've use Feedify and QR Codes in one post (shortly before the first instance of MageCart), a discussion on OWASP, and how it could ruin your company or brand as examples about why folks should look into this in the past. Especially since it's a relatively easy problem to solve.

I feel like you could make it into a series of posts. Even as someone who knows this stuff and how to implement it, I'd love to read a series where the author goes from "here's the theory" through "here's my initial plan", to "here's why my assumptions were wrong" (because with CSP, they will be) to "here's the finished headers for my site".

A lot of folks who write about headers tend to focus on the first and last step here, but devs need to know that the middle part is hard. Maybe you could cover that, or nominate someone to do so. Maybe I'll take a whack at it with an app for one of my clients 😉

Collapse
 
yazidaqel profile image
yazid aqel

Very detailed post with so much information around http headers in .net runtime applications, thanks a lot

Collapse
 
ianrathbone profile image
Ian Rathbone

Thanks this is very useful, I've not seen this site before so will certainly be using it!!

Collapse
 
thomasardal profile image
Thomas Ardal

Thanks. Appreciate the feedback :)