aws-ebs-copy-snapshot-exfil
ec2:CopySnapshot called from an attacker account (on a shared snapshot) or with a destination in another account copies snapshot data cross-boundary.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?snapshot) ==
Snapshot
?principal has EFFECTIVE ec2:CopySnapshot
?snapshot.owner_account != ?principal.account (principal reads snapshot from a different account than the owner)
emit
| source type | Identity |
|---|---|
| target type | Snapshot |
| source | ?principal |
| target | ?snapshot |
| permissions | ec2:CopySnapshot |
| conditions | iam_permission key_permission |
| state logic | ACTIVE when ec2:CopySnapshot is effective AND the snapshot is readable from the caller's account (createVolumePermission grants the caller or 'all'). The WHERE clause ensures cross-account access: the snapshot belongs to a different account than the principal. CONDITIONAL(key_permission) if the snapshot is CMK-encrypted and the key is not shared with the destination account. NOTE: The destination account is a runtime decision (caller specifies it in the CopySnapshot call) and cannot be determined from the graph at rule-match time — only verify that the source is cross-account. Analysts must review the actual CopySnapshot calls to confirm exfiltration to attacker accounts. |
Narrative
{principal.name} can call ec2:CopySnapshot to duplicate {snapshot.name} (owned by a different account) to a caller-specified destination, gaining a persistent copy of the disk data outside the original account boundary.
Raw rule rules/derived/aws/ebs.yaml
id: aws-ebs-copy-snapshot-exfil
emits: CanExfiltrate
description: ec2:CopySnapshot called from an attacker account (on a shared snapshot) or with a destination
in another account copies snapshot data cross-boundary.
match:
- - principal: null
- CanRead
- snapshot: null
where:
- node_type(?snapshot) == Snapshot
- ?principal has EFFECTIVE ec2:CopySnapshot
- ?snapshot.owner_account != ?principal.account (principal reads snapshot from a different account than
the owner)
emit:
source_type: Identity
target_type: Snapshot
source: ?principal
target: ?snapshot
permissions:
- ec2:CopySnapshot
conditions:
- iam_permission
- key_permission
state_logic: "ACTIVE when ec2:CopySnapshot is effective AND the snapshot is readable from the caller's\
\ account (createVolumePermission grants the caller or 'all'). The WHERE clause ensures cross-account\
\ access: the snapshot belongs to a different account than the principal. CONDITIONAL(key_permission)\
\ if the snapshot is CMK-encrypted and the key is not shared with the destination account. NOTE: The\
\ destination account is a runtime decision (caller specifies it in the CopySnapshot call) and cannot\
\ be determined from the graph at rule-match time \u2014 only verify that the source is cross-account.\
\ Analysts must review the actual CopySnapshot calls to confirm exfiltration to attacker accounts."
confidence: 0.85
derived_from:
- <CanRead edge on ?snapshot>
false_positive_note: "CopySnapshot copies into the caller's account (or a caller-specified destination\
\ if using the Destination parameter) \u2014 the caller must already have createVolumePermission on\
\ the source snapshot (own it or have it shared). Do not emit if the snapshot is only accessible within\
\ the owner account. The destination account and region are API call parameters, not graph properties\
\ \u2014 this rule conservatively emits when cross-account read is confirmed, but analysts must validate\
\ the actual call destinations. Cross-region copy requires ec2:CopySnapshot to be permitted in the\
\ destination region as well (honor region-level SCPs). For CMK-encrypted snapshots, the destination\
\ account must either have the key shared or be able to decrypt under the source account's key access\
\ \u2014 verify this before reporting ACTIVE."
narrative: '{principal.name} can call ec2:CopySnapshot to duplicate {snapshot.name} (owned by a different
account) to a caller-specified destination, gaining a persistent copy of the disk data outside the
original account boundary.'