Skip to content

Ambiguous branch name exploitation

Please read the process on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.

HackerOne report #1940441 by inspector-ambitious on 2023-04-10, assigned to @fvpotvin:

Report | Attachments | How To Reproduce

Report

Summary

Introduction

I previously reported #1831547 and #1831543, they have been closed and fixed. However I wanted to retest them carefully over the weekend and I managed to replicate the issue again but this time using a branch called heads/main !

A quick recap about symbolic ref names

The following is extracted from this documentation.

A symbolic ref name. E.g. master typically means the commit object referenced by refs/heads/master. If you happen to have both heads/master and tags/master, you can explicitly say heads/master to tell Git which one you mean. When ambiguous, a <refname> is disambiguated by taking the first match in the following rules:

If $GIT_DIR/<refname> exists, that is what you mean (this is usually useful only for HEAD, FETCH_HEAD, ORIG_HEAD, MERGE_HEAD and CHERRY_PICK_HEAD);

  • otherwise, refs/<refname> if it exists;

  • otherwise, refs/tags/<refname> if it exists;

  • otherwise, refs/heads/<refname> if it exists;

  • otherwise, refs/remotes/<refname> if it exists;

  • otherwise, refs/remotes/<refname>/HEAD if it exists.

In the following exploitation scenario, we're going to abuse the fact that the following symbolic reference name
heads/foo, can resolve to two distinct branches either refs/heads/foo or refs/heads/heads/foo.

Steps to reproduce

This scenario was tested on gitlab.com.

Step 1: The malicious heads/main default branch

A user named victim01 creates an empty new repository named ambiguity (without a README).

image.png

victim01 will then create a branch named heads/main containing a malicious script named ./script.sh. That branch will become the default branch since the repository was empty.
From the command line, it would look like this

git clone git@gitlab.com:evilcorporation/ambiguity.git  
cd ambiguity  
echo "echo 'execute malicious code'" >> script.sh  
chmod +x script.sh  
git add script.sh  
git commit -m "malicious script"  
git branch -M hack  
git push origin hack:refs/heads/heads/main  

image.png

Note in the screenshot above that the default branch is heads/main and the commit name is malicious script.

Step 2: The genuine main branch

Then victim01 creates a main branch in the repository containing as well a ./script.sh but this time the content of ./script.sh is genuine and safe to execute.
From the command line, it would look like this

mkdir ambiguity_genuine  
cdambiguity_genuine  
echo "echo 'this is genuine'" >> script.sh  
chmod +x script.sh  
git init  
git add script.sh  
git commit -m "genuine script"  
git branch -M genuine  
git remote add origin  git@gitlab.com:evilcorporation/ambiguity.git  
git push origin genuine:refs/heads/main  
Step 3: The victim clone the repo and execute the script

Now let's say the user user1 goes to the repository https://gitlab.com/evilcorporation/ambiguity.git/, user1 will see the following.

image.png

image.png

While the default branch is heads/main, user1 will see the content of main branch instead, note the commit name genuine script. And if user1 was cloning the repository and executing script.sh, it will be the malicious code that would be executed instead.

image.png

I also tested the download of the zip file and it is vulnerable this time ! (contrary to previous report), the victim would download the content heads/main branch, see below the extraction of the zip and the output of script.sh

image.png

Output of checks

This bug happens on GitLab.com

Impact

Malicious repositories could be created to lure users into executing what they think is safe code, resulting in the takeover of the victim system.

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

How To Reproduce

Please add reproducibility information to this section: