aws-ebs-create-and-share-snapshot

CreateSnapshot + ModifySnapshotAttribute(add=<external account>) lets an attacker ship a full disk image to an account they control. The rule matches on the CanWrite capability on a volume and confirms effective IAM permissions for both snapshot creation and cross-account sharing.

derived aws emits CanExfiltrateCrossAccountTrust

match

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

{'principal': None} CanWrite {'volume': None}

where

node_type(?volume) == BlockStorage ?principal has EFFECTIVE ec2:CreateSnapshot scoped to ?volume or Resource: * ec2:ModifySnapshotAttribute is scoped to Resource: * OR a tag condition covering new snapshots (NOT fixed snapshot ARNs) the createVolumePermission mutation target is an account != owner account

emit

Raw rule rules/derived/aws/ebs.yaml

id: aws-ebs-create-and-share-snapshot
emits:
- CanExfiltrate
- CrossAccountTrust
description: CreateSnapshot + ModifySnapshotAttribute(add=<external account>) lets an attacker ship a
  full disk image to an account they control. The rule matches on the CanWrite capability on a volume
  and confirms effective IAM permissions for both snapshot creation and cross-account sharing.
match:
- - principal: null
  - CanWrite
  - volume: null
where:
- node_type(?volume) == BlockStorage
- '?principal has EFFECTIVE ec2:CreateSnapshot scoped to ?volume or Resource: *'
- 'ec2:ModifySnapshotAttribute is scoped to Resource: * OR a tag condition covering new snapshots (NOT
  fixed snapshot ARNs)'
- the createVolumePermission mutation target is an account != owner account
emit:
- source_type: Identity
  target_type: Snapshot
  source: ?principal
  target: ?snapshot (existing snapshot of ?volume, OR synthetic marker for POTENTIAL new snapshot)
  edge_type: CanExfiltrate
  permissions:
  - ec2:CreateSnapshot
  - ec2:ModifySnapshotAttribute
  conditions:
  - iam_permission
  state_logic: "CONDITIONAL(iam_permission) by default: the principal CAN create and share a snapshot\
    \ of ?volume (CreateSnapshot + ModifySnapshotAttribute effective). Upgrade to POTENTIAL when confirming\
    \ scope covers new snapshots. Upgrade to ACTIVE only when a snapshot of ?volume already exists in\
    \ the graph (match on AttachedTo to find existing snapshots of this volume) AND ModifySnapshotAttribute\
    \ is confirmed effective on that snapshot. Additional gate: ec2:CreateSnapshot on a RUNNING instance\
    \ may require ec2:StopInstances or crash-consistent mode \u2014 if Stop is absent, CONDITIONAL(service_state)."
  confidence: 0.75
  derived_from:
  - <CanWrite edge on ?volume>
  - Direct IAM evaluation of ec2:CreateSnapshot + ec2:ModifySnapshotAttribute
  false_positive_note: "CRITICAL: This rule only emits ACTIVE when targeting an EXISTING snapshot in the\
    \ graph. For new snapshots (POTENTIAL case), emit as CONDITIONAL with the caveat that the snapshot\
    \ must be created first before exfiltration is possible. If ec2:ModifySnapshotAttribute is scoped\
    \ to specific snapshot ARNs (fixed snap-*), the principal CANNOT modify newly-created snapshots \u2014\
    \ stay CONDITIONAL. A KMS-encrypted volume snapshot can be shared but only decrypted in the target\
    \ account if the CMK is also shared or the snapshot is re-encrypted with a shareable key \u2014 flag\
    \ as CONDITIONAL(key_permission) for encrypted volumes. Do NOT emit if ec2:CreateSnapshot is effectively\
    \ denied via SCP or permission boundary."
  narrative: '{principal.name} can call ec2:CreateSnapshot on {volume.name} and then ec2:ModifySnapshotAttribute
    to share a resulting snapshot with an attacker-controlled account, gaining full disk-image access
    (and any credentials stored on the disk) outside the account boundary. Exploitation requires that
    ModifySnapshotAttribute is scoped to cover new snapshots (Resource: * or tag-based), not just existing
    ones.'
- source_type: Snapshot
  target_type: Account
  source: ?snapshot (existing snapshot of ?volume, OR synthetic marker for POTENTIAL new snapshot)
  target: <external account from createVolumePermission>
  edge_type: CrossAccountTrust
  permissions:
  - ec2:ModifySnapshotAttribute
  conditions:
  - iam_permission
  state_logic: 'CONDITIONAL(iam_permission): the principal CAN grant createVolumePermission to the external
    account (ModifySnapshotAttribute effective). POTENTIAL when scoped to future snapshots. Inherit the
    state from the CanExfiltrate edge: if CanExfiltrate is ACTIVE, CrossAccountTrust is ACTIVE; if CONDITIONAL,
    CrossAccountTrust is CONDITIONAL.'
  confidence: 0.75
  derived_from:
  - ?principal's ec2:ModifySnapshotAttribute permission
  - <CanExfiltrate edge on same ?principal + ?snapshot>
  narrative: '{principal.name}''s ability to call ec2:ModifySnapshotAttribute means that snapshots derived
    from {volume.name} can be shared to the external account {target.name}, establishing a cross-account
    trust boundary.'
move · open · esc close