43

I'm looking for a good way to implement a relatively strong Content-Security-Policy header for my ASP.NET WebForms application. I'm storing as much JavaScript as possible in files instead of inline, but by default, WebForms injects a lot of inline scripts—for things as simple as form submission and basic AJAX calls.

MVC has some simple ways to implement nonces, especially with the help of third party libraries like NWebsec, but I can't seem to find any methods of implementing them with WebForms. I wouldn't even have a problem using hashes if there were a way to predict and retrieve the hash for each .NET injected script tag.

I hate allowing the 'unsafe-inline' value. It feels wrong needing to turn off such a powerful security feature. Is there a reasonable way to implement it in WebForms?

Michael
  • 8,362
  • 6
  • 61
  • 88
Andy
  • 636
  • 1
  • 6
  • 16
  • I did not. I even tried enlisting the help of [Troy Hunt](https://www.troyhunt.com/) and [André Klingsheim](http://www.dotnetnoob.com/) on [Twitter](https://twitter.com/askrenes/status/705471606311800836), to no avail. – Andy May 12 '17 at 16:56

4 Answers4

13

I had the same problem. I'm sad to say this was the best we have done. We basically identified what we use and don't use. We even had to put unsafe-eval in some instructions because we were using third party controls that couldn't work without it. At least we avoid calls to external urls.

default-src 'self'; 
child-src 'self' 'unsafe-inline' 'unsafe-eval'; 
object-src 'none'; 
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google-analytics.com; 
img-src 'self' https://www.google-analytics.com; 
style-src 'self' 'unsafe-inline'
Michael
  • 8,362
  • 6
  • 61
  • 88
MichaelChan
  • 1,808
  • 17
  • 34
8

I wrote an answer here for what to do about all those injected scripts:

If you open up the dev tools in Chrome, you'll likely see a message like

Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'. Either the 'unsafe-inline' keyword, a hash ('sha256-2NqnatcPqy5jjBXalTpZyJMO/0fUaYUb3ePlviUP4II='), or a nonce ('nonce-...') is required to enable inline execution.

If you look carefully at that message, it's telling you what the hash would be: sha256-2NqnatcPqy5jjBXalTpZyJMO/0fUaYUb3ePlviUP4II=

So if you don't want to go the nonce route, you can instead go the hash route and add

Content-Security-Policy: script-src 'self' 'sha256-2NqnatcPqy5jjBXalTpZyJMO/0fUaYUb3ePlviUP4II=' 'unsafe-eval';

You may have to add unsafe-eval in some cases as well for this to work.

Michael
  • 8,362
  • 6
  • 61
  • 88
codeMonkey
  • 4,134
  • 2
  • 31
  • 50
1

Let's start with a simple example:

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Content-Security-Policy" value="default-src 'self'" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

The value of the Content-Security-Policy header is made up of N segments separated by a semicolon. In the example above, we only specify a single segment, saying "only load resources from 'self'". 'self' translates to the same origin as the HTML resource. With this minimum configuration, your HTML is allowed to fetch JavaScript, stylesheets etc. from the same domain that served the HTML referencing the resources. You won't be able to include external scripts from CDNs and similar.

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.

Michael
  • 8,362
  • 6
  • 61
  • 88
Ashutosh B Bodake
  • 1,304
  • 1
  • 19
  • 31
  • 4
    This answer doesn't address the central thesis of the question: ASP.Net injects _inline scripts_ onto the page to work its magic. OP _already knows_ what CSP does. He wants to make the platform work without `unsafe-inline`. – Michael Apr 16 '21 at 16:38
0

We also had to tighten

default-src 'none'; 
script-src 'self' 'unsafe-inline' 'unsafe-eval';
img-src 'self' data:;
style-src 'self' 'unsafe-inline' 'unsafe-eval';
connect-src 'self';
font-src 'self';
frame-ancestors 'none';

This solution works well with ASP.NET WebForms as it still allows inline (no need to extract everything to separate js files) as well as eval's.

Unsafe-Tags are specifically needed to provide better WebForms Functionality in my opinion.

To see if you need any additional/less Restrictions you can use: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy