Skip to main content

Cloud VAPT Notes (GCP Initial Acces, Recon, Enumeration)

2232 words
Edwin Tok | Shiro
Author
Edwin Tok | Shiro
「 ✦ OwO ✦ 」
Table of Contents

Cloud Pentesting (GCP)
#


Initial Access & Reconnaissance
#

Authentication Methods
#

gcloud CLI Authentication (Current Standard):
#

# Installation verification
gcloud version

# Update to latest version
gcloud components update

# USER AUTHENTICATION METHODS:

# Method 1: Interactive browser authentication (OAuth 2.0)
gcloud auth login

# Method 2: Device code flow (for headless/restricted environments)
gcloud auth login --no-launch-browser
# Follow the displayed URL and enter code

# Method 3: Application Default Credentials (ADC)
gcloud auth application-default login
# Used by client libraries and SDKs

# SERVICE ACCOUNT AUTHENTICATION:

# Method 4: Service account key file
gcloud auth activate-service-account --key-file=/path/to/key.json

# Method 5: Service account impersonation
gcloud auth activate-service-account SERVICE_ACCOUNT@PROJECT.iam.gserviceaccount.com \
    --key-file=/path/to/key.json

# WORKLOAD IDENTITY (Modern Kubernetes authentication)
# Automatically configured for GKE workloads
# No explicit authentication needed from within cluster

# VERIFY AUTHENTICATION:

# Check current authenticated account
gcloud auth list

# Show active account details
gcloud config list

# Get current project
gcloud config get-value project

# Get access token (for API calls)
gcloud auth print-access-token

# Get identity token (for authenticated services)
gcloud auth print-identity-token

# SET CONFIGURATION:

# Set active project
gcloud config set project PROJECT_ID

# Set default region/zone
gcloud config set compute/region us-central1
gcloud config set compute/zone us-central1-a

# Create named configuration (multiple accounts)
gcloud config configurations create red-team-config
gcloud config configurations activate red-team-config

# OPSEC: OAuth authentication generates logs in Workspace if using Google Workspace
# Service account authentication is common for automation (less suspicious)
# ADC is used by applications (blends with normal app traffic)

Credential Storage & Security:
#

# Credential locations:
# Linux/macOS: ~/.config/gcloud/
# Windows: %APPDATA%\gcloud\

# Key files:
# - credentials.db: Access tokens (SQLite database)
# - application_default_credentials.json: ADC tokens
# - legacy_credentials/: Older credential format
# - access_tokens.db: Cached access tokens

# View stored credentials
cat ~/.config/gcloud/credentials.db | strings | grep -i token

# Application Default Credentials location
cat ~/.config/gcloud/application_default_credentials.json

# Extract access token manually
sqlite3 ~/.config/gcloud/credentials.db "SELECT * FROM credentials;"

# OPSEC: Credential files contain refresh tokens (long-lived)
# Stealing credentials.db provides persistent access
# ADC credentials often have broad permissions

Service Account Key Management:
#

# Service account keys are JSON files containing private keys
# NEVER commit to version control (common mistake)

# Example service account key structure:
{
  "type": "service_account",
  "project_id": "project-id",
  "private_key_id": "key-id",
  "private_key": "-----BEGIN PRIVATE KEY-----\n...",
  "client_email": "sa-name@project-id.iam.gserviceaccount.com",
  "client_id": "1234567890",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs"
}

# Authenticate with service account key
gcloud auth activate-service-account --key-file=sa-key.json

# OPSEC: Service account keys are powerful and often over-permissioned
# Look for keys in:
# - Git repositories (.git/config, commit history)
# - Cloud Storage buckets
# - Application source code
# - CI/CD pipelines
# - Developer workstations
# - Docker images / container registries

GCP - Project Discovery & IAM Enumeration
#

Project and Organization Discovery
#

Organization Enumeration:

bash

# List accessible organizations (requires specific permissions)
gcloud organizations list

