CSP-bypass XSS in project settings page
High
G
GitLab
Submitted None
Actions:
Reported by
yvvdwf
Vulnerability Details
Technical details and impact analysis
### Summary
This javascript [function](https://gitlab.com/gitlab-org/gitlab/-/blob/85fbd72dc08bcedcb9fe80fad4df798e9527ded8/app/assets/javascripts/projects/settings/access_dropdown.js#L534) is vulnerable:
```javascript
deployKeyRowHtml(key, isActive) {
const isActiveClass = isActive || '';
return `
<li>
<a href="#" class="${isActiveClass}">
<strong>${key.title}</strong>
<p>
${sprintf(
__('Owned by %{image_tag}'),
{
image_tag: `<img src="${key.avatar_url}" class="avatar avatar-inline s26" width="30">`,
},
false,
)}
<strong class="dropdown-menu-user-full-name gl-display-inline">${escape(
key.fullname,
)}</strong>
<span class="dropdown-menu-user-username gl-display-inline">${key.username}</span>
</p>
</a>
</li>
`;
}
```
It is used to render a deployment key in a dropdown item. Because the deployment title is controlled by users, it can be any html content, such as, `<script>alert(document.domain)</script>`. Furthermore, the html content will be [rendered](https://gitlab.com/gitlab-org/gitlab/-/blob/85fbd72dc08bcedcb9fe80fad4df798e9527ded8/app/assets/javascripts/deprecated_jquery_dropdown/gl_dropdown.js#L396) using jQuery, so the `<script>` tag will be executed despise of CSP with `script-src ` having `'strict-dynamic'` value:
```javascript
renderMenu(html) {
if (this.options.renderMenu) {
return this.options.renderMenu(html);
}
return $('<ul>').append(html);
}
```
### Steps to reproduce
1. In an existing project or create a new one, goto `Settings`/`Repository`. Then fill the form in `Deploy keys` as the following:
- `Title`: `test <script>alert(document.domain)</script>`
- `Key`: `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkhkyrQJvb30Q5lLZzxeALqCyBrLOh+QzRYWh+gPGpqi2efyGMf5beN2zda66OI6DaclB31SJ0jYzaYKgKXQw7rzu/IYazONdy5lz5O2iUB2BkDzJYZ+BObTaTCjyDgSvNNuezUqNXXqoXftEMa1l0+FRSkTusH5F2P3JCV3Tf1BBQImrbDIpdc6ps+UxsiX7S/dT+7bNIVXblC8s8k+AK4CWsC2KmfMToK35pk+sa9JI+rb26hzv8IHA8n7cqXOmR5qAj2qX962p1kOLNXCyHJAKAIfRXCuDPbXiB+kjnu478eIcudOPveo3CK3G6hBI0hPSRfoyAUIubcddnnbhR `
- `Grant write permissions to this key`: Checked
Then click `Add key` button to save the form.
{F1752821}
__NOTE__:
- `Title` can be any HTML content that represents the attack payload. In the example above, we just show an alert containing the current domain.
- `Key` can be any valid SSH public key. In the example above, I give you a random key so that you can copy-paste into the form without the need to generate a key
2. Always in the `Settings`/`Repository` page, click on `Protected branches` link to expand its form
3. Click on the dropdown box under `Allowed to push `, you should see an alert that was generated when the payload above being executed
{F1752822}
__NOTE__:
- This is not self-XSS as any project maintainer can access to the settings page. Furthermore a victim can be added as a project maintainer without their explicit acceptation
- The Step 2 can be ignored by accessing directly within `#js-protected-branches-settings` on the url, for example, `https://gitlab.com/yvvdwf/xss/-/settings/repository#js-protected-branches-settings`
### Impact
XSS with CSP bypass allows attacks to perform arbitrary malicious requests on behalf of victims on HTTP client side, such as, do an API request to access to private resources, etc.
### Examples
https://gitlab.com/yvvdwf/xss/-/settings/repository#js-protected-branches-settings
### What is the current *bug* behavior?
Deployment title is not sanitized
### What is the expected *correct* behavior?
Deployment title should be sanitized
### Output of checks
This bug happens on GitLab.com
## Impact
XSS with CSP bypass allows attacks to perform arbitrary malicious requests on behalf of victims on HTTP client side, such as, do an API request to access to private resources, etc.
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Submitted
Weakness
Cross-site Scripting (XSS) - Generic