# Route53 and CloudFront Enumeration

> Enumerate AWS Route53 hosted zones, DNS records, and CloudFront distributions to map attack surface, identify misconfigurations, and uncover exposed infrastructure.

- **URL:** https://hackindex.io/platforms/aws/enumeration/route53-cloudfront/route53-and-cloudfront-enumeration
- **Path:** AWS > Enumeration > Route53 / CloudFront
- **Up:** [Route53 / CloudFront](https://hackindex.io/platforms/aws/enumeration/route53-cloudfront.md)
- **Published:** 2026-05-24
- **Updated:** 2026-05-24

## Route53

### List Hosted Zones

Route53 zones define the DNS namespace for an account. Start here to map what domains the account controls. The output shows zone IDs, names, record counts, and whether each zone is public or private.

```bash
aws route53 list-hosted-zones --profile $PROFILE --query 'HostedZones[*].{ID:Id,Name:Name,Private:Config.PrivateZone,Records:ResourceRecordSetCount}' --output table
```

Private zones are only resolvable within the associated VPC: they expose internal hostnames. Access to private zone data requires VPC-level access or a role with route53:ListResourceRecordSets permission. A zone with many records and internal naming patterns is worth enumerating fully. Look for subdomains naming databases, internal APIs, or admin services.

### List All DNS Records

Replace $DOMAIN with the zone's exact name including the trailing dot, or the select filter returns nothing. This command pulls one value per record set, so aliased records may not show a raw IP. Run it for each zone ID from the previous step.

```bash
ZONE_ID=$(aws route53 list-hosted-zones --profile $PROFILE | jq -r '.HostedZones[] | select(.Name=="$DOMAIN.") | .Id' | cut -d'/' -f3)
aws route53 list-resource-record-sets --hosted-zone-id $ZONE_ID --profile $PROFILE --query 'ResourceRecordSets[*].{Name:Name,Type:Type,TTL:TTL,Value:ResourceRecords[0].Value}' --output table
```

CNAME records pointing to AWS services (S3, Elastic Beanstalk, CloudFront) may be dangling takeover candidates. See [S3 Bucket Discovery](https://hackindex.io/platforms/aws/reconnaissance/s3-bucket-discovery). A dangling CNAME points to a resource that no longer exists. If the target service accepts registrations, you can claim it. For S3, check if the bucket named in the CNAME is unregistered and in the same region. For Elastic Beanstalk, look for a matching environment name that can be recreated.

### Private Zone Records

Private zones reveal internal service names, database hostnames, internal load balancers, and microservice endpoints. This data is only useful once you have VPC-level access or a role with route53 read permissions. Use the record names to map the internal architecture. Database hostnames matching RDS patterns confirm the database engine. Internal load balancer names often follow patterns that reveal environment names or team ownership.

```bash
aws route53 list-resource-record-sets --hosted-zone-id $ZONE_ID --profile $PROFILE | jq '.ResourceRecordSets[] | select(.Type == "A" or .Type == "CNAME")'
```

### Health Checks

Route53 health checks reveal which endpoints are being monitored and their status. The target domain and port identify services the account treats as critical. An unhealthy check means the endpoint is down or rate-limiting the health check probe. HTTP and HTTPS checks confirm what port and path the service expects. Endpoints listed here but absent from public DNS may be internal services exposed for monitoring only.

```bash
aws route53 list-health-checks --profile $PROFILE --query 'HealthChecks[*].{ID:Id,Type:HealthCheckConfig.Type,Target:HealthCheckConfig.FullyQualifiedDomainName,Port:HealthCheckConfig.Port}' --output table
```

## CloudFront

### List Distributions

CloudFront distributions are CDN configurations that sit in front of origins. Each distribution has a unique ID and a `.cloudfront.net` domain. The output shows which origins are behind the CDN and whether each distribution is active. A disabled distribution still exists and may accept configuration queries.

```bash
aws cloudfront list-distributions --profile $PROFILE --query 'DistributionList.Items[*].{ID:Id,Domain:DomainName,Origins:Origins.Items[0].DomainName,Enabled:Enabled,Status:Status}' --output table
```

### Get Distribution Config

Full config including origins, behaviours, WAF associations, and geo-restrictions. Check the WAFWebACLId field: an empty value means no WAF is attached. Geo-restrictions show which countries are blocked or allowed. Viewer protocol policy controls whether HTTP is redirected to HTTPS or allowed plaintext. A `allow-all` viewer protocol means HTTP requests reach the origin unencrypted.

```bash
aws cloudfront get-distribution --id $DISTRIBUTION_ID --profile $PROFILE
```

Origin domain names may reveal:

- S3 bucket names (potential public access if misconfigured)
- Internal ALB DNS names (reachable directly if security groups allow it)
- EC2 instance public DNS

For S3 origins, check if the bucket allows public access independently of the distribution. For ALB origins, the security group may restrict access to CloudFront IPs or allow any source. Test direct access to the ALB to determine if CloudFront is the only path. Bypassing CloudFront reaches the origin without WAF rules or geo-restrictions.

### Origin Access Control / Identity

OAC is the newer mechanism replacing OAI. Both restrict S3 bucket access to the CloudFront service principal. If neither is configured, the S3 bucket must rely on its own bucket policy to prevent direct access. Check if S3 origins are protected by an OAC or OAI (restricts direct S3 access):

```bash
aws cloudfront get-distribution --id $DISTRIBUTION_ID --profile $PROFILE | jq '.Distribution.DistributionConfig.Origins.Items[] | {Domain:.DomainName, OAC:.OriginAccessControlId, OAI:.S3OriginConfig.OriginAccessIdentity}'
```

If `OriginAccessIdentity` is empty and the S3 bucket has no separate restriction, the bucket may be accessible directly. Verify by requesting the S3 website endpoint or the bucket URL directly. Use the bucket name from the origin domain to check public access block settings with `aws s3api get-public-access-block`. An accessible bucket lets you list or read objects without going through the distribution.

### Cache Policies and Functions

Cache policies control which headers, query strings, and cookies are forwarded to the origin. A policy that forwards auth headers means tokens reach the origin and form part of the cache key. Functions attached to behaviors run JavaScript at the edge for request and response manipulation.

```bash
aws cloudfront list-cache-policies --profile $PROFILE
aws cloudfront list-functions --profile $PROFILE
aws cloudfront get-function --name $FUNCTION_NAME --profile $PROFILE
```

CloudFront Functions run at the edge and may contain business logic, auth checks, or token validation: worth reviewing for bypasses. The `get-function` command returns the function source code. Read it for hardcoded secrets, weak token validation, or header manipulation that alters downstream auth decisions. Functions that rewrite URLs may expose path-based controls that protect specific routes.
