GCP_INJECT_SSH_KEY
Summary
Forestall ACL Alias
GCP_INJECT_SSH_KEY
GCP Alias
Compute Execution & Pipeline Pivots
Affected Object Types
Virtual Machines
Exploitation Certainty
Likely
Granting Roles
roles/owner, roles/editor, roles/compute.admin, roles/compute.instanceAdmin.v1, roles/compute.instanceAdmin
Description
GCP_INJECT_SSH_KEY indicates that an identity can write instance or project metadata on a GCE VM and thereby plant its own SSH public key, obtaining an interactive shell on a machine it was never granted login access to. The relevant permissions are:
compute.instances.setMetadata
A single instance — plants a key in that VM's ssh-keys metadata
compute.projects.setCommonInstanceMetadata
Every VM in the project that does not set block-project-ssh-keys=TRUE
The guest environment agent running on each VM polls its metadata and provisions a local Linux account for any key it finds in ssh-keys, granting it sudo. Writing metadata is therefore equivalent to creating a privileged local user, and no SSH-related permission is required to do it.
When OS Login is enforced, the guest agent ignores metadata SSH keys, which appears to neutralise this edge. It does not: enable-oslogin is itself a metadata key. An identity holding setMetadata can set enable-oslogin=FALSE and restore metadata-key processing before planting its key. The control that is supposed to contain the attack is writable by the same permission the attack uses.
Relationship to GCP_SSH_TO: Both edges end in a shell on a VM. GCP_SSH_TO uses the sanctioned OS Login path with an IAM-bound identity, and is fully attributable in audit logs. GCP_INJECT_SSH_KEY fabricates a local account instead, so subsequent SSH activity is not tied to any Google identity — the only IAM-attributable event is the metadata write itself. It is the stealthier of the two, and unlike GCP_SSH_TO it does not depend on OS Login being enabled.
As with any shell on a GCE VM, the objective is usually the metadata server rather than the host. A shell yields an OAuth token for the service account attached to the instance (see GCP_RUNS_AS), so the effective privilege gained is that of the VM's service account, which is frequently far broader than the compute role that enabled the injection.
Identification
gcloud CLI
A VM is exposed to project-level key injection whenever block-project-ssh-keys is absent or FALSE. A VM is exposed to instance-level injection regardless of that setting, and enable-oslogin=TRUE only mitigates it for attackers who cannot also rewrite metadata.
GCP Console
Open GCP Console → Compute Engine → Metadata to review project-wide metadata, including any
ssh-keysentries that apply across all VMs.Open Compute Engine → VM Instances → select an instance → Edit. The Metadata and SSH Keys sections show instance-level entries; Service accounts shows the identity a shell would inherit.
Check IAM & Admin → IAM for
Compute Admin,Compute Instance Admin (v1),Editor, andOwnergrants.Inspect custom roles under IAM & Admin → Roles for
compute.instances.setMetadataorcompute.projects.setCommonInstanceMetadata.
Exploitation
When appending to existing keys, read the current ssh-keys value and write it back together with the new entry — add-metadata replaces the whole key, so overwriting it removes legitimate access and is likely to be noticed.
With a shell established, harvest the attached service account's token:
The token is usable against Google APIs from anywhere until it expires:
If no external IP is present, the same session is available through an IAP tunnel with roles/iap.tunnelResourceAccessor:
Mitigation
Enforce OS Login with an organization policy — apply the
compute.requireOsLoginconstraint at org or folder scope. Set as an org policy it cannot be undone by a metadata write, which is what makes it effective; instance metadata alone is not a sufficient control.Set
block-project-ssh-keys=TRUEon every VM so project-wide metadata keys cannot reach it, and enforce this at provisioning time rather than retrospectively.Treat
roles/compute.instanceAdmin.v1,roles/editor, androles/owneras shell-on-every-VM roles. Do not grant them for routine compute operations; prefer narrowly scoped custom roles that excludecompute.instances.setMetadataandcompute.projects.setCommonInstanceMetadata.Audit custom roles for the metadata permissions — either permission is equivalent to root SSH on the instances in scope, and neither is obvious from a role's name.
Attach minimal-privilege service accounts to VMs and never the default Compute Engine service account with broad scopes. This caps the value of any shell obtained this way.
Block metadata server access from workloads that do not need it.
Restrict
roles/iap.tunnelResourceAccessor, which removes network reachability as a barrier.
Detection
The metadata write is the one reliably attributable moment in this attack — SSH activity afterwards belongs to a local account with no Google identity behind it. Detection should centre on the write.
Admin Activity
v1.compute.instances.setMetadata
Instance-level metadata write — inspect for ssh-keys, enable-oslogin
Admin Activity
v1.compute.projects.setCommonInstanceMetadata
Project-wide metadata write — affects all unprotected VMs
Admin Activity
v1.compute.instances.insert
New VM created without block-project-ssh-keys=TRUE
Admin Activity
SetIamPolicy
New compute.instanceAdmin*, compute.admin, editor, or owner bindings
Alert on:
Any write of
ssh-keysmetadata, at instance or project scope, by a principal that is not the expected provisioning pipeline.enable-osloginbeing set toFALSE— legitimate operations rarely disable OS Login, and doing so is a strong precursor to key injection.Project-wide
setCommonInstanceMetadatacalls, which affect every VM withoutblock-project-ssh-keys=TRUEat once.SSH logins by local Linux accounts that do not correspond to any OS Login identity.
Metadata server token requests from a VM shortly after a metadata write to that same instance.
VMs created without
block-project-ssh-keys=TRUE, which enlarges the project-wide injection surface.
References
https://cloud.google.com/compute/docs/connect/add-ssh-keys
https://cloud.google.com/compute/docs/metadata/overview
https://cloud.google.com/compute/docs/oslogin/set-up-oslogin
https://cloud.google.com/compute/docs/access/service-accounts
https://cloud.google.com/iap/docs/using-tcp-forwarding
Last updated
Was this helpful?