Amazon CloudFront is a global CDN that delivers content with low latency. It sits in front of origins (S3, ALB, EC2, custom) and can be a critical security boundary for web applications.
CloudFront caches and delivers content from edge locations worldwide. Supports static files, dynamic content, streaming, and WebSocket connections. Can serve as reverse proxy for APIs.
Origins: S3 buckets, ALB/ELB, EC2, Lambda@Edge, API Gateway, custom HTTP servers
Integrates with WAF, Shield, ACM for DDoS protection and TLS. Supports signed URLs/cookies, geo-restriction, field-level encryption, and Origin Access Control (OAC).
Edge compute: Lambda@Edge and CloudFront Functions for request/response manipulation at edge locations
CloudFront misconfigurations can expose origin servers, bypass WAF rules, leak sensitive data via cache poisoning, and allow unauthorized access to private content. Origin takeover is a critical risk.
aws cloudfront list-distributions --query 'DistributionList.Items[*].[Id,DomainName,Origins.Items[0].DomainName]'aws cloudfront get-distribution-config --id EXXXXXXXXXXaws cloudfront list-origin-access-controlsaws cloudfront get-cache-policy --id XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXaws cloudfront list-functionsTip: Look for endpoints where static file extensions cause caching of dynamic content containing user data.
aws cloudfront list-distributions \
--query "DistributionList.Items[?contains(Aliases.Items, 'target.com')].Id" \
--output textaws cloudfront get-distribution --id EXXXXXXXXXX \
--query "Distribution.DistributionConfig.Origins.Items[*].DomainName"curl -H "X-Forwarded-Host: evil.com" \
-H "X-Original-URL: /admin" \
https://target.cloudfront.net/page# If you see "NoSuchBucket" error
aws s3api head-bucket --bucket origin-bucket-name 2>&1 | grep -q "404" && echo "Takeover possible!"aws cloudfront create-invalidation \
--distribution-id EXXXXXXXXXX \
--paths "/*"aws cloudfront get-distribution --id EXXXXXXXXXX \
--query "Distribution.DistributionConfig.DefaultCacheBehavior.TrustedSigners"{
"Version": "2012-10-17",
"Statement": [{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}]
}Bucket is publicly accessible - CloudFront provides no real protection
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "AllowCloudFrontOAC",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/EXXXXXXXXXX"
}
}
}]
}Only CloudFront can access origin via Origin Access Control
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity *"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}]
}Wildcard OAI allows any CloudFront distribution to access - use OAC instead
# CloudFront Custom Origin Config
Origin Custom Headers:
X-Origin-Verify: super-secret-value-123
# Origin Server Validation
if request.headers['X-Origin-Verify'] != 'super-secret-value-123':
return 403Custom header validates requests came through CloudFront
X-Forwarded-HostHost header injectionX-Original-URLPath manipulationX-Rewrite-URLURL rewritingX-Forwarded-SchemeProtocol confusionForwardedVarious injectionsHostStandard routingAuthorizationAuth differentiationAccept-EncodingCompression variantsAccept-LanguageLocalizationCloudFront-Viewer-CountryGeo targetingCache Poisoning: Find headers that affect the response but are NOT part of the cache key. Inject malicious values, get them cached, then all users receive the poisoned response.
Replace legacy OAI with OAC for S3 origins. Provides better security with SigV4 signing.
aws cloudfront create-origin-access-control \
--origin-access-control-config \
Name=MyOAC,SigningProtocol=sigv4,SigningBehavior=always,OriginAccessControlOriginType=s3Protect against common web attacks with AWS WAF rules.
aws cloudfront update-distribution \
--id EXXXXXXXXXX \
--distribution-config file://config.json
# Add WebACLId to configRedirect HTTP to HTTPS and use TLS 1.2+ for origin connections.
ViewerProtocolPolicy: redirect-to-https
OriginProtocolPolicy: https-only
OriginSSLProtocols: [TLSv1.2]Log all requests to S3 for security monitoring and incident response.
aws cloudfront update-distribution \
--id EXXXXXXXXXX \
--distribution-config '{"Logging":{"Enabled":true,"Bucket":"logs.s3.amazonaws.com","Prefix":"cf/"}}'Block direct access to origin by allowing only CloudFront IP ranges or using custom headers.
Protect private content with signed URLs or cookies using CloudFront key pairs.
# Generate signed URL
aws cloudfront sign \
--url https://d111.cloudfront.net/private/file.pdf \
--key-pair-id KXXXXXXXXXXXX \
--private-key file://private_key.pem \
--date-less-than 2024-12-31AWS CloudFront Security Card • Toc Consulting
Always obtain proper authorization before testing