# Get organization details
gcloud organizations describe ORGANIZATION_ID

# Get organization IAM policy (requires resourcemanager.organizations.getIamPolicy)
gcloud organizations get-iam-policy ORGANIZATION_ID

# List folders in organization (hierarchical structure)
gcloud resource-manager folders list --organization=ORGANIZATION_ID

# Get folder IAM policy
gcloud resource-manager folders get-iam-policy FOLDER_ID

# OPSEC: Organization-level access is rare
# Most users only see project-level resources
# Organization visibility indicates privileged access or misconfig

Project Enumeration:

bash

# List all accessible projects
gcloud projects list

# Get detailed project information
gcloud projects describe PROJECT_ID

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

# Get project IAM policy
gcloud projects get-iam-policy PROJECT_ID

# Format output for easier parsing
gcloud projects get-iam-policy PROJECT_ID --format=json > project-iam.json

# Filter for specific roles
gcloud projects get-iam-policy PROJECT_ID \
    --flatten="bindings[].members" \
    --filter="bindings.role:roles/owner"

# List billing accounts associated with projects
gcloud billing projects describe PROJECT_ID

# Check if billing is enabled (disabled projects have limited functionality)
gcloud billing projects describe PROJECT_ID --format="value(billingEnabled)"

# Enumerate project metadata
gcloud compute project-info describe --project=PROJECT_ID

# Get project-wide SSH keys
gcloud compute project-info describe --project=PROJECT_ID \
    --format="value(commonInstanceMetadata.items[0].value)"

# OPSEC: Project enumeration is normal for developers/admins
# Focus on projects with production-sounding names
# Billing-enabled projects are active targets

Active Project Context:

bash

# Set active project for subsequent commands
gcloud config set project PROJECT_ID

# Verify current project
gcloud config get-value project

# Quick project switching
export PROJECT_ID="target-project-id"
gcloud config set project $PROJECT_ID

# Use project flag in individual commands (alternative to setting default)
gcloud compute instances list --project=PROJECT_ID

# OPSEC: Project switching generates minimal logs
# All subsequent API calls tied to active project

IAM Enumeration Strategy
#

Service Account Discovery & Analysis:

bash

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

# Get specific service account details
gcloud iam service-accounts describe SA_EMAIL --project=PROJECT_ID

# List keys for service account (key metadata, not actual keys)
gcloud iam service-accounts keys list \
    --iam-account=SA_EMAIL \
    --project=PROJECT_ID

# Check when keys were created (look for old/stale keys)
gcloud iam service-accounts keys list \
    --iam-account=SA_EMAIL \
    --project=PROJECT_ID \
    --format="table(name,validAfterTime,validBeforeTime)"

# Get service account IAM policy (who can impersonate it)
gcloud iam service-accounts get-iam-policy SA_EMAIL --project=PROJECT_ID

# Critical: Check for overly permissive impersonation
gcloud iam service-accounts get-iam-policy SA_EMAIL \
    --project=PROJECT_ID \
    --flatten="bindings[].members" \
    --filter="bindings.role:roles/iam.serviceAccountUser OR bindings.role:roles/iam.serviceAccountTokenCreator"

# Find service accounts that can be impersonated by current user
for sa in $(gcloud iam service-accounts list --format="value(email)"); do
    echo "Checking: $sa"
    gcloud iam service-accounts get-iam-policy $sa \
        --flatten="bindings[].members" \
        --filter="bindings.members:user:$(gcloud config get-value account)" 2>/dev/null && \
        echo "  [+] Can interact with: $sa"
done

# PRIVILEGE ESCALATION: Create new key for service account (if you have permissions)
gcloud iam service-accounts keys create key.json \
    --iam-account=SA_EMAIL \
    --project=PROJECT_ID

# Use the newly created key
gcloud auth activate-service-account --key-file=key.json

# OPSEC: Service account key creation is logged
# Old service accounts with keys may be forgotten/unmonitored
# Default service accounts (compute, app engine) often over-permissioned

