HexBrain

GitLab · Report #1588732

CSP-bypass XSS in project settings page

Validstatus
highseverity
100upvotes
16 Nov 2022disclosed

How it was found

Summary

This javascript function is vulnerable:

  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 using jQuery, so the <script> tag will be executed despise of CSP with script-src having 'strict-dynamic' value:

  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
  1. Always in the Settings/Repository page, click on Protected branches link to expand its form
  2. 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.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original