gcp-gcs-exfiltrate

storage.objects.get on the source bucket + storage.objects.create on a destination bucket (cross-project or attacker-controlled) constitute effective data exfiltration; achievable via storage.objects.copy (rewriteObject) which combines read+write permissions.

derived gcp emits CanExfiltrate

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'principal': None} CanReadData {'bucket': None}

where

?principal has EFFECTIVE storage.objects.create on a destination bucket in a different project or attacker-controlled bucket node_type(?bucket) == ObjectStorage

emit

source typeIdentity
target typeStorage
source?principal
target?bucket
permissionsstorage.objects.get storage.objects.create
conditionsiam_permission resource_policy
state logicACTIVE when CanReadData(?principal, ?bucket) is ACTIVE AND storage.objects.create on a writable destination bucket (ideally attacker-controlled or cross-project) is confirmed; CONDITIONAL(iam_permission) when destination bucket write rights are uncertain; POTENTIAL when no destination write path is modeled. CMEK state inherits from the CanReadData input (CONDITIONAL(key_permission) if CMEK gated).

Narrative

{principal.name} can read objects from {bucket.name} (storage.objects.get) and write them to an attacker-controlled or cross-project bucket (storage.objects.create), enabling exfiltration via storage.objects.copy or gcloud storage cp to move data outside the project boundary.

Raw rule rules/derived/gcp/gcs.yaml

id: gcp-gcs-exfiltrate
emits: CanExfiltrate
description: storage.objects.get on the source bucket + storage.objects.create on a destination bucket
  (cross-project or attacker-controlled) constitute effective data exfiltration; achievable via storage.objects.copy
  (rewriteObject) which combines read+write permissions.
match:
- - principal: null
  - CanReadData
  - bucket: null
where:
- ?principal has EFFECTIVE storage.objects.create on a destination bucket in a different project or attacker-controlled
  bucket
- node_type(?bucket) == ObjectStorage
emit:
  source_type: Identity
  target_type: Storage
  source: ?principal
  target: ?bucket
  permissions:
  - storage.objects.get
  - storage.objects.create
  conditions:
  - iam_permission
  - resource_policy
  state_logic: ACTIVE when CanReadData(?principal, ?bucket) is ACTIVE AND storage.objects.create on a
    writable destination bucket (ideally attacker-controlled or cross-project) is confirmed; CONDITIONAL(iam_permission)
    when destination bucket write rights are uncertain; POTENTIAL when no destination write path is modeled.
    CMEK state inherits from the CanReadData input (CONDITIONAL(key_permission) if CMEK gated).
  confidence: min(contributing_confidences) * 0.92
  derived_from:
  - ?principal CanReadData ?bucket
  - storage.objects.create on destination bucket
  false_positive_note: 'Exfiltration requires write access to a destination bucket outside the source
    project boundary or controlled by the attacker. The GCS JSON API storage.objects.copy (rewriteObject)
    operation uses the SAME permissions required by this rule: storage.objects.get on the source AND storage.objects.create
    on the destination. Both the copy operation and the gcloud storage cp command use storage.objects.get
    + storage.objects.create and are covered by this rule. A write-only path to a bucket in the SAME project
    without read may indicate supply-chain risk but not exfiltration. VPC-SC perimeters that co-perimeter
    source and destination projects may block cross-perimeter object copies -> BLOCKED(resource_policy).
    Object lifecycle / retention does not block copy operations to a different bucket. Storage Transfer
    Service (storagetransfer.*) is a separate API and requires separate permissions not modeled here.'
  narrative: '{principal.name} can read objects from {bucket.name} (storage.objects.get) and write them
    to an attacker-controlled or cross-project bucket (storage.objects.create), enabling exfiltration
    via storage.objects.copy or gcloud storage cp to move data outside the project boundary.'
move · open · esc close