Content-Security-Policy in ASP.NET MVC
This is the second post in a series about ASP.NET security.
In the previous post, Improving security in ASP.NET MVC using custom headers, I skipped talking about the
Content-Security-Policy header entirely. It is not harder to implement, but since it requires a bit more explanation to understand, the header now has its own post. As a small teaser, I will show you an easy way to implement the
Content-Security-Policy header using elmah.io in the next post.
Content-Security-Policy header, is a HTTP response header much like the ones from the previous post. The header helps to prevent code injection attacks like cross-site scripting and clickjacking, by telling the browser which dynamic resources that are allowed to load.
Let's start with a simple example:
<system.webServer> <httpProtocol> <customHeaders> <add name="Content-Security-Policy" value="default-src 'self'" /> </customHeaders> </httpProtocol> </system.webServer>
value of the
Content-Security-Policy header is made up of x segments separated by a semicolon. In the example above, we only specify a single segment, saying "only load resources from self".
Let's say that you host everything yourself, but want to include jQuery from cdnjs. You would need the following value to allow the browser to make requests outside your origin:
<add name="Content-Security-Policy" value="default-src 'self' https://cdnjs.cloudflare.com" />
Remember the segments I talked about? You can configure which domains to load different kind of resources from using a range of different
*-src keys like this:
<add name="Content-Security-Policy" value="default-src 'self'; script-src 'self' https://cdnjs.cloudflare.com; style-src 'self' https://maxcdn.bootstrapcdn.com" />
This configuration let your web application load resources from its own domain plus scripts from
cdnjs.cloudflare.com and stylesheets from
maxcdn.bootstrapcdn.com. The combinations are endless, so check out the documentation on Mozilla.org for details.
Would your users appreciate fewer errors?➡️ Reduce errors by 90% with elmah.io error logging and uptime monitoring ⬅️
Chances are, you don't have a document where every dependency of your website is written down. Implementing the
Content-Security-Policy header therefore takes time and digging. The best approach is to start limiting resources to
self and testing the entire web application and see if it works or not. If running with developer tools open in Chrome or whatever browser may be your favorite, the Console will tell you when your web app tries to fetch or execute code not allowed in the header:
Another approach to catching all needed configuration, is to start by using an alternative header named
<add name="Content-Security-Policy-Report-Only" value="default-src 'self'" />
By adding this header instead of
Content-Security-Policy, the browser will keep telling when something isn't allowed, but allow it anyway. This way you can keep an eye on the console, when running your website in production. When all error messages in the console are gone, you switch back to the original header.
Constantly keeping an eye the console and trying to touch all pieces of code in your application can be hard. In Storing Content-Security-Policy reports in elmah.io, I will show you how to use elmah.io to monitor the output of the
elmah.io: Error logging and Uptime Monitoring for your web apps