Correctly using hash with content security policy (CSP) - content-security-policy

I am trying to use a hash with my content security policy...
Below are two example errors in my console:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' apis.google.com cdn.iubenda.com cdnjs.cloudflare.com www.googletagmanager.com". Either the 'unsafe-inline' keyword, a hash ('sha256-oKmCrr+GWRARSXYeVJshOWETr0oqOtt73CNO8efpujQ='), or a nonce ('nonce-...') is required to enable inline execution.
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' apis.google.com cdn.iubenda.com cdnjs.cloudflare.com www.googletagmanager.com". Either the 'unsafe-inline' keyword, a hash ('sha256-pS4Uy3ilo+JLn8IadtJGfyO9z7jqIrGUONfEUDLxoPk='), or a nonce ('nonce-...') is required to enable inline execution.
Here is the corresponding content security policy directive:
add_header Content-Security-Policy "default-src 'self'; script-src 'self' apis.google.com cdn.iubenda.com cdnjs.cloudflare.com www.googletagmanager.com; style-src 'self' fonts.googleapis.com; img-src 'self' cdn.shortpixel.ai secure.gravatar.com; font-src 'self' fonts.googleapis.com fonts.gstatic.com";
Specifically in this example:
script-src 'self' apis.google.com cdn.iubenda.com cdnjs.cloudflare.com www.googletagmanager.com;
From what I gathered from reading the CSP guide on hashes, I should be able to add the hash as per my console to the directive...
The easiest way to generate it is to just open the developer tools console and it will output what the expected hash of your script was in the console error message.
But if I modify my directive to include the hash (example below), I still get the same error in console (obviously with a different hash).
script-src 'self' apis.google.com cdn.iubenda.com cdnjs.cloudflare.com www.googletagmanager.com 'sha256-oKmCrr+GWRARSXYeVJshOWETr0oqOtt73CNO8efpujQ=';
How exactly is the correct way to hash a CSP directive? And why are there multiple errors for the same directive, is this basically one for each domain specified? Should one hash cover all the domains specified?
Not really sure how I should be doing this.

From what I gathered from reading the
content-security-policy.com/hash/ CSP guide on hashes, I should be
able to add the hash as per my console to the directive...
Yeah, it's working only "theoretically", the "practice" is more hard. Yes, Google Chrome calcs hashes, but you need to read the error message carefully to determine what is really blocked: inline script, javascript: navigation or inline event handler. Because each of these have own way how to fix.
- Inline scripts can be just allowed by 'sha256-VALUE' token.
- to allow javascript: navigation and inline event handlers you need to use 'sha256-VALUE' tokens with 'unsafe-hashes'. And not all browsers support 'unsafe-hashes' for javascript: navigation as for now.
But if I modify my directive to include the hash (example below), I
still get the same error in console (obviously with a different hash).
Why do you stopped? I see you use www.googletagmanager.com (GTM), do you think GTM has only one inline script? You allowed the parent script, it began to load the child ones, so you need hashes for both.
You can use parent script hash + 'strict-dynamic' token to allow all the childs ones, but it does not work in Safari as for now.
At the final you will get a lot of hashes for all inline scripts. Bad thing is that GTM and others can time to time change content of it inline scripts, so you have to add a new hashes and to remove obsoletes. But you don't know which hash to which script belongs.
Therefore the preferable way is to use 'nonce-value' for any inline scripts, all the more since GTM distributes 'nonce' to all inline scripts except Custom HTML Tags. For Custom HTML Tags(if used) you can use hashes, because those scripts is under your control.
It's better to investigate all inline scripts manually before decide how it easier and reliable way to allow them.
PS: GTM is a hard nuts for CSP because GTM can be used to inject a open list of inline/external scripts. And if use the custom JavaScript variable names are used for the «Custom HTML tag», it required to allow 'unsafe-eval'.
You can test your GTM ID for what additional scripts it loads and which CSP is enough for it.

Related

Working on CSP headers, seeing console browser as Refused to execute inline script because it violates the following Content Security Policy directive

#console browser issue for Content security Policy
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-9X08/o2ns8hEbTzT0V1Xyn6yYc8qftFOKmH3KNb8dWo='), or a nonce ('nonce-...') is required to enable inline execution.[enter image description here][1]
#Image of the error
[1]: https://i.stack.imgur.com/7R9sp.png
Code written for CSP
frame-ancestors 'self' https:
script-src 'self';
object-src 'none';
base-uri 'none';
style-src 'self' fonts.googleapis.com 'unsafe-inline';
media-src *;
img-src 'self';
It seems the error indicated there's issue with using inline-script.
which looks like
<script>
your codes
</script>
If you're going to use inline script, add 'unsafe-line' to script-src directive.
Current setting only allows scripts that's source of your domain.
ex)
<script src="/yourDomain/public/yourScript.js">
Your script-src directive of 'self' only allows scripts to be loaded as script files from the same domain. Your page also has inline scripts that need to have permission in the CSP to run. You have a few choices:
Move the script code to a separate .js file hosted on the same domain. If you use a different host you'll need to allow that host in your script-src directive.
Add 'unsafe-inline'. This will allow ALL inline scripts, which will pretty much remove the XSS protection that CSP is able to give.
Add the suggested hash value 'sha256-9X08/o2ns8hEbTzT0V1Xyn6yYc8qftFOKmH3KNb8dWo=' to script-src allowing this one script. This is a good solution if there are only one or a few inline scripts to allow.
Add a nonce. Nonces should change on every pageload and are a good solution for dynamic scripts if you are able to inject nonces correctly.

Content Securiy Policy (CSP) for multi-tenant apps

Trying to set a decent CSP policy for a multi-tenant webapp.
Since users can add content themselves, whitelisting or blacklisting certain domains is impossible.
It is possible to white list the default src's the app itself is using, but for other resources, it must be a wildcard, for example -
Content-Security-Policy: default-src 'self' trusted.com *.trusted.com ; img-src *; media-src *; script-src *; object-src *; font-src *; style-src *; frame-src *
I guess the actual question is - would it be efficient to set up such a CSP header versus not setting one at all?
If your users can add their own javascript as content by design, your application is vulnerable to XSS anyway. If they can't, then you should remove script-src * and replace maybe with self. This would help prevent some XSS attacks which should probably be your most important concern.
The same applies to object-src, does that need to be * too? It shouldn't be. The rest of the * values are I think present less risk, modern browsers will not normally run javascript from those.
The third thing that comes to mind is clickjacking. Do these pages ever have to be displayed in a frame? If no, then it's easy, you could set frame-ancestors to none, or self if you use iframes on your own origin. If your users do want to embed their page in an iframe, you could for exmaple have them register their origin when they want to have the iframe, and your application could dynamically generate a suitable frame-ancestors csp based on the origin of the current request.

What is the difference between 'self' and 'unsafe-inline' in Content-Security-Policy?

I am trying to understand how Content Security Policies can mitigate XSS-Attacks on Web-Servers. Suppose there is a XSS-vulnerability in an User-Input-Field. It can be used to induce Javascript, such as alert(1) but it can also induce much more serious input, such as a script to exfiltrate Cookies.
When i tried to implement a Content-Security-Policy on that Webserver, i have noticed that both
script-src 'self'
as well as
script-src 'unsafe-inline'
prevent the Cookie exfiltration, however 'self' also prevents alert(1) and unsafe-inline doesnt
I am not an expert to Web Engineering, so i do not know what inline or self even refers to. What do they refer to and what are the similarities and differences between the two and how does that relate to the results i got, when i tried to secure my webserver?
'self' is just a mnemonic (token) for self domain of website.
For example, the website is accessible as http://example.com, http://www.example.com, https://example.com, https://www.example.com. http://example.com:8080 etc.
Therefore you have to specify all these host-sources in the script-src directive, because you do not know via which URL user will access your website.
Alternatively you can just specify 'self', it will mean:
if user access webpage as http://www.example.com, browser will substitute this source instead of 'self'.
if user access webpage as http://example.com:81, browser will substitute this source instead of 'self'.
Note that it's better to have relative Urls in the HTML for 'self' token usage. If user acces webpage as http://www.example.com and in HTML code is using <script src='http://example.com/js/jquery.min.js'> - the script loading will be blocked.
In the connect-src directive the 'self' token additionally allows ws://example.com and wss://example.com in the CSP3-compatible browsers.
'self' is safe because it does not allow XSS via injection of inline scripts or third-party scripts.
'unsafe-inline' it's just a token which allows 3 kinds of inline scripts in the webpage.
'unsafe-inline' is unsafe because it allows XSS through script injection.

IIS custom header "Content-Security-Policy" is overwritten

I have currently an issue with a SharePoint web application, where all websites return a response header content-security-policy: default-src 'self'; object-src 'none'; form-action 'self', which breaks the website's view using Chrome or Firefox, as styles won't be applied and Javascript won't be executed.
Console-Log
Refused to execute inline script because it violates the following Content Security Policy directive: default-src 'self'.
Either the 'unsafe-inline' keyword, a hash ('sha256-WFRyoBrQbrYtLpGIdyBszDzxQni3b0V/wUirab0OhKM='), or a nonce ('nonce-...') is required to enable inline execution.
Note also that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
The problems only occurs if the websites are addressed using HTTPS. I already checked the HTTP Response Headers in IIS. content-security-policy is not specified. If I add it myself, it gets overwritten and is not sent in the response header. There are only two solutions installed, which do not mess with the response headers.
Has anyone an idea what else could change the custom response header and overwrite the one defined in the web.config? Or is there an other way to change the Content-Security-Policy?
I tested changing the IIS Response Headers by configuring the "CustomHeaders"-section in the web.config, by writing custom IIS modules, which modified the headers using the request lifecycle, and also by writing additional rules with the URL Rewriting tool. Nothing worked...
In the end we found out someone extended the firewall, which onwards would add new header and overwrite my changes of the HTTPS response. Mystery solved :)
In my case, I was asked by Network and Information Security Team to add the Content-Security-Policy: default-src 'self'; header in my IIS 8.5 SharePoint Server 2016 Publishing website which affects all the system pages and the browser refuses to execute the scripts and in console we got this error
Refused to execute inline script because it violates the following Content Security Policy directive: "default-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-HU8dCwZsqh4m8QG0y6qanyzPx1d6YSGHuAN0QXmxZvw='), or a nonce ('nonce-...') is required to enable inline execution. Note also that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
I then change the header to Content-Security-Policy:frame-ancestors 'self'; and it resolves the issue.
I actually got this from the JohnC's Answer that helps me resolving the issue

Content-Security-Policy: default-src *

I started exploring Content Security Policy on a website which uses inline scripts and other crimes. I configured CSP per header field like this:
content-security-policy: default-src *; frame-ancestors 'self'; style-src 'self' 'unsafe-inline' fonts.googleapis.com cdn.jsdelivr.net *.stripe.com; report-uri https://sentry.io/api/x/csp-report/?sentry_key=y
My problem now is that the browser complains with the following message:
Refused to execute inline script because it violates the following Content Security Policy directive: "default-src *"
I read the documentation for default-src <source> which states that <source> can be one of the following sources:
<host-source>
<scheme-source>
'self'
'unsafe-inline'
etc.
It seems to me that the asterisk can only be used for host sources. But what else can I do since only one <source> seems to be allowed? default-src * 'unsafe-inline' would not be compliant, right?
My goal basically is to use a minimal CSP configuration which works (and can be embedded via iframe). I am aware that it's best practice to go on with specific rules.
It seems to me that the asterisk can only be used for host sources.
Yes
But what else can I do since only one <source> seems to be allowed?
Multiple <source>s are allowed.
default-src * 'unsafe-inline' would not be compliant, right?
It’s compliant.
You can use https://cspvalidator.org/ to check. Or https://csp-evaluator.withgoogle.com/.
But you really want to avoid specifying 'unsafe-inline' in any CSP policy. Using 'unsafe-inline' pretty much defeats the entire purpose of CSP.
What you want to do instead for any inline scripts causing CSP errors is: take the scripts out of your document and move them into separate files. That’s sort of the whole point.
But if you really must specify 'unsafe-inline', then as far as the dealing with the specific error cited in the question, you should only specify 'unsafe-inline' for script-src — because the error message says, “Refused to execute inline script.”
If you instead specify 'unsafe-inline' for default-src, then that causes the browser to fail to do CSP checks for any inline resources in your document — stylesheets, etc., too, not just scripts.
So if the only problem is an inline script and for some reason you can’t fix that by moving the script out to a separate file, or specifying a hash or nonce for it, then you should at least only specify 'unsafe-inline' for script-src.

Resources