Route 53 Profiles package private hosted zones, Resolver rules, DNS Firewall rule groups, query logging configurations, interface VPC endpoints, and selected DNS settings into one regional object. A Profile owner can share that object through AWS Resource Access Manager (AWS RAM). The default read-only share still lets a consumer associate the Profile with VPCs, making every DNS resource in the Profile effective there.[1][2]
This creates a cross-account DNS control path. An attacker prepares a private hosted zone and Profile in one account, shares the Profile to a target account, then uses a target principal to attach it to a VPC. The hosted zone remains owned and managed in the source account.
A single target-account AssociateProfile call can make an attacker-owned DNS namespace effective across a VPC while its hosted zone remains absent from ListHostedZonesByVPC.
The result is DNS shadowing rather than universal DNS takeover. Zone specificity, directly associated VPC resources, and Resolver rules determine which answer wins.
How the technique works
flowchart TB
S([Source-account principal])
H[Attacker-owned private hosted zone]
P[Route 53 Profile]
R[AWS RAM resource share]
T([Target-account principal])
V[Target VPC]
Q[Workload DNS query]
A[Shadowed answer or NXDOMAIN]
S -->|CreateHostedZone + ChangeResourceRecordSets| H
S -->|CreateProfile| P
H -->|AssociateResourceToProfile| P
P -->|CreateResourceShare| R
R -->|shared Profile| T
T -->|AssociateProfile| V
Q -->|AmazonProvidedDNS| V
V -->|Profile private hosted zone| A
class S,T principal
class H,P,R,V awsResource
A private hosted zone associated through a Profile participates in Route 53 Resolver evaluation for each associated VPC. The public namespace is unchanged. Workloads using the VPC resolver see the private answer while resolvers outside those VPCs continue to see public DNS.
Resolution priority
Route 53 applies the most specific matching domain. A Profile zone for packages.corp.example therefore takes priority over a directly associated zone for corp.example. When the Profile and a directly associated VPC resource use the same domain, the direct VPC configuration takes priority. A Resolver forwarding rule also takes priority over a private hosted zone when both match the same domain.[3][4]
| VPC DNS state | Query | Result |
|---|---|---|
| No matching direct private zone or Resolver rule | packages.corp.example |
The matching Profile private zone answers. |
Direct zone corp.example, Profile zone packages.corp.example |
packages.corp.example |
The more-specific Profile zone answers. |
Direct zone and Profile zone both named packages.corp.example |
packages.corp.example |
The directly associated zone answers. |
| Profile zone matches, but the requested name or record type is absent | Any matching name | Route 53 returns NXDOMAIN instead of falling back to public DNS. |
| Resolver forwarding rule and Profile zone use the same domain | Any matching name | The forwarding rule takes priority. |
The last behavior also provides a denial primitive. An otherwise empty private zone can suppress public answers for its namespace because Route 53 does not forward a failed private-zone lookup to public DNS.[4:1]
DNS redirection alone does not defeat TLS, mutual TLS, certificate pinning, or application-layer authentication. Its interception value depends on the client protocol and trust model. It can still redirect plaintext protocols, redirect clients that trust a certificate available to the attacker, alter endpoints whose trust depends on DNS, or deny resolution outright.
Preconditions
The source-account principal needs control of the DNS resources and the Profile share. The relevant permissions are:
route53:CreateHostedZone,route53:ChangeResourceRecordSets, andec2:DescribeVpcsfor the private hosted zone.route53profiles:CreateProfileandroute53profiles:AssociateResourceToProfilefor the Profile.ram:CreateResourceShareplus the RAM association actions used by the chosen sharing workflow.route53profiles:GetProfilePolicyandroute53profiles:PutProfilePolicy, which Route 53 requires when sharing a Profile through AWS RAM.[5][2:1]
The target-account principal needs route53profiles:AssociateProfile for the target VPC. For a share from outside an AWS Organization, a target principal must also accept the AWS RAM invitation with ram:AcceptResourceShareInvitation. When organization sharing is enabled and the Profile is shared within that organization, AWS RAM grants access automatically and no invitation acceptance is required.[2:2][6]
The Profile and target VPC must be in the same Region. A VPC can have only one Profile, while one Profile can be associated with up to 1,000 VPCs by default. Private hosted zone resolution also requires both enableDnsSupport and enableDnsHostnames on the VPC.[1:1][7][4:2]
Execution
The source account first creates a private hosted zone. Route 53 requires an initial VPC association at zone creation, so this example uses a source-account VPC in us-east-1:[8]
aws route53 create-hosted-zone \
--name packages.corp.example \
--caller-reference profile-graft-20260901T120000Z \
--vpc VPCRegion=us-east-1,VPCId=vpc-0a111111111111111
Assume the returned hosted zone ID is Z0123456789EXAMPLE. Add the answer that target workloads should receive:
aws route53 change-resource-record-sets \
--hosted-zone-id Z0123456789EXAMPLE \
--change-batch '{
"Changes": [{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "packages.corp.example",
"Type": "A",
"TTL": 60,
"ResourceRecords": [{"Value": "198.51.100.40"}]
}
}]
}'
Create a Profile in the Region of the target VPC:
aws route53profiles create-profile \
--name shared-network-baseline \
--region us-east-1
Assume the response returns Profile ID rp-0abc123def456example. Associate the private hosted zone with it. Route 53 hosted zone ARNs omit both Region and account ID:[9]
aws route53profiles associate-resource-to-profile \
--name corp-package-resolution \
--profile-id rp-0abc123def456example \
--resource-arn arn:aws:route53:::hostedzone/Z0123456789EXAMPLE \
--region us-east-1
Share the Profile from source account 111122223333 to target account 444455556666:
aws ram create-resource-share \
--name shared-network-baseline \
--resource-arns arn:aws:route53profiles:us-east-1:111122223333:profile/rp-0abc123def456example \
--principals 444455556666 \
--region us-east-1
When permission-arns is omitted, AWS RAM attaches the default permission for the resource type. For Route 53 Profiles, AWSRAMPermissionRoute53ProfileAllowAssociation gives the consumer read access to Profile resources and permits VPC association, but not modification of the Profile’s resource associations.[10][2:3]
For a share that produces an invitation, the target principal accepts it:
aws ram accept-resource-share-invitation \
--resource-share-invitation-arn arn:aws:ram:us-east-1:111122223333:resource-share-invitation/01234567-89ab-cdef-0123-456789abcdef \
--region us-east-1
The target principal can then attach the shared Profile to VPC vpc-0b222222222222222:
aws route53profiles associate-profile \
--name shared-network-baseline \
--profile-id rp-0abc123def456example \
--resource-id vpc-0b222222222222222 \
--region us-east-1
AssociateProfile initially returns an association with status CREATING. Once its status becomes COMPLETE, every resource and setting in the shared Profile applies to the target VPC. In this example, queries for packages.corp.example resolve to the private A record when no higher-priority direct configuration or Resolver rule matches.[11]
The source owner retains control of the hosted zone and its records. Later ChangeResourceRecordSets calls alter the answer presented through every VPC association without another API call in the target account.
Detection
The primary target-account signal is route53profiles.amazonaws.com AssociateProfile. It directly connects a principal, Profile ID, and VPC ID. The Profile ID does not contain an account ID, so detection should enrich the event with GetProfile or ListProfiles and compare the returned OwnerId with the target account.[12][13]
A focused CloudTrail record contains the fields needed to identify the graft point:
{
"eventTime": "2026-09-01T12:12:00Z",
"eventSource": "route53profiles.amazonaws.com",
"eventName": "AssociateProfile",
"awsRegion": "us-east-1",
"recipientAccountId": "444455556666",
"userIdentity": {
"type": "AssumedRole",
"arn": "arn:aws:sts::444455556666:assumed-role/NetworkAutomation/session"
},
"sourceIPAddress": "198.51.100.24",
"requestParameters": {
"name": "shared-network-baseline",
"profileId": "rp-0abc123def456example",
"resourceId": "vpc-0b222222222222222"
}
}
Detection inputs
| Event | Decision-useful fields | Why it matters |
|---|---|---|
route53.amazonaws.com CreateHostedZone |
requestParameters.name, requestParameters.vPC.vPCId, responseElements.hostedZone.id |
Creates the private namespace later placed in the Profile. This event can exist only in the source account. |
route53.amazonaws.com ChangeResourceRecordSets |
requestParameters.hostedZoneId, changed names, types, actions, and values |
Captures creation or later replacement of shadow answers. |
route53profiles.amazonaws.com CreateProfile |
requestParameters.name, responseElements.profile.id, responseElements.profile.ownerId |
Establishes the source Profile and its owner. |
route53profiles.amazonaws.com AssociateResourceToProfile |
requestParameters.profileId, resourceArn, name |
Links the private hosted zone ARN to the Profile. |
ram.amazonaws.com CreateResourceShare |
requestParameters.resourceArns, principals, permissionArns, allowExternalPrincipals |
Shows the Profile leaving its owner account or being shared to an organization scope. |
ram.amazonaws.com AcceptResourceShareInvitation |
requestParameters.resourceShareInvitationArn, responseElements.resourceShareInvitation.senderAccountId, receiverAccountId |
Identifies explicit target-side acceptance and the source account. It is absent for automatic organization sharing. |
route53profiles.amazonaws.com AssociateProfile |
requestParameters.profileId, resourceId, name, userIdentity.arn |
Makes all Profile DNS resources effective on the target VPC. |
Retain eventTime, recipientAccountId, awsRegion, userIdentity.arn, sourceIPAddress, userAgent, and errorCode across each event. Route 53 Profiles and AWS RAM use the CloudTrail event sources route53profiles.amazonaws.com and ram.amazonaws.com, respectively.[12:1][14]
Correlation logic
- Select successful
AssociateProfileevents in each target account and Region. - Resolve the Profile with
GetProfile. Raise confidence whenOwnerIddiffers fromrecipientAccountId,ShareStatusisSHARED_WITH_ME, or the owner is outside the approved DNS account set. - Join explicit external shares to
AcceptResourceShareInvitationusing the share invitation and sender account. Do not require this event for organization shares. - Enumerate the Profile’s resources with
ListProfileResourceAssociations. Raise severity when it contains a private hosted zone whose domain overlaps a production namespace or a public dependency used by the VPC. - Where source-account telemetry is available, correlate
CreateProfile,AssociateResourceToProfile, andCreateResourceSharebefore the targetAssociateProfile. Continue to monitorChangeResourceRecordSetsfor the associated zone because record changes alter the target answer without another target-account event. - Use Resolver query logs to find a new private answer, a sudden answer-address change, or increased
NXDOMAINresponses for the affected namespace.[15]
The classic Route 53 inventory path is insufficient. AWS explicitly states that ListHostedZonesByVPC does not report hosted zone associations made through Route 53 Profiles.[16]
Inventory each VPC through the Profiles API instead:
aws route53profiles list-profile-associations \
--resource-id vpc-0b222222222222222 \
--region us-east-1
aws route53profiles get-profile \
--profile-id rp-0abc123def456example \
--region us-east-1
aws route53profiles list-profile-resource-associations \
--profile-id rp-0abc123def456example \
--region us-east-1
ListProfileAssociations maps Profiles to VPCs. ListProfileResourceAssociations then exposes each private hosted zone and other DNS resource carried by a Profile.[17][18]
Tune against approved Profile owner accounts, target VPCs, DNS automation roles, and expected namespaces. Profile names are operator-controlled labels and should not be used as the trust decision.
Hardening
| Control | Implementation | Why it helps |
|---|---|---|
| Profile association permissions | Limit route53profiles:AssociateProfile and route53profiles:DisassociateProfile to dedicated DNS automation roles. Use the route53profiles:ResourceIds condition key to constrain eligible VPCs. |
Removes the target-side write primitive from general deployment identities. |
| RAM share governance | Restrict ram:AcceptResourceShareInvitation and review organization-wide or OU-wide Profile shares. Maintain an allowlist of Profile owner accounts. |
Prevents untrusted source accounts from becoming accepted DNS configuration owners. |
| Complete DNS inventory | Add ListProfiles, GetProfile, ListProfileAssociations, and ListProfileResourceAssociations to every VPC DNS inventory workflow. Record OwnerId, ShareStatus, resource ARNs, and hosted zone domains. |
Closes the visibility gap left by ListHostedZonesByVPC. |
| Change monitoring | Alert on target-account AssociateProfile and source-account changes to every private hosted zone carried by an approved shared Profile. |
Detects both the initial graft and later answer changes that produce no target-account mutation event. |
| Resolver query logging | Enable query logging through a target-controlled configuration and retain query name, response code, and answer data.[15:1] | Exposes changed answers and private-zone NXDOMAIN suppression at resolution time. |
| Application trust | Require authenticated TLS, mutual TLS, certificate pinning where appropriate, or signed application artifacts for sensitive internal workflows. | Keeps DNS redirection from becoming endpoint impersonation or trusted content substitution. |
References
Amazon Route 53 Developer Guide, What are Amazon Route 53 Profiles?. ↩︎ ↩︎
Amazon Route 53 Developer Guide, Sharing Route 53 Profiles. ↩︎ ↩︎ ↩︎ ↩︎
Amazon Route 53 Developer Guide, How Route 53 Profile settings are prioritized. ↩︎
Amazon Route 53 Developer Guide, Considerations when working with a private hosted zone. ↩︎ ↩︎ ↩︎
AWS Service Authorization Reference, Actions, resources, and condition keys for Amazon Route 53 Profiles. ↩︎
AWS RAM API Reference, AcceptResourceShareInvitation. ↩︎
Amazon Route 53 Developer Guide, Quotas on Route 53 Profiles. ↩︎
AWS CLI Command Reference, create-hosted-zone. ↩︎
Amazon Route 53 API Reference, AssociateResourceToProfile. ↩︎
AWS RAM API Reference, CreateResourceShare. ↩︎
Amazon Route 53 API Reference, AssociateProfile. ↩︎
Amazon EventBridge Reference, Amazon Route 53 Profiles events. ↩︎ ↩︎
Amazon Route 53 API Reference, GetProfile. ↩︎
Amazon EventBridge Reference, AWS Resource Access Manager events. ↩︎
Amazon Route 53 Developer Guide, Resolver query log values. ↩︎ ↩︎
Amazon Route 53 API Reference, ListHostedZonesByVPC. ↩︎
Amazon Route 53 API Reference, ListProfileAssociations. ↩︎
Amazon Route 53 API Reference, ListProfileResourceAssociations. ↩︎