aws-neptune-snapshot-already-public-exfil

Neptune cluster snapshot with public restore attribute (restore=all) is immediately exfiltrable by any AWS account via RestoreDBClusterFromSnapshot.

derived aws emits CanExfiltrate

match

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

{'snapshot': None} CrossAccountTrust {'account': None}

where

node_type(?snapshot) == Snapshot node_type(?account) == Account ?snapshot.SnapshotType == 'manual'

emit

source typeAnonymousIdentity
target typeSnapshot
source<AnonymousIdentity>
target?snapshot
permissionsrds:RestoreDBClusterFromSnapshot
conditionskey_permission
state logicACTIVE when the snapshot has a public restore permission (AttributeValues='all', emitted as CrossAccountTrust to external Account) and is a manual snapshot. Any AWS account can call rds:RestoreDBClusterFromSnapshot to obtain a full offline copy of all graph data. CONDITIONAL(key_permission) only if the snapshot is encrypted with a customer-managed KMS key (CMK) — the restoring account must also hold kms:Decrypt / kms:CreateGrant on the CMK for the restore to succeed. Without the key grant, the restore call fails.

Narrative

Neptune cluster snapshot {snapshot.name} is immediately restorable by any AWS account (AttributeValues='all'). Any account can call rds:RestoreDBClusterFromSnapshot to create a full copy of all graph data (vertices, edges, properties) - the snapshot itself is a complete offline exfiltration surface requiring no credentials or additional action from the attacker.

Raw rule rules/derived/aws/neptune.yaml

id: aws-neptune-snapshot-already-public-exfil
emits: CanExfiltrate
description: Neptune cluster snapshot with public restore attribute (restore=all) is immediately exfiltrable
  by any AWS account via RestoreDBClusterFromSnapshot.
match:
- - snapshot: null
  - CrossAccountTrust
  - account: null
where:
- node_type(?snapshot) == Snapshot
- node_type(?account) == Account
- ?snapshot.SnapshotType == 'manual'
emit:
  source_type: AnonymousIdentity
  target_type: Snapshot
  source: <AnonymousIdentity>
  target: ?snapshot
  permissions:
  - rds:RestoreDBClusterFromSnapshot
  conditions:
  - key_permission
  derived_from:
  - CrossAccountTrust(?snapshot, ?account)
  state_logic: "ACTIVE when the snapshot has a public restore permission (AttributeValues='all', emitted\
    \ as CrossAccountTrust to external Account) and is a manual snapshot. Any AWS account can call rds:RestoreDBClusterFromSnapshot\
    \ to obtain a full offline copy of all graph data. CONDITIONAL(key_permission) only if the snapshot\
    \ is encrypted with a customer-managed KMS key (CMK) \u2014 the restoring account must also hold kms:Decrypt\
    \ / kms:CreateGrant on the CMK for the restore to succeed. Without the key grant, the restore call\
    \ fails."
  narrative: "Neptune cluster snapshot {snapshot.name} is immediately restorable by any AWS account (AttributeValues='all').\
    \ Any account can call rds:RestoreDBClusterFromSnapshot to create a full copy of all graph data (vertices,\
    \ edges, properties) \u2014 the snapshot itself is a complete offline exfiltration surface requiring\
    \ no credentials or additional action from the attacker."
move · open · esc close