Skip to content

Pipeline script injection by adding arbitrary command in post checkout hook & changing hook path to run command in future pipeline on target runner

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 #2525777 by xorz on 2024-05-30, assigned to GitLab Team:

Report | Attachments | How To Reproduce

Report

Summary

An attacker who has permissions to push code can inject code for any pipelines within a project with docker executor runner.

Steps to reproduce
  1. sign in as user_a

  2. create a new project project_a

  3. register and keep only one runner (docker) for the project. https://docs.gitlab.com/runner/executors/docker.html

  4. invite the user_b as a developer

  5. goto project_a > Build -> Pipeline Editor

  6. paste the content of owner_pipeline.yml and commit

  7. the user_a should see the pipeline is green

  8. sign in as user_b

  9. goto the project project_a > Code >Repository

  10. create a branch test

  11. paste the content of attacker_pipeline.yml and commit

  12. wait for the pipeline is done

  13. sign in as user_a

  14. goto the project project_a > Build > Pipelines

  15. trigger a new pipeline on branch main

  16. wait for the pipeline is done

  17. then the user_a should see the text like CI_JOB_TOKEN outputted by the inject code in job logs

Impact
  1. Get all the environment variables and access other projects. As it says on Gitlab Docs You can use a job token to authenticate with GitLab to access another group or project’s resources (the target project). By default, the job token’s group or project must be added to the target project’s allowlist.
  2. Inject code to release without touch the protected branches if the project using pipeline to build and release code.
Examples
without user interaction
  1. two cases listed in Impact above
with user interaction
  1. the injected code can be run on any user's laptop after running the app downloaded from the injected releases.
  2. the attacker can down all the projects via stealing the ssh key if the group owner runs the released app on local.
What is the current bug behavior?

According to Choose the default Git strategy, pipelines re-use the local working copy and the customized git hooks path won't be purged for the sequential jobs.

What is the expected correct behavior?

Get the hooks path by git config core.hooksPath.

Relevant logs and/or screenshots

hooks_path.jpg ci-job-injection.mov

Output of checks

(If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com)

Results of GitLab environment info

Gitlab

System information  
System:         Ubuntu 22.04  
Proxy:          no  
Current User:   user  
Using RVM:      no  
Ruby Version:   3.2.3  
Gem Version:    3.5.10  
Bundler Version:2.5.10  
Rake Version:   13.0.6  
Redis Version:  7.0.14  
Sidekiq Version:7.1.6  
Go Version:     go1.22.3 linux/amd64

GitLab information  
Version:        17.1.0-pre  
Revision:       7a6a65965a1  
Directory:      /home/user/dev/gitlab-development-kit/gitlab  
DB Adapter:     PostgreSQL  
DB Version:     14.9  
URL:            http://gitlab.test:3001  
HTTP Clone URL: http://gitlab.test:3001/some-group/some-project.git  
SSH Clone URL:  ssh://git@gitlab.test:2222/some-group/some-project.git  
Elasticsearch:  no  
Geo:            no  
Using LDAP:     no  
Using Omniauth: yes  
Omniauth Providers: google_oauth2

GitLab Shell  
Version:        14.35.0  
Repository storages:  
- default:      unix:/home/user/dev/gitlab-development-kit/praefect.socket  
GitLab Shell path:              /home/user/dev/gitlab-development-kit/gitlab-shell

Gitaly  
- default Address:      unix:/home/user/dev/gitlab-development-kit/praefect.socket  
- default Version:      17.0.0-rc2-230-g23975a577  
- default Git Version:  2.45.1

Gitlab Runner

 gitlab-runner --version  
Version:      17.0.0  
Git revision: 44feccdf  
Git branch:   17-0-stable  
GO version:   go1.21.9  
Built:        2024-05-16T13:46:14+0000  
OS/Arch:      linux/amd64

Impact

  1. Get all the environment variables and access other projects. As it says on Gitlab Docs You can use a job token to authenticate with GitLab to access another group or project’s resources (the target project). By default, the job token’s group or project must be added to the target project’s allowlist.

  2. Inject code to release without touch the protected branches if the project using pipeline to build and release code.

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

How To Reproduce

Please add reproducibility information to this section:

Proposed fix

Edited by Darren Eastman