aws-memorydb-snapshot-exfil

memorydb:CopySnapshot exports cluster snapshot to S3; attacker-accessible bucket yields full data exfiltration.

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::MemoryDB::Snapshot' ?principal has EFFECTIVE memorydb:CopySnapshot on ?snapshot ARN

emit

source typeIdentity
target typeSnapshot
source?principal
target?snapshot
permissionsmemorydb:CopySnapshot
conditionsiam_permission scp_or_org_policy resource_policy key_permission
state logicCONDITIONAL(resource_policy): the principal can call memorydb:CopySnapshot to export the snapshot to an S3 bucket. However, the destination bucket must be attacker-accessible (principal controls the bucket, or bucket policy allows writes from the principal's account, or cross-account S3 write edge exists). Upgrade to ACTIVE only when the destination bucket is confirmed attacker-accessible. CONDITIONAL(key_permission) when the snapshot is encrypted with a CMK: the CopySnapshot call succeeds, but reading the snapshot content in S3 requires kms:Decrypt on the CMK. BLOCKED when an SCP or permission boundary denies memorydb:CopySnapshot.

Narrative

{principal.name} can call memorydb:CopySnapshot to export the MemoryDB snapshot {snapshot.name} to an S3 bucket as a complete data dump. The snapshot contains all in-memory cluster data at snapshot time, including any cached application secrets, session tokens, API keys, or database credentials. If the destination S3 bucket is attacker-accessible, {principal.name} can download and parse the snapshot offline to extract all cached data without ever connecting to the live cluster.

Raw rule rules/derived/aws/memorydb.yaml

id: aws-memorydb-snapshot-exfil
emits: CanExfiltrate
description: memorydb:CopySnapshot exports cluster snapshot to S3; attacker-accessible bucket yields full
  data exfiltration.
match:
- - principal: null
  - HasPermission
  - snapshot: null
where:
- node_type(?snapshot) == Snapshot
- ?snapshot.provider_type == 'AWS::MemoryDB::Snapshot'
- ?principal has EFFECTIVE memorydb:CopySnapshot on ?snapshot ARN
emit:
  source_type: Identity
  target_type: Snapshot
  source: ?principal
  target: ?snapshot
  permissions:
  - memorydb:CopySnapshot
  conditions:
  - iam_permission
  - scp_or_org_policy
  - resource_policy
  - key_permission
  state_logic: 'CONDITIONAL(resource_policy): the principal can call memorydb:CopySnapshot to export the
    snapshot to an S3 bucket. However, the destination bucket must be attacker-accessible (principal controls
    the bucket, or bucket policy allows writes from the principal''s account, or cross-account S3 write
    edge exists). Upgrade to ACTIVE only when the destination bucket is confirmed attacker-accessible.
    CONDITIONAL(key_permission) when the snapshot is encrypted with a CMK: the CopySnapshot call succeeds,
    but reading the snapshot content in S3 requires kms:Decrypt on the CMK. BLOCKED when an SCP or permission
    boundary denies memorydb:CopySnapshot.'
  confidence: min(contributing_confidences) * 0.75
  derived_from:
  - ?principal HasPermission ?snapshot (memorydb:CopySnapshot effective permission)
  false_positive_note: "The destination S3 bucket is the critical gate. memorydb:CopySnapshot's TargetS3BucketName\
    \ parameter specifies where the snapshot is written. The attacker must have write access (s3:PutObject)\
    \ on the bucket to retrieve the snapshot file. Do NOT emit ACTIVE without confirming the bucket is\
    \ attacker-accessible (in the attacker's account, or the bucket policy allows the principal's account\
    \ to write). For encrypted snapshots (KmsKeyId is non-empty), the snapshot is encrypted with that\
    \ CMK; the attacker needs kms:Decrypt on the key to read the unencrypted snapshot file. AWS-managed\
    \ key (default aws/memorydb) is available per-account; custom CMKs require explicit key-grant evaluation.\
    \ This rule requires an existing snapshot \u2014 memorydb:CreateSnapshot must have been called first\
    \ (or a snapshot is pre-existing). The snapshot itself is the attack target, not the cluster; a snapshot\
    \ can persist long after the cluster is deleted. This rule is conservative (Phase-6 low-relevance\
    \ guidance: 1-3 rules). Snapshot exfil is powerful but requires two permissions (CopySnapshot + S3\
    \ access) and is more complex than the ACL-swap path."
  narrative: '{principal.name} can call memorydb:CopySnapshot to export the MemoryDB snapshot {snapshot.name}
    to an S3 bucket as a complete data dump. The snapshot contains all in-memory cluster data at snapshot
    time, including any cached application secrets, session tokens, API keys, or database credentials.
    If the destination S3 bucket is attacker-accessible, {principal.name} can download and parse the snapshot
    offline to extract all cached data without ever connecting to the live cluster.'
move · open · esc close