aws-ebs-direct-api-exfil
EBS direct API read on a cross-account shared snapshot constitutes data exfiltration: the caller reads another account's disk data from their own account without ever launching an EC2 instance in the source account. This rule chains CanReadData on a cross-account snapshot into CanExfiltrate.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?snapshot) ==
Snapshot
?snapshot.owner_account != ?principal.account
emit
| source type | Identity |
|---|---|
| target type | Snapshot |
| source | ?principal |
| target | ?snapshot |
| permissions | ebs:ListSnapshotBlocks ebs:GetSnapshotBlock |
| conditions | iam_permission key_permission |
| state logic | Inherit from aws-ebs-direct-api-read CanReadData: ACTIVE if the CanReadData edge is ACTIVE, CONDITIONAL if gated by key_permission or other conditions. The CanExfiltrate edge summarizes the meaningful capability: data from another account CAN be exfiltrated, regardless of which rule (ebs direct API, volume mount, etc.) produced the CanReadData edge. Do NOT filter on rule_id provenance. |
Narrative
{principal.name} can read blocks of {snapshot.name} (owned by a different account) via ebs:GetSnapshotBlock, constituting cross-account data exfiltration without any EC2 instance running in the source account.
Raw rule rules/derived/aws/ebs.yaml
id: aws-ebs-direct-api-exfil
emits: CanExfiltrate
description: 'EBS direct API read on a cross-account shared snapshot constitutes data exfiltration: the
caller reads another account''s disk data from their own account without ever launching an EC2 instance
in the source account. This rule chains CanReadData on a cross-account snapshot into CanExfiltrate.'
match:
- - principal: null
- CanReadData
- snapshot: null
where:
- node_type(?snapshot) == Snapshot
- ?snapshot.owner_account != ?principal.account
emit:
source_type: Identity
target_type: Snapshot
source: ?principal
target: ?snapshot
permissions:
- ebs:ListSnapshotBlocks
- ebs:GetSnapshotBlock
conditions:
- iam_permission
- key_permission
state_logic: 'Inherit from aws-ebs-direct-api-read CanReadData: ACTIVE if the CanReadData edge is ACTIVE,
CONDITIONAL if gated by key_permission or other conditions. The CanExfiltrate edge summarizes the
meaningful capability: data from another account CAN be exfiltrated, regardless of which rule (ebs
direct API, volume mount, etc.) produced the CanReadData edge. Do NOT filter on rule_id provenance.'
confidence: 0.9
derived_from:
- <CanReadData edge on ?snapshot where ?snapshot.owner_account != ?principal.account>
false_positive_note: "Only emit when the snapshot genuinely belongs to a different account (cross- account\
\ data boundary crossing). If the snapshot is in the same account, the CanReadData edge is still real\
\ but it is not an exfiltration \u2014 omit CanExfiltrate and emit only CanReadData. All CMEK caveats\
\ from aws-ebs-direct-api-read apply. The CanReadData edge may be produced by any rule (direct API,\
\ volume mount, etc.); this rule does NOT require provenance from a specific rule."
narrative: '{principal.name} can read blocks of {snapshot.name} (owned by a different account) via ebs:GetSnapshotBlock,
constituting cross-account data exfiltration without any EC2 instance running in the source account.'