Arbitrary file read via the UploadsRewriter when moving an issue
HackerOne report #827052 by vakzz
on 2020-03-23, assigned to @dcouture:
Summary
The UploadsRewriter
does not validate the file name, allowing arbitrary files to be copied via directory traversal when moving an issue to a new project.
The pattern used to look for references is :
MARKDOWN_PATTERN = %r{\!?\[.*?\]\(/uploads/(?<secret>[0-9a-f]{32})/(?<file>.*?)\)}.freeze
This is used by the UploadsRewriter
when copying an issue to also copy across the files:
[@]text.gsub([@]pattern) do |markdown|
file = find_file([@]source_project, $~[:secret], $~[:file])
break markdown unless file.try(:exists?)
klass = target_parent.is_a?(Namespace) ? NamespaceFileUploader : FileUploader
moved = klass.copy_to(file, target_parent)
...
def find_file(project, secret, file)
uploader = FileUploader.new(project, secret: secret)
uploader.retrieve_from_store!(file)
uploader
end
As there is no restriction on what file
can be, path traversal can be used to copy any file.
Demo
file-read.mp4
Steps to reproduce
- Create two projects
- Add an issue with the following description:

- Move the issue to the second project
- The file will have been copied to the project
Impact
Allows an attacker to read arbitrary files on the server, including tokens, private data, configs, etc
What is the current bug behavior?
The file name and path are not checked when copying an issue between projects
What is the expected correct behavior?
The file or path should be validated before copying files.
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.8.7-ee
Revision: 2643fd87200
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: 11.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
Allows an attacker to read arbitrary files on the server, including tokens, private data, configs, etc
Attachments
Warning: Attachments received through HackerOne, please exercise caution!