CSP Adoption in Australia 2021
Last updated: May 29, 2021
Hi friends!
I’m Cole and I write a weekly series of Blogs about security and development. If you have any feedback, feel free to message me on LinkedIn! Anyway, onto the article!
Background
The Content Security Policy was conceived (ew) to help mitigate the Cross-Site Scripting menace. If you specified what content was allowed on your website in a policy, then other content should be blocked. Good in theory, but in practice it wasn’t as effective as first thought.
Google clearly demonstrated this in their publication from 23 August, 2016. Great read, but in summary most policies were bypassable.
Much has changed since then including:
- New tooling like the Google CSP Evaluator and Scott’s Security Headers
- Technical guides like Mozilla’s brilliant one
- and Improvements to the CSP specification itself
Despite these developments, few Australian companies I know have a CSP or are planning to implement one.
But change is inevitable, and security has become even more critical for businesses now. XSS is still a menace, and it’s been almost 5 years since that paper was released. So I thought I’d check out how we’re doing down under so grab a beer and enjoy!
Caveats
I know I’ll get called out by at least one internet denizen. Feel free to send me hatemail. Here are the assumptions / constraints I am working within.
- If the web-app is complex, I might have missed the CSP. Sorry!
- Some of these sites are static webpages or not business critical. Having no CSP is fine if it’s within your risk appetite! See mine for example.
- I didn’t spend time enumerating all domains, I just hit their main website and recorded the response headers. I’m not here to find exploits and be evil, I just want a snapshot.
I tried to cover many sectors by googling “random straya etfs” and asking my dad what companies he loves and hates. Feel free to guess which ones those are.
Findings
Here are the stats:
- 20.35% reviewed had ANY form of CSP
- 0.88% reviewed gained OK security benefits from the CSP
- 100% of CSP’s had
unsafe-inline
andunsafe-eval
active. - 35% of CSP’s had wildcarded CDN’s OR > 50 AllowListed Domains.
- 0% were using Nonce’s or strict-dynamic
- 36.28% of domains were using x-xss-protection: 1, Block or similar
- 40% of CSP’s had no script-src or object-src, primarily being used for Frame-Ancestors or upgrade-insecure-requests.
Most large Australian businesses are not using a Content Security Policy. Those who have are using a weak or ineffective one. No sector comes out ahead statistically, Australia has collectively missed this.
Now look, we’re not here to criticise or shame these businesses, that’s not helpful. Instead, let’s consider why they have a weak (or no) CSP, and what we can do about it.
Unsafe *
Common to each policy analysed is unsafe-inline
and unsafe-eval
. These, as suggested by their name, allow scripts to execute in an unsafe manner. They’re well known XSS sinks, but why are they still being used?
Mostly because of legacy code OR a quick work-around. Either way, a barrier to adoption for a CSP. Most organisations are working from an existing application rather than from scratch. Many of these applications rely on inline scripts to function correctly. Refactoring these into a javascript file, and then adding that to the CSP w/ a nonce and strict-dynamic could be difficult.
Depending on the complexity of the application, the need of the business, and I guess whether anybody remembers the technology or codebase at all, it could end up being a monumental task. Eval is in the same situation, although significantly less likely than the inline scripts.
As unsafe-inline and unsafe-eval are common to most CSP’s, getting back to basics with input validation and output encoding are okay. Sure there will be gaps where developers make a mistake, but if the CSP is hard to build and ineffective because of inline code, then it’s not the right control to be using.
CDN Usage
Older websites used content distribution networks (CDN’s) to improve the performance of their web applications. Heavy CDN usage in a CSP is very common unfortunately.
content-security-policy
default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' polyfill.io *.images-home.com https://snap.licdn.com/li.lms-analytics/insight.min.js *.moatads.com *.hotjar.com stackpath.bootstrapcdn.com youtube.com.au *.youtube.com.au *.youtube.com *.gstatic.com *.weblink.com.au *.nr-data.net ajax.cloudflare.com js-agent.newrelic.com maps.googleapis.com ajax.googleapis.com www.google.com *.google-analytics.com apis.google.com connect.facebook.net ajax.aspnetcdn.com www.youtube.com/iframe_api www.youtube.com.au/iframe_api platform.twitter.com syndication.twitter.com/ s.ytimg.com publish.twitter.com *.twimg.com platform.linkedin.com platform.stumbleupon.com/1/widgets.js dec.azureedge.net/ munchkin.marketo.net *.eloqua.com *.en25.com unpkg.com *.arcgis.com *.addthis.com *.addthisedge.com assets.juicer.io tagmanager.google.com www.googletagmanager.com app.hivo.com.au snap.licdn.com cdn.polyfill.io www.googleadservices.com googleads.g.doubleclick.net; style-src 'self' 'unsafe-inline' fonts.googleapis.com *.googleapis.com netdna.bootstrapcdn.com kendo.cdn.telerik.com www.google.com dec.azureedge.net platform.twitter.com/css/ *.twimg.com *.arcgis.com assets.juicer.io app.hivo.com.au blob: * 'unsafe-inline'; font-src 'self' fonts.gstatic.com kendo.cdn.telerik.com netdna.bootstrapcdn.com *.arcgis.com *.arcgisonline.com static.juicer.io data:; img-src 'self' *.linkedin.com *.woodside.com.au woodside-staging.s3.amazonaws.com woodside-development.s3.amazonaws.com *.images-home.com http://files-content.woodside.s3.amazonaws.com http://files-content.woodside files-content.woodside http://files.woodside.s3.amazonaws.com http://files.woodside files.woodside *.adsymptotic.com www.gstatic.com gstatic.com ssl.gstatic.com scontent.cdninstagram.com i.imgur.com yt3.ggpht.com i.ytimg.com stats.g.doubleclick.net maps.gstatic.com maps.googleapis.com *.googleapis.com *.google-analytics.com platform.tumblr.com web.facebook.com www.facebook.com delicious.com www.redditstatic.com www.linkedin.com syndication.twitter.com static.licdn.com/scds/common/u/images/apps/connect/sprites/sprite_connect_v14.png dec.azureedge.net *.dec.sitefinity.com pbs.twimg.com platform.twitter.com/css/ *.twimg.com app.hivo.com.au data: blob: *.eloqua.com *.arcgis.com *.arcgisonline.com assets.juicer.io *.fbcdn.net www.google.com www.google.com.au; media-src 'self' data: blob: woodside-staging.s3.amazonaws.com woodside-development.s3.amazonaws.com http://files-content.woodside.s3.amazonaws.com http://files-content.woodside http://files.woodside.s3.amazonaws.com http://files.woodside; frame-src 'self' *.addthis.com app.hivo.com.au *.hotjar.com *.twitter.com *.youtube.com.au *.youtube-nocookie.com *.youtube.com https://www.google.com/ https://clients3.weblink.com.au *.doubleclick.net; child-src 'self' https://www.google.com *.weblink.com.au platform.twitter.com/ syndication.twitter.com/ www.youtube.com/ player.vimeo.com/ w.soundcloud.com/ apis.google.com accounts.google.com staticxx.facebook.com www.facebook.com web.facebook.com badge.stumbleupon.com *.addthis.com *.youtube-nocookie.com *.weblink.com.au; connect-src 'self' api.cognitive.microsoft.com *.sentry.io *.hotjar.io *.hotjar.com ws://*.hotjar.com accounts.google.com apis.google.com *.dec.sitefinity.com *.mktoresp.com *.arcgis.com *.arcgisonline.com *.addthis.com *.juicer.io graph.facebook.com ws://woodside.dev.local:9000 woodside-staging.s3.amazonaws.com woodside-development.s3.amazonaws.com http://files-content.woodside.s3.amazonaws.com http://files-content.woodside http://files.woodside.s3.amazonaws.com http://files.woodside bam.nr-data.net *.doubleclick.net www.google-analytics.com;
Here we have a mining firm. They start off strong with unsafe-inline
and unsafe-eval
. Then they go and list over 50 domains under script-src. While we can remain reasonably confident that youtube is arguably not hosting malicious code, we cannot be certain of other domains. This is especially problematic for the * wildcarded domains
This is the easy way to write a CSP. Open the browser console and check the warnings and add that domain to the allowlist until eventually your website works.
To make it secure, you need to:
- Host content yourself
- Use ‘self’ or a domain you control
- Be very precise with what you allow, leading to a bloated policy.
- Consolidate code where you can.
These take significant application-layer refactoring. Purists or Spooks amongst you may advocate for writing code yourself, but that is unacceptably resource and time-prohibitive for everyone except ASD I guess. Doing this also creates additional risk in managing the patching and deprecation of those libraries. Even then, it might not even work for dynamically generated or obfuscated code like that Google stuff.
Anyway, with new technology like webpacks, server-side rendering, QUIC, and cloud-native CDN’s, having the client pull everything from random domains isn’t the most efficient method and introduces security weakness. Of course, cleaning up this technical debt isn’t adding new features, so we’ll throw it into the JIRA board and never look at it again.
Data Exposure
Here we have a legal firm who are open about what’s going on behind the scenes. Kind of odd for a Law Firm, but anyway. Exposing your backend isn’t always well received, not kink-shaming here. Maybe just don’t use content from your test environment in prod? Just a suggestion S&G (don’t sue me).
Jokes aside, having a bloated CSP with cross-domain dependencies is a great information source for adversaries unfortunately.
content-security-policy
upgrade-insecure-requests; default-src 'self'; script-src 'unsafe-eval' 'self' data: 'unsafe-inline' code.jquery.com slaterandgordon.force.com uat-slaterandgordon.cs114.force.com maps.googleapis.com www.googletagservices.com static.zdassets.com www.google.com www.googletagmanager.com www.google-analytics.com ssl.google-analytics.com pagead2.googlesyndication.com connect.facebook.net bat.bing.com script.crazyegg.com js.adsrvr.com pixel.roymorgan.com secure.quantserve.com rules.quantcount.com ups.analytics.yahoo.com widget.trustpilot.com ad.doubleclick.net googleads.g.doubleclick.net www.gstatic.com bat.bing.com slaterandgordonlaw.formstack.com static.formstack.com www.googleadservices.com yourir.info optimize.google.com tagmanager.google.com; style-src 'self' data: 'unsafe-inline' slaterandgordon.force.com uat-slaterandgordon.cs114.force.com ad.doubleclick.net static.formstack.com yourir.info fonts.googleapis.com optimize.google.com tagmanager.google.com; font-src 'self' fonts.gstatic.com slaterandgordon.force.com uat-slaterandgordon.cs114.force.com; media-src 'self' static.zdassets.com; img-src 'self' data: https://data:0 https://slatergordon.imgix.net https://assets.slatergordon.com.au www.google.com.au i.ytimg.com www.google-analytics.com www.facebook.com adservice.google.com insight.adsrvr.com pixel.quantserve.com www.google.com googleads4.g.doubleclick.net v2assets.zopim.io www.googletagmanager.com slaterandgordon.force.com uat-slaterandgordon.cs114.force.com img.youtube.com maps.gstatic.com maps.googleapis.com optimize.google.com ssl.gstatic.com www.gstatic.com googleads.g.doubleclick.net; frame-src 'self' www.google.com www.youtube.com www.facebook.com *.fls.doubleclick.net bid.g.doubleclick.net widget.trustpilot.com www.googletagmanager.com optimize.google.com; connect-src 'self' slaterandgordon.force.com uat-slaterandgordon.cs114.force.com www.google-analytics.com ekr.zdassets.com wss://widget-mediator.zopim.com script.crazyegg.com www.facebook.com slatergordonchat.zendesk.com *.g.doubleclick.net tracking.crazyegg.com yourir.info
x-xss-protection
Common to a third of these domains, is the x-xss-protection header. Over a decade ago, x-xss-protection was introduced to help identify potential XSS attacks and block requests that looked like <script>
mostly. Adversaries were able to find methods to ignore this header or intentionally trigger the XSS-Auditor for abuse. Because of that, Google, Microsoft, and Mozilla deprecated it from their browsers a few years ago.
While the header does nothing in modern browsers, it is a bit misleading. Many developers may not be aware that it was deprecated. Worse still, with such a strong name as x-xss-protection, it could introduce false confidence in the security of their application.
It is puzzling that it has such widespread adoption still. Maybe the original developers retired? Regardless, if you see the header in your codebase, it’s a good time to remove it for future you!
No CSP3 features?
CSP3 came out with some fantastic improvements to really kill xss dead. Those are used by a whopping 0% of Australian websites reviewed giving a net benefit of fuck all. What gives?
They’re hard to implement. Aussie dev’s aren’t even refactoring inline code. Placing dynamically generated nonce’s into these is a hard ask. Let’s deal with crawling before we run, so once we get enough adoption in Australia of any content security policy followed by cleaining up the unsafe stuff and CDN’s, then we can deal with strict-dynamic.
#Straya
I’m interested to see whether the adoption of CSP improves, but what we are really seeing is that there are barriers to adoption for most Australian businesses. The CSP is just one tool we have in our web security arsenal.
Ultimately it’s up to us as Application Security professionals to guide our businesses about what’s best for them.
Thanks for reading, if you like this please drop me a note on LinkedIn. :)
Cole