Smuggling content in MR with refs/replace in Gitlab
HackerOne report #1938185 by inspector-ambitious
on 2023-04-07, assigned to @ottilia_westerlund:
Report | Attachments | How To Reproduce
Report
Summary
In Git, the refs/replace
namespace is used to create a temporary reference that points to a commit object, allowing for the replacement or overwriting of an existing commit with a new one.
When a new commit object is created in Git, it is assigned a unique SHA-1 hash that identifies it in the repository's history.
However, an attacker with the Developer
role in a repository can push a replacement reference in the refs/replace
namespace, which would replace an existing commit with a malicious one. And if the head commit of a MR is replaced with a malicious one, we will get a situation where the MR will show the original commit but what would be merged will be the malicious one instead. Therefore this would allow an attacker to inject malicious code in the protected branch.
You can find a documentation on git replace here.
Steps to reproduce
To reproduce this vulnerability we will need 2 users:
-
victim01
the victim and repository owner. -
inspector-ambitious
the attacker withDeveloper
access.
victim01
)
Step 1: Setup repository (in victim context -
Create an empty (no README) private project called
replace
-
Add one empty file called
a
. (we need at least one commit)
- Go to
Settings > Repository > Protected Branches
and check thatmain
branch is protected
It should be the default setup. Only maintainers can merge or push to this branch.
- Got to
Project information > Members
and inviteinspector-ambitious
with the roleDeveloper
inspector-ambitious
)
Step 2: Attack preparation (in attacker context ** It is extremely important to respect the order of operations here **
- Create a new branch from
main
calledb
for example - Add a new empty file called
b
in the branchb
- Create a branch called
c
frommain
with an empty file calledc
- Clone the repository and run
git ls-remote
in the terminal
- Now push a refs/replace reference to replace commit from
b
withc
in our case based on previous output of ls-remote
running git ls-remote
again we get
- Create a MR from
b
tomain
.
As you can see only the file b
should be added when this PR is merged.
main
branch is compromised (in victim context victim01
)
Step 3: - Go to the pull request and merge it.
- Go to the
main
branch
You can see the file c
from c
got merged !
The commit history looks correct.
However if we look at the merge commit we see that c
was added instead of b
Output of checks
This bug happens on GitLab.com, I tried to reproduce it on a local instance but somehow it didn't work out...
Impact
A collaborator can bypass branch protection and smuggle malicious content in a merge request, which could potentially introduce security vulnerabilities or other types of defects into the codebase, compromising the integrity and security of the repository. This could result in sensitive data being leaked, unauthorized access to resources, or even complete system compromise.
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
- image.png
- image.png
- image.png
- image.png
- image.png
- image.png
- image.png
- image.png
- image.png
- image.png
- image.png
- image.png
- image.png
- image.png
- image.png
How To Reproduce
Please add reproducibility information to this section: