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!