Skip to content

Stored XSS through javascript URL in Analytics dashboards

Please read the process on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.

HackerOne report #2683863 by joaxcar on 2024-08-26, assigned to @cmaxim:

Report | Attachments | How To Reproduce

Report

Summary

When configuring Analytics dashboards (docs) you gain access to some default dashboards and visualizations. One of these visualizations presents a list of Top pages based on view count.
The list contains links to the pages, but only the path is shown.

It's possible for an unauthenticated attacker to spoof these metrics and have them point to a javascript URL instead. On Gitlab.com this will get blocked by CSP, but on a self-hosted instance (maybe behind a proxy or VPN) this CSP might not be configured and the payload will trigger.

To get a victim to click the link the attacker can just spam a lot of "visits" to the fake page and have it end up in top of the "top pages" list.

Steps to reproduce

Even if it gets blocked by CSP on gitlab.com, it's easiest to reproduce it there just to prove the injection. The feature can be configured on a self-hosted server as well

as the victim

  1. Create a new Ultimate subscription using trials
  2. In the new group create a new project
  3. Go to https://gitlab.com/GROUPNAME/PROJECTNAME/-/analytics/dashboards and click Set up to the right of Product Analytics
  4. Click the checkbox I agree to event collection and processing in this region. and select Use Gitlab-managed provider (this would on selfhosted be set up using custom settings but the end result is still the same, Cube + Snowflake + ClickHouse)
  5. You will land on https://gitlab.com/GROUPNAME/PROJECTNAME/-/analytics/dashboards/product-analytics-onboarding here just copy the Using HTML script html code looking like this

Screenshot_2024-08-26_at_16.29.19.png

  1. Host this HTML somewhere (you can use something like JSFiddle for this, just make a note of the URL that is hosting the content) This now simulates the service that you are hosting and monitoring

as the attacker
7. Use a proxy tool to do a match and replace on all traffic from your browser that looks like this

type: Request body  
match: https://YOURDOMAIN.com/  
replace: javascript://YOURDOMAIN.com/%0aalert(document.domain)%0a  

Screenshot_2024-08-26_at_16.33.30.png

  1. Now visit the URL from step 6. The page should make an "analytics request" but slightly modified

as the victim
9. Go to https://gitlab.com/GROUPNAME/PROJECTNAME/-/analytics/dashboards/behavior 10. Under Top Pages` there should be a link, if you click it you should see a warning in devtools that javascript tried to execute but was blocked by CSP.

Screenshot_2024-08-26_at_16.37.12.png

Impact

XSS on selfhosted services. As this is possible to be used unauthenticated as a blind xss against selfhosted servers that are not accessible from the wide web I think its could be seen as having a CVSS of

8.0 -> CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:N  

as selfhosted servers that are not exposed to the internet are more likely to not have CSP in place.

If not I think it should be put on CVSS

6.1 -> CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N  

The complexity is only high if the attack is seen as blind XSS in my opinion, otherwise its the same as other javascript: based XSS's

What is the current bug behavior?

An attacker can spoof Top pages to point to anything. Like javascript urls

What is the expected correct behavior?

It should not allow any form of URL only safe ones

Impact

XSS on selfhosted services

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

How To Reproduce

Please add reproducibility information to this section: