aws-redshift-snapshot-cross-account-exfil

redshift:AuthorizeSnapshotAccess grants another AWS account the ability to restore a cluster snapshot, exfiltrating a full copy of warehouse data to that account.

derived aws emits CanExfiltrate

match

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

{'principal': None} HasPermission {'snapshot': None}

where

node_type(?snapshot) == Snapshot ?snapshot.provider_type == 'AWS::Redshift::ClusterSnapshot' ?principal has EFFECTIVE redshift:AuthorizeSnapshotAccess on ?snapshot ARN

emit

source typeIdentity
target typeSnapshot
source?principal
target?snapshot
permissionsredshift:AuthorizeSnapshotAccess
conditionsiam_permission scp_or_org_policy
state logicACTIVE when redshift:AuthorizeSnapshotAccess is confirmed EFFECTIVE on the snapshot ARN (identity-based policy + no SCP deny). CONDITIONAL(iam_permission) when an SCP or permission boundary may restrict the action but isn't resolved. BLOCKED by an explicit SCP deny on redshift:AuthorizeSnapshotAccess. A successful AuthorizeSnapshotAccess does not automatically restore the cluster — it grants the permission; the exfiltration is realized when the target account calls RestoreFromClusterSnapshot. Emit CanExfiltrate here for the authorization capability; note the restore step as implicit.

Narrative

{principal.name} can share the Redshift snapshot {snapshot.name} with an external AWS account (redshift:AuthorizeSnapshotAccess), enabling that account to restore a full copy of the cluster's data - a complete warehouse exfiltration.

Raw rule rules/derived/aws/redshift.yaml

id: aws-redshift-snapshot-cross-account-exfil
emits: CanExfiltrate
description: redshift:AuthorizeSnapshotAccess grants another AWS account the ability to restore a cluster
  snapshot, exfiltrating a full copy of warehouse data to that account.
match:
- - principal: null
  - HasPermission
  - snapshot: null
where:
- node_type(?snapshot) == Snapshot
- ?snapshot.provider_type == 'AWS::Redshift::ClusterSnapshot'
- ?principal has EFFECTIVE redshift:AuthorizeSnapshotAccess on ?snapshot ARN
emit:
  source_type: Identity
  target_type: Snapshot
  source: ?principal
  target: ?snapshot
  permissions:
  - redshift:AuthorizeSnapshotAccess
  conditions:
  - iam_permission
  - scp_or_org_policy
  state_logic: "ACTIVE when redshift:AuthorizeSnapshotAccess is confirmed EFFECTIVE on the snapshot ARN\
    \ (identity-based policy + no SCP deny). CONDITIONAL(iam_permission) when an SCP or permission boundary\
    \ may restrict the action but isn't resolved. BLOCKED by an explicit SCP deny on redshift:AuthorizeSnapshotAccess.\
    \ A successful AuthorizeSnapshotAccess does not automatically restore the cluster \u2014 it grants\
    \ the permission; the exfiltration is realized when the target account calls RestoreFromClusterSnapshot.\
    \ Emit CanExfiltrate here for the authorization capability; note the restore step as implicit."
  confidence: min(contributing_confidences) * 0.95
  derived_from:
  - ?principal HasPermission ?snapshot (redshift:AuthorizeSnapshotAccess effective permission)
  false_positive_note: "AuthorizeSnapshotAccess grants a SPECIFIC account the restore permission; it is\
    \ not an open wildcard grant. The target account must then call RestoreFromClusterSnapshot, incurring\
    \ Redshift compute costs and typically appearing in CloudTrail. The snapshot must exist (not already\
    \ deleted via automated retention). KMS-encrypted snapshots (cluster uses a CMK) require the target\
    \ account to also be granted kms:Decrypt on the CMK \u2014 without it, RestoreFromClusterSnapshot\
    \ fails (CONDITIONAL(key_permission) on the exfil if the snapshot's CMK grant is unresolved)."
  narrative: "{principal.name} can share the Redshift snapshot {snapshot.name} with an external AWS account\
    \ (redshift:AuthorizeSnapshotAccess), enabling that account to restore a full copy of the cluster's\
    \ data \u2014 a complete warehouse exfiltration."
move · open · esc close