Article by Ben Leembruggen.
Exfiltrating S3 Data with Bucket Replication Policies
Related Reading: Data exfiltration with native AWS S3 features
Introduction
S3 data replication provides the ability to copy objects to another bucket, which can be useful from an enterprise logging, integration or security perspective. This can be configure between buckets in the same account, or an unrelated account. Where this feature could be abused is where a malicious actor could input a replication policy to copy objects to an attacker controlled bucket. Objects will continue to be replicated for as long as the policy in place, applying to all future objects placed into the bucket. Using S3 batch operations, attackers can also replicate objects already in the bucket, making it a convenient method for extracting all current and future objects uploaded to the impacted bucket.
Required Configurations and Permissions
Pre-requisites
For bucket replication to be enabled, the following pre-requisites need to be in place:
- The source bucket owner must have the source and destination AWS Regions enabled for their account. For the destination account, just the destination region needs to be enabled.
- Both source and destination buckets must have versioning enabled.
- If the source bucket has S3 Object Lock enabled, the destination buckets must also have S3 Object Lock enabled.
IAM Role
Minimum Required IAM Permissions - Source Account
iam:CreateRole
(creating a new role)iam:CreatePolicy
&iam:AttachRolePolicy
(creating a new policy) oriam:PutRolePolicy
(modifying an existing policy)iam:UpdateAssumeRolePolicy
Like most things in AWS, the replication service requires a user supplied role to carry out the replication on your behalf. To replicate all data (including existing objects), an example trust policy and permission set would look something like:
Trust Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"s3.amazonaws.com",
"batchoperations.s3.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
IAM Permissions
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetReplicationConfiguration",
"s3:ListBucket",
"s3:PutInventoryConfiguration",
"s3:InitiateReplication"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObjectVersionForReplication",
"s3:GetObjectVersionAcl",
"s3:GetObjectVersionTagging"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:ReplicateObject",
"s3:ReplicateDelete",
"s3:ReplicateTags"
],
"Resource": "*"
},
{
"Sid": "OnlyRequiredIfReplicatingEncryptedObjects",
"Effect":"Allow",
"Action":[
"kms:Decrypt"
],
"Condition":{
"StringLike":{
"kms:EncryptionContext:aws:s3:arn":[
"arn:aws:s3:::SOURCEBUCKET/*"
]
}
},
"Resource":[
"KEY ID IN SOURCE ACCOUNT CURRENTLY ENCRYPTING OBJECTS"
]
},
{
"Sid": "OnlyRequiredIfReplicatingEncryptedObjectsToo",
"Effect":"Allow",
"Action":[
"kms:Encrypt"
],
"Condition":{
"StringLike":{
"kms:EncryptionContext:aws:s3:arn":[
"arn:aws:s3:::DESTINATIONBUCKET/*"
]
}
},
"Resource":[
"KEY ID IN DESTINATION ACCOUNT TO BE SPECIFIED IN REPLICATION POLICY"
]
}
]
}
KMS - If objects are encrypted
Minimum Required IAM Permissions - Source Account
kms:PutKeyPolicy
Where a KMS policy is configured to only allow a subset of principals to access an encrypted S3 object, the key policy will need to be updated to allow the above replication role access to decrypt the S3 objects.
Attacker Account Configuration
Minimum Required IAM Permissions (Destination Account)
s3:PutBucketPolicy
kms:CreateKey
,kms:PutKeyPolicy
s3:PutBucketVersioning
In order for a bucket to receive logs from another account, it requires a bucket policy explicitly allowing the replication of objects across. An example of this policy is below.
Destination Bucket Policy
{
"Version":"2012-10-17",
"Id":"",
"Statement":[
{
"Sid":"Set permissions for objects",
"Effect":"Allow",
"Principal":{
"AWS":"arn:aws:iam::SOURCE_ACCOUNT_ID:role/S3_REPLICATION_ROLE"
},
"Action":[
"s3:ReplicateObject",
"s3:ReplicateDelete"],
"Resource":"arn:aws:s3:::DESTINATION_BUCKET/*"
},
{
"Sid":"Set permissions on bucket",
"Effect":"Allow",
"Principal":{
"AWS":"arn:aws:iam::SOURCE_ACCOUNT_ID:role/S3_REPLICATION_ROLE"
},
"Action":[
"s3:List*",
"s3:GetBucketVersioning",
"s3:PutBucketVersioning"],
"Resource":"arn:aws:s3:::DESTINATION_BUCKET"
}
]
}
If the S3 objects in the source account are encrypted, a key must be created in the destination account to encrypt the objects on replication. Additionally, a pre-requisite of bucket replication is that Bucket Versioning is enabled on the destination bucket.
Configuring the replication
Minimum Required IAM Permissions - Source Account
s3:PutBucketReplication
iam:PassRole
s3:CreateJob
&s3:UpdateJobStatus
(Creating and starting a S3 batch replication job)s3:PutBucketVersioning
(Only if not already enabled)
The final step is to configure the replication between the source and destination buckets. Depending on whether you use the CLI or console, the steps can change slightly. The full process for both options is documented by AWS here.
In line with the steps above, ensure that:
- Specify your created S3 replication role
- Replicate existing objects (Disabled by default)
- Select Replicate KMS Encrypted objects if needed (Disabled by default)
- The Key ID should be the KMS key in the destination account.
What defenders can look for
- Unknown
PutBucketReplication
orJobCreated
events in the Cloudtrail Management trail. TheJobCreated
event is generated when an S3 Batch operation job has been created, indicating that all existing objects in a bucket are being replicated across, as opposed to only future S3 objects.
-
When an encrypted object is replicated, KMS
Decrypt
/Encrypt
events will appear in a Cloudtrail Management trail, with a principalID and sts assumed role prefixed with 's3-replication'. These encryption events will reference a KMS key in another account - which may trigger certain data perimeter detections. -
Unknown
PutBucketVersioning
events (a pre-requisite of bucket replication) on existing S3 buckets, recorded by the Cloudtrail Management trail.