Other Security Features of Content Security Policy

5 years ago

Stuart Larsen #article


Content Security Policy was built to combat a prolific web vulnerability known as Cross Site Scripting, or XSS. (More info). But CSP also offers protections besides just (defense in depth) protection against XSS.

This article covers some of those additional features.

Mixed-Content

Both 'block-all-mixed-content' and 'upgrade-insecure-requests' deal with content loaded over insecure channels (http/ws).

As of recently major browsers block security-sensitive resources (also called 'active mixed content' or 'blockable content') from being loaded from an insecure origin when currently on a secure origin. So stuff like javascript and stylesheets could potentially be blocked.

So right now, if you are on https://securewebsite.com and try to load http://cdn.js.com/jquery.js it will fail since the request is http. This is pretty cool and a huge leap forward for making the web more secure.

Non-security sensitive resources (also called 'passive mixed content', or 'optionally blockable content)' still load. This is stuff like images, videos, audio. Stuff that can't harm or interact with the rest of the website. It's still good to upgrade it though. While more difficult to pull off, you could imagine a scenario where swapping button images could cause someone to take the wrong action. (Or you could just be a troll and person-in-the-middle in some lewd content).

Sample content security policy mixed content

Figure 1: Mixed Content Warning

upgrade-insecure-requests

upgrade-insecure-requests will simply convert any insecure resource to the secure resource counterpart. So an image loaded from http://image4all.com/cats.png will be converted to https://image4all.com/cats.png. If the https:// equivalent doesn't exist, the request will fail.

This probably sounds similar to HSTS (HTTP Strict Transport Security), and it is very similar, but there are differences. A big difference being that the upgrade-insecure-requests will only apply to elements on the specific page that returned the 'upgrade-insecure-requests' header. HSTS will apply on the initial page load. HSTS also applies to a domain, whereas 'upgrade-insecure-requests' applies to all resources on the web page.

(For the technically sound readers, it's also cool to note that upgrade-insecure-requests will work through multiple levels of iframes.)

To apply 'upgrade-insecure-requests' just include it in your CSP like a normal directive.

block-all-mixed-content

block-all-mixed-content is even simpler. It just blocks all insecure requests. (It also works through multiple levels of iframes) To apply 'block-all-mixed-content' just include it in your CSP like a normal directive.

frame-ancestors

The frame-ancestors directive can be used as a substitute for the HTTP header X-Frame-Options (XFO), a protection against clickjacking, (sometimes called ui redressing attack).

If you're not familiar with click jacking, the key insight is that it's possible to create a transparent iframe that is still interactable. So on https://myevilsuperaddictivegame.com I could embed a transparent iframe to bank.com, so while you think you're typing in random numbers as part of the game, you're actually typing in my bank account number, 1,000,000 and then clicking send. frame-ancestors is similar to X-Frame-Options, except frame-ancestors is better for two reasons:

  • XFO only allowed two keywords, 'DENY' and 'SAMEORIGIN'. CSP's frame-ancestors allows host sources, so you can specify non-self remote origins. (technically XFO had an 'ALLOW-FROM' but it wasn't fully supported).
  • frame-ancestors also checks against each ancestor in a chain. So if you had a web page that embedded an iframe that embedded a different iframe, that embedded a third iframe, frame-ancestors would check all three. This is cool to prevent some tricky type of attacks.

When both frame-ancestors and XFO are seen on the same request, the browser will follow frame-ancestors.

form-actions

Using CSP you can define where HTML <form>s are allowed to submit data.

This has a couple of uses, the obvious is maybe an attacker could inject a form into a web page that submits some data somewhere. Maybe it's used to redirect to a page that looks similar to the original page and then attempts to phish credentials or something.

The less obvious is in the form of dangling markup injections. These attacks are described in more detail in one of my all time favorite articles: Postcards from the post-XSS world. But tl;dr; there's a few attacks where you could attempt to steal CSRF tokens (or other sensitive inline material) by constructing forms that "eat up" a bunch of HTML and then the "post" that html to an endpoint as a form parameter. (Or if it's a CSRF token, it just treats it like a normal form input).

sandbox

A very neat feature of <iframe>'s is the 'sandbox' attribute. You can use it to severely lock down what a page is allowed to do.

With Content-Security-Policy you can now do that to any website, not just <iframe>'s.

(One of the very cool features of an iframe's sandbox is that it treats content like it came from some other random origin (meaning it won't have access to cookies/localstorage etc). Combine this with iframe's srcdoc attribute and you have a very nifty way to embed untrusted content. But that's not as useful for CSP)

There's a bunch of directives, I've listed a couple of the cool ones here, but the full list can be found on the mozilla docs.

Value Description
allow-forms The webpage can include <form>s
allow-popups The webpage can use window.open, target="_blank" and other popups
allow-scripts The webpage can execute scripts (javascript)
allow-top-navigation The webpage can redirect to different pages

There's also some stuff for downloads, orientation locks, pointers, presentation mode, etc.

If you specify just 'sandbox' the page won't execute javascript, no forms, no nothing. Just pure clean HTML.

plugin-types

Sometimes you have to allow object-src. A common example was for allowing flash to copying data to clipboard. (Now thankfully there are javascript APIs for that).

But, including one object-src includes a bunch of nasty stuff you're probably don't want to also include, like shockwave, and silverlight, and applets. So instead you can specifically say what type of plugins you support. (Although hopefully it's none).

Future / Other

require-sri-for

There's a cool feature of script tags and style tags where you can do integrity checking on the resource before it's executed. Basically you attach a hash of the contents of the script that is about to be remotely loaded. Then when the browser downloads the script it'll make sure the hash matches (so you know the remote script didn't change).

SRI is completely legit and ready to go.

<script src="https://code.jquery.com/jquery-2.1.4.min.js" integrity="sha384-R4/ztc4ZlRqWjqIuvf6RX5yb/v90qNGx6fS48N0tRxiGkqveZETq72KgDVJCp2TC" crossorigin="anonymous"></script>

There's also a feature of CSP where you can specify "require-sri-for" and 'script' and/or 'style'. Which will mandate SRI for those resources on a website.

But it is behind feature flag on chrome, and not supported by mozilla (anymore). Maybe in the future.

trusted-types

There's a third type of XSS that CSP doesn't fully address, this is DOM based XSS. Trusted-types is a proposal where you have to specifically tag resources and their types before they can fed into certain browser functions. (These browser functions are xss-sinkable, like innerHTML).

It's not supported yet, but should be exciting to see. Hopefully in the future you can use CSP to enable trusted-types, and even only allow specific trusted-type "templates".

This is still in the draft, but it's an interesting idea where you can specify the allowed locations where a page can navigate to (<a> tags, window.location, forms, etc).

This is useful because even with CSP, an attacker can inject HTML. So an attacker could inject content that looks like it's part of the original page, put in some <a> tags, and then have those <a> tags redirect to a different phishing website that looks exactly the same as the original in hopes of tricking the user to re-type their password or something.

Conclusion

Well I hope you had a good time learning about the other security features of CSP. If you have any questions or comments, I'd love to chat. stuart@csper.io.

Subscribe for updates?

Stay up to date with the latest Content Security Policy news, product updates, discounts, and more!