Role Analysis:

bash

# List all predefined roles
gcloud iam roles list

# Filter roles by name pattern
gcloud iam roles list --filter="name:*admin*"

# Get detailed role permissions
gcloud iam roles describe roles/owner

# List custom roles in project
gcloud iam roles list --project=PROJECT_ID

# Get custom role definition
gcloud iam roles describe ROLE_ID --project=PROJECT_ID

# Find dangerous permissions in custom roles
gcloud iam roles describe ROLE_ID --project=PROJECT_ID | \
    grep -E "iam.serviceAccountKeys.create|iam.serviceAccounts.actAs|compute.instances.setMetadata"

# List all roles at organization level
gcloud iam roles list --organization=ORGANIZATION_ID

# OPSEC: Role enumeration is read-only and common
# Focus on custom roles (may have privilege escalation paths)
# Look for wildcard permissions: "resourcemanager.*", "iam.*", "compute.*"

IAM Policy Analysis (Critical for Privilege Escalation):

bash

# PROJECT-LEVEL IAM:

# Get complete project IAM policy
gcloud projects get-iam-policy PROJECT_ID --format=json

# Find all users with Owner role
gcloud projects get-iam-policy PROJECT_ID \
    --flatten="bindings[].members" \
    --filter="bindings.role:roles/owner" \
    --format="table(bindings.members)"

# Find all users with Editor role
gcloud projects get-iam-policy PROJECT_ID \
    --flatten="bindings[].members" \
    --filter="bindings.role:roles/editor"

# Find service accounts with elevated privileges
gcloud projects get-iam-policy PROJECT_ID \
    --flatten="bindings[].members" \
    --filter="bindings.members:serviceAccount:*" \
    --format="table(bindings.role,bindings.members)"

# Check for allUsers or allAuthenticatedUsers (public access)
gcloud projects get-iam-policy PROJECT_ID \
    --flatten="bindings[].members" \
    --filter="bindings.members:allUsers OR bindings.members:allAuthenticatedUsers"

# RESOURCE-LEVEL IAM:

# Get IAM policy for specific Compute Engine instance
gcloud compute instances get-iam-policy INSTANCE_NAME \
    --zone=ZONE \
    --project=PROJECT_ID

# Get IAM policy for Cloud Storage bucket
gsutil iam get gs://BUCKET_NAME

# Get IAM policy for Cloud Function
gcloud functions get-iam-policy FUNCTION_NAME --region=REGION

# Get IAM policy for Cloud Run service
gcloud run services get-iam-policy SERVICE_NAME --region=REGION

# CONDITIONAL IAM BINDINGS (modern feature):
# Check for condition-based access (time-based, attribute-based)
gcloud projects get-iam-policy PROJECT_ID --format=json | \
    jq '.bindings[] | select(.condition != null)'

# OPSEC: IAM policy enumeration is normal administrative activity
# Extensive enumeration may trigger rate limits
# Focus on high-value roles: Owner, Editor, Service Account Admin

Impersonation and ActAs Permissions:

bash

# SERVICE ACCOUNT IMPERSONATION (Major Privilege Escalation Path):

# Check if you can impersonate service accounts
# Required permission: iam.serviceAccounts.actAs or iam.serviceAccounts.getAccessToken

# Test impersonation
gcloud iam service-accounts get-access-token SA_EMAIL

# If successful, use impersonated service account for operations
gcloud compute instances list \
    --impersonate-service-account=SA_EMAIL \
    --project=PROJECT_ID

# Generate access token as impersonated service account
gcloud auth print-access-token \
    --impersonate-service-account=SA_EMAIL

# Run command as impersonated service account
gcloud projects get-iam-policy PROJECT_ID \
    --impersonate-service-account=SA_EMAIL

# Chain impersonation (if SA1 can impersonate SA2)
gcloud compute instances list \
    --impersonate-service-account=SA2_EMAIL \
    --impersonate-service-account=SA1_EMAIL

# OPSEC: Impersonation is logged as the impersonated identity
# Audit logs show both impersonator and impersonated account
# Common in CI/CD pipelines and automation

Workload Identity Federation (Modern GCP Feature):

bash

# Workload Identity Federation allows external identities (AWS, Azure, GitHub)
# to authenticate to GCP without service account keys

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

# Describe Workload Identity Pool
gcloud iam workload-identity-pools describe POOL_ID \
    --location=global \
    --project=PROJECT_ID

# List Workload Identity Providers
gcloud iam workload-identity-pools providers list \
    --workload-identity-pool=POOL_ID \
    --location=global \
    --project=PROJECT_ID

# Get provider configuration
gcloud iam workload-identity-pools providers describe PROVIDER_ID \
    --workload-identity-pool=POOL_ID \
    --location=global \
    --project=PROJECT_ID

# ATTACK VECTOR: If you control external identity (GitHub Actions, AWS role)
# You may be able to authenticate to GCP via Workload Identity Federation

# OPSEC: Workload Identity Federation is newer and may be less monitored
# Common in multi-cloud environments
# Check attribute conditions (may have weak validation)

IAM Recommender (Find Over-Privileged Accounts):

bash

# IAM Recommender suggests removing unused permissions
# Useful for attackers to identify valuable permissions

# List IAM recommendations
gcloud recommender recommendations list \
    --project=PROJECT_ID \
    --location=global \
    --recommender=google.iam.policy.Recommender

# Get specific recommendation
gcloud recommender recommendations describe RECOMMENDATION_ID \
    --project=PROJECT_ID \
    --location=global \
    --recommender=google.iam.policy.Recommender

# Insights show actual permission usage
gcloud recommender insights list \
    --project=PROJECT_ID \
    --location=global \
    --insight-type=google.iam.policy.Insight

# OPSEC: Recommender data shows which permissions are actively used
# Unused permissions may indicate test accounts or over-provisioning
# Actively used permissions are likely required for operations

Policy Troubleshooter (Understand Permission Denials):

bash

# Policy Troubleshooter explains why access was granted/denied
# Useful for understanding privilege escalation paths

# Check if user has specific permission on resource
gcloud policy-troubleshoot iam \
    --resource-name="//cloudresourcemanager.googleapis.com/projects/PROJECT_ID" \
    --permission="resourcemanager.projects.setIamPolicy" \
    --principal-email="user@example.com"

# OPSEC: Policy troubleshooter queries are logged
# Reveals which permissions you're testing
# Use sparingly to avoid detection

Asset Inventory (Comprehensive Resource Enumeration):

bash

# Cloud Asset Inventory provides unified view of all resources
# Requires cloudasset.assets.* permissions

# Search all assets in project
gcloud asset search-all-resources \
    --scope=projects/PROJECT_ID \
    --asset-types="*"

# Search for specific asset types
gcloud asset search-all-resources \
    --scope=projects/PROJECT_ID \
    --asset-types="compute.googleapis.com/Instance,storage.googleapis.com/Bucket"

# Search IAM policies across all resources
gcloud asset search-all-iam-policies \
    --scope=projects/PROJECT_ID \
    --query="policy:roles/owner"

# Find resources accessible by specific user
gcloud asset search-all-iam-policies \
    --scope=projects/PROJECT_ID \
    --query="policy:user:target@example.com"

# Export full asset inventory
gcloud asset export \
    --project=PROJECT_ID \
    --content-type=resource \
    --output-path=gs://BUCKET/assets.json

# OPSEC: Asset API provides comprehensive view
# Single API for all resource types
# Requires elevated permissions but extremely valuable

Admin Activity Audit Log Analysis:

bash

# Audit logs reveal who has what permissions based on actual usage
# Requires logging.logEntries.list permission

# List recent admin activities
gcloud logging read "protoPayload.methodName=~SetIamPolicy" \
    --project=PROJECT_ID \
    --limit=50 \
    --format=json

# Find recent service account key creations
gcloud logging read 'protoPayload.methodName="google.iam.admin.v1.CreateServiceAccountKey"' \
    --project=PROJECT_ID \
    --limit=20

# Find recent compute instance creations
gcloud logging read 'resource.type="gce_instance" AND protoPayload.methodName="v1.compute.instances.insert"' \
    --project=PROJECT_ID \
    --limit=20

# Find authentication events
gcloud logging read 'protoPayload.serviceName="iamcredentials.googleapis.com"' \
    --project=PROJECT_ID \
    --limit=50

# OPSEC: Log queries are themselves logged (meta-logging)
# Use filters to reduce noise
# Large log queries may trigger alerts

Enumerate Enabled APIs:

bash

# List enabled APIs and services in project
gcloud services list --enabled --project=PROJECT_ID

# Check if specific API is enabled
gcloud services list --enabled --filter="name:compute.googleapis.com" --project=PROJECT_ID

# Common high-value APIs to check:
# - compute.googleapis.com (Compute Engine)
# - storage-api.googleapis.com (Cloud Storage)
# - iam.googleapis.com (IAM)
# - cloudkms.googleapis.com (Key Management)
# - sqladmin.googleapis.com (Cloud SQL)
# - container.googleapis.com (GKE)

# PRIVILEGE ESCALATION: Enable APIs (if you have permissions)
gcloud services enable compute.googleapis.com --project=PROJECT_ID

# OPSEC: Enabled APIs indicate which services are in use
# Disabled APIs limit attack surface
# Enabling APIs generates logs and may trigger alerts

Quick Privilege Check Script:

bash

#!/bin/bash
# GCP Quick Privilege Enumeration
# Usage: ./gcp-priv-check.sh PROJECT_ID

PROJECT_ID=$1

echo "[*] GCP Privilege Enumeration for $PROJECT_ID"
echo ""

echo "[+] Current Identity:"
gcloud config get-value account

echo ""
echo "[+] Current Project:"
gcloud config get-value project

echo ""
echo "[+] Testing High-Value Permissions:"

# Test Owner role
echo -n "  - resourcemanager.projects.setIamPolicy (Owner): "
gcloud projects get-iam-policy $PROJECT_ID &>/dev/null && echo "YES" || echo "NO"

# Test service account key creation
echo -n "  - iam.serviceAccountKeys.create: "
gcloud iam service-accounts keys list --iam-account=test@$PROJECT_ID.iam.gserviceaccount.com &>/dev/null && echo "YES" || echo "NO"

# Test compute instance creation
echo -n "  - compute.instances.create: "
gcloud compute instances list --project=$PROJECT_ID &>/dev/null && echo "YES (list)" || echo "NO"

# Test storage bucket access
echo -n "  - storage.buckets.list: "
gsutil ls -p $PROJECT_ID &>/dev/null && echo "YES" || echo "NO"

# Test service account impersonation
echo ""
echo "[+] Checking Service Account Impersonation:"
for sa in $(gcloud iam service-accounts list --format="value(email)" --project=$PROJECT_ID 2>/dev/null); do
    if gcloud iam service-accounts get-access-token $sa &>/dev/null; then
        echo "  [!] Can impersonate: $sa"
    fi
done

echo ""
echo "[+] High-Privilege Service Accounts:"
gcloud projects get-iam-policy $PROJECT_ID \
    --flatten="bindings[].members" \
    --filter="bindings.role:roles/owner OR bindings.role:roles/editor" \
    --format="table(bindings.role,bindings.members)" 2>/dev/null | grep serviceAccount

echo ""
echo "[+] Enabled APIs:"
gcloud services list --enabled --project=$PROJECT_ID --format="value(config.name)" | head -10

echo ""
echo "[*] Enumeration Complete"

Make script executable and run:
#

chmod +x gcp-priv-check.sh
./gcp-priv-check.sh my-project-id