aws-s3-exfiltrate-replication
s3:PutReplicationConfiguration sets up continuous S3 Replication to an external/attacker-controlled destination bucket, establishing a persistent data exfiltration channel.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?bucket) ==
ObjectStorage
?bucket.provider_type == 'AWS::S3::Bucket'
?principal has EFFECTIVE s3:PutReplicationConfiguration on ?bucket ARN
?principal has EFFECTIVE iam:PassRole for a replication IAM role (required for every PutReplicationConfiguration call to pass the role ARN)
?bucket.properties.VersioningStatus == 'Enabled' (replication requires versioning on source bucket)
emit
| source type | Identity |
|---|---|
| target type | ObjectStorage |
| source | ?principal |
| target | ?bucket |
| permissions | s3:PutReplicationConfiguration iam:PassRole |
| conditions | iam_permission scp_or_org_policy role_compatibility |
| state logic | ACTIVE when s3:PutReplicationConfiguration AND iam:PassRole (for the replication role) are both EFFECTIVE, and bucket versioning is enabled. CONDITIONAL (role_compatibility) when the replication role or its destination permissions are unknown. CONDITIONAL(iam_permission) when s3:PutReplicationConfiguration is effective but iam:PassRole for a replication role with destination write access is not confirmed. BLOCKED by an SCP deny on PutReplicationConfiguration or iam:PassRole. Note: the destination bucket policy must also grant s3:ReplicateObject to the source replication role — if it does not, replication fails at the first object (emit CONDITIONAL(role_compatibility) when destination policy is unknown). |
Narrative
{principal.name} can configure S3 Replication on {bucket.name} (s3:PutReplicationConfiguration + iam:PassRole) to continuously copy all new objects to an external destination bucket - establishing a persistent exfiltration channel that survives credential rotation.
Raw rule rules/derived/aws/s3.yaml
id: aws-s3-exfiltrate-replication
emits: CanExfiltrate
description: s3:PutReplicationConfiguration sets up continuous S3 Replication to an external/attacker-controlled
destination bucket, establishing a persistent data exfiltration channel.
match:
- - principal: null
- HasPermission
- bucket: null
where:
- node_type(?bucket) == ObjectStorage
- ?bucket.provider_type == 'AWS::S3::Bucket'
- ?principal has EFFECTIVE s3:PutReplicationConfiguration on ?bucket ARN
- ?principal has EFFECTIVE iam:PassRole for a replication IAM role (required for every PutReplicationConfiguration
call to pass the role ARN)
- ?bucket.properties.VersioningStatus == 'Enabled' (replication requires versioning on source bucket)
emit:
source_type: Identity
target_type: ObjectStorage
source: ?principal
target: ?bucket
permissions:
- s3:PutReplicationConfiguration
- iam:PassRole
conditions:
- iam_permission
- scp_or_org_policy
- role_compatibility
state_logic: "ACTIVE when s3:PutReplicationConfiguration AND iam:PassRole (for the replication role)\
\ are both EFFECTIVE, and bucket versioning is enabled. CONDITIONAL (role_compatibility) when the\
\ replication role or its destination permissions are unknown. CONDITIONAL(iam_permission) when s3:PutReplicationConfiguration\
\ is effective but iam:PassRole for a replication role with destination write access is not confirmed.\
\ BLOCKED by an SCP deny on PutReplicationConfiguration or iam:PassRole. Note: the destination bucket\
\ policy must also grant s3:ReplicateObject to the source replication role \u2014 if it does not,\
\ replication fails at the first object (emit CONDITIONAL(role_compatibility) when destination policy\
\ is unknown)."
confidence: min(contributing_confidences) * 0.85
derived_from:
- ?principal HasPermission ?bucket (s3:PutReplicationConfiguration effective permission)
- iam:PassRole for replication IAM role
false_positive_note: "Replication requires SOURCE bucket versioning to be enabled (VersioningStatus:\
\ Enabled) \u2014 without it the API call succeeds but replication never starts. Check the bucket's\
\ VersioningConfiguration before emitting ACTIVE. The replication IAM role must have s3:GetObject\
\ / s3:GetObjectVersion on the source AND s3:ReplicateObject on the destination bucket; without both,\
\ objects fail to replicate. The DESTINATION bucket policy must allow the source role's account/ principal\
\ to write (s3:ReplicateObject) \u2014 cross-account replication requires the destination to explicitly\
\ grant this; if the destination is in the same account, the role's identity policy may be sufficient.\
\ SSE-KMS source objects also require the replication role to have kms:Decrypt on the source CMK and\
\ kms:GenerateDataKey on the destination CMK \u2014 CONDITIONAL(key_permission) when CMKs are involved\
\ and the role's key access is unconfirmed."
narrative: "{principal.name} can configure S3 Replication on {bucket.name} (s3:PutReplicationConfiguration\
\ + iam:PassRole) to continuously copy all new objects to an external destination bucket \u2014 establishing\
\ a persistent exfiltration channel that survives credential rotation."