gcp-cloudsql-clone-exfiltrate

cloudsql.instances.clone creates a full copy of a Cloud SQL instance (with all databases and data) accessible to the cloning principal in the same project - direct data exfiltration without external GCS access.

derived gcp emits CanExfiltrate

match (effective permission)

{ "action": "cloudsql.instances.clone", "resource_type": "google.sql.Instance" }

emit

source typeIdentity
target typeData
source<principal>
target<Cloud SQL Instance node (source)>
permissionscloudsql.instances.clone
conditionsiam_permission service_state network_reachability
state logicACTIVE when cloudsql.instances.clone is confirmed effective and the source instance is RUNNABLE; CONDITIONAL(service_state) when the instance state cannot be confirmed; BLOCKED when an org policy prevents instance cloning. Note: After cloning, the principal must also hold DB authentication credentials (or IAM DB auth if enabled) to actually query the cloned instance.

Narrative

{principal.name} holds cloudsql.instances.clone (via roles/cloudsql.admin) on {instance.name} and can create a full copy of the database instance in the same project, exfiltrating all data to a cloned instance the attacker can query directly (assuming DB authentication credentials are available).

Raw rule rules/derived/gcp/cloudsql.yaml

id: gcp-cloudsql-clone-exfiltrate
emits: CanExfiltrate
description: "cloudsql.instances.clone creates a full copy of a Cloud SQL instance (with all databases\
  \ and data) accessible to the cloning principal in the same project \u2014 direct data exfiltration\
  \ without external GCS access."
match_effective_permission:
  action: cloudsql.instances.clone
  resource_type: google.sql.Instance
emit:
  source_type: Identity
  target_type: Data
  source: <principal>
  target: <Cloud SQL Instance node (source)>
  permissions:
  - cloudsql.instances.clone
  conditions:
  - iam_permission
  - service_state
  - network_reachability
  state_logic: 'ACTIVE when cloudsql.instances.clone is confirmed effective and the source instance is
    RUNNABLE; CONDITIONAL(service_state) when the instance state cannot be confirmed; BLOCKED when an
    org policy prevents instance cloning. Note: After cloning, the principal must also hold DB authentication
    credentials (or IAM DB auth if enabled) to actually query the cloned instance.'
  false_positive_note: 'cloudsql.instances.clone is listed in roles/cloudsql.admin as a distinct permission.
    The clone is created as a new instance in the same project, accessible by the cloning principal via
    standard Cloud SQL access controls. The clone contains all databases and data from the source instance
    as of the clone creation time.

    IMPORTANT: After the clone is created, the attacker still requires DB-level access to query it. Cloning
    alone does NOT grant data access; the principal must ALSO satisfy one of: - Hold cloudsql.instances.connect
    + valid DB user password - Hold cloudsql.instances.login + IAM DB auth enabled on the cloned instance

    This CanExfiltrate edge assumes the attacker can subsequently authenticate (either via DB password
    or IAM auth). Unlike export (which writes to a GCS bucket the service agent can access), clone creates
    a managed Cloud SQL instance the attacker can query directly IF they hold the auth credentials. This
    is often a higher-value exfil path than export because it preserves DB structure and allows live querying
    (not just a one-time dump).'
  narrative: '{principal.name} holds cloudsql.instances.clone (via roles/cloudsql.admin) on {instance.name}
    and can create a full copy of the database instance in the same project, exfiltrating all data to
    a cloned instance the attacker can query directly (assuming DB authentication credentials are available).'
  derived_from:
  - cloudsql.instances.clone effective permission on google.sql.Instance
move · open · esc close