For the complete documentation index, see llms.txt. This page is also available as Markdown.

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:

Permission
Scope of effect

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

  1. Open GCP Console → Compute Engine → Metadata to review project-wide metadata, including any ssh-keys entries that apply across all VMs.

  2. 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.

  3. Check IAM & Admin → IAM for Compute Admin, Compute Instance Admin (v1), Editor, and Owner grants.

  4. Inspect custom roles under IAM & Admin → Roles for compute.instances.setMetadata or compute.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

  1. Enforce OS Login with an organization policy — apply the compute.requireOsLogin constraint 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.

  2. Set block-project-ssh-keys=TRUE on every VM so project-wide metadata keys cannot reach it, and enforce this at provisioning time rather than retrospectively.

  3. Treat roles/compute.instanceAdmin.v1, roles/editor, and roles/owner as shell-on-every-VM roles. Do not grant them for routine compute operations; prefer narrowly scoped custom roles that exclude compute.instances.setMetadata and compute.projects.setCommonInstanceMetadata.

  4. 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.

  5. 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.

  6. Block metadata server access from workloads that do not need it.

  7. 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.

Log Type
Method
Key Fields

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-keys metadata, at instance or project scope, by a principal that is not the expected provisioning pipeline.

  • enable-oslogin being set to FALSE — legitimate operations rarely disable OS Login, and doing so is a strong precursor to key injection.

  • Project-wide setCommonInstanceMetadata calls, which affect every VM without block-project-ssh-keys=TRUE at 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?