gcp-bigtable-exfiltrate-via-backup

A principal with bigtable.backups.read on a source backup AND bigtable.backups.create + bigtable.backups.restore in a destination instance (any project) can copy the backup cross-project and restore the full table contents in the destination, exfiltrating all data outside the source project boundary.

derived gcp emits CanExfiltrate

match (effective permission)

{ "action": [ "bigtable.backups.read", "bigtable.backups.create", "bigtable.backups.restore" ], "resource_type": [ "google.bigtable.admin.v2.Backup", "google.bigtable.admin.v2.Instance" ] }

where

principal HOLDS bigtable.backups.read ON source_backup principal HOLDS bigtable.backups.create ON destination_instance principal HOLDS bigtable.backups.restore ON destination_instance destination_instance.project NOT_EQUALS source_backup.project source_backup.instance.state EQUALS READY destination_instance.state EQUALS READY

emit

source typeIdentity
target typeBackup
source<principal>
target<Bigtable Backup node>
permissionsbigtable.backups.read bigtable.backups.create bigtable.backups.restore
conditionsiam_permission resource_policy key_permission
state logicACTIVE when bigtable.backups.read is confirmed on the source backup AND bigtable.backups.create + bigtable.backups.restore are confirmed in a destination instance in a different project AND both the source and destination instances are in READY state AND the destination cluster's CMEK key (if present) is compatible with the restored backup (either the source and destination clusters share the same KMS key, or the destination cluster's service agent holds the source backup's CMEK key's decrypt grant) AND no VPC-SC perimeter blocks backup copy operations; CONDITIONAL(iam_permission) when destination create/restore rights are uncertain (e.g., only project-scope billing confirmed, destination project is unmodeled); CONDITIONAL(key_permission) when destination cluster uses a different CMEK key than the source cluster and the destination cluster's service agent's access to that key or the source key's accessibility is unconfirmed; POTENTIAL when a destination instance exists but its accessibility is unconfirmed; BLOCKED when a VPC-SC perimeter prevents the cross-project backup copy call (bigtable.googleapis.com in the perimeter restricts API access), OR when the destination cluster's CMEK key is in DISABLED/DESTROYED state, OR when the destination cluster's service agent lacks the decrypt grant for the key required by the restored backup.

Narrative

{principal.name} holds bigtable.backups.read on backup {backup.name} (source of table {table.name}) and bigtable.backups.create + bigtable.backups.restore in a destination project; it can copy the backup cross-project and restore the full table contents in the destination, exfiltrating all of {table.name}'s data outside the source project boundary.

Raw rule rules/derived/gcp/bigtable.yaml

id: gcp-bigtable-exfiltrate-via-backup
emits: CanExfiltrate
description: A principal with bigtable.backups.read on a source backup AND bigtable.backups.create + bigtable.backups.restore
  in a destination instance (any project) can copy the backup cross-project and restore the full table
  contents in the destination, exfiltrating all data outside the source project boundary.
match_effective_permission:
  action:
  - bigtable.backups.read
  - bigtable.backups.create
  - bigtable.backups.restore
  resource_type:
  - google.bigtable.admin.v2.Backup
  - google.bigtable.admin.v2.Instance
where:
- principal HOLDS bigtable.backups.read ON source_backup
- principal HOLDS bigtable.backups.create ON destination_instance
- principal HOLDS bigtable.backups.restore ON destination_instance
- destination_instance.project NOT_EQUALS source_backup.project
- source_backup.instance.state EQUALS READY
- destination_instance.state EQUALS READY
emit:
  source_type: Identity
  target_type: Backup
  source: <principal>
  target: <Bigtable Backup node>
  permissions:
  - bigtable.backups.read
  - bigtable.backups.create
  - bigtable.backups.restore
  conditions:
  - iam_permission
  - resource_policy
  - key_permission
  state_logic: ACTIVE when bigtable.backups.read is confirmed on the source backup AND bigtable.backups.create
    + bigtable.backups.restore are confirmed in a destination instance in a different project AND both
    the source and destination instances are in READY state AND the destination cluster's CMEK key (if
    present) is compatible with the restored backup (either the source and destination clusters share
    the same KMS key, or the destination cluster's service agent holds the source backup's CMEK key's
    decrypt grant) AND no VPC-SC perimeter blocks backup copy operations; CONDITIONAL(iam_permission)
    when destination create/restore rights are uncertain (e.g., only project-scope billing confirmed,
    destination project is unmodeled); CONDITIONAL(key_permission) when destination cluster uses a different
    CMEK key than the source cluster and the destination cluster's service agent's access to that key
    or the source key's accessibility is unconfirmed; POTENTIAL when a destination instance exists but
    its accessibility is unconfirmed; BLOCKED when a VPC-SC perimeter prevents the cross-project backup
    copy call (bigtable.googleapis.com in the perimeter restricts API access), OR when the destination
    cluster's CMEK key is in DISABLED/DESTROYED state, OR when the destination cluster's service agent
    lacks the decrypt grant for the key required by the restored backup.
  confidence: min(contributing_confidences) * 0.92
  derived_from:
  - bigtable.backups.read effective permission on source Backup
  - bigtable.backups.create effective permission in destination project
  - bigtable.backups.restore effective permission in destination project
  false_positive_note: "ALL THREE permissions are required: bigtable.backups.read on the SOURCE backup\
    \ (allows copy), bigtable.backups.create in the DESTINATION instance (creates the copied backup),\
    \ and bigtable.backups.restore in the destination (restores the backup to a new table). Without source\
    \ backups.read, the copy call fails. Without destination create+restore, the data cannot be materialized.\
    \ bigtable.backups.get (read metadata) does NOT allow backup data copy \u2014 only bigtable.backups.read\
    \ enables copy operations. The destination restore always creates a NEW table (cannot overwrite an\
    \ existing table). For CMEK backups, the restored table in the destination cluster uses that cluster's\
    \ CMEK key (or Google-managed key if the destination cluster is not CMEK). If the source CMEK key\
    \ is not accessible to the destination cluster's service agent, the restore will fail -> emit as CONDITIONAL(key_permission)\
    \ when the destination cluster uses a different CMEK key than the source."
  narrative: '{principal.name} holds bigtable.backups.read on backup {backup.name} (source of table {table.name})
    and bigtable.backups.create + bigtable.backups.restore in a destination project; it can copy the backup
    cross-project and restore the full table contents in the destination, exfiltrating all of {table.name}''s
    data outside the source project boundary.'
move · open · esc close