Information disclosure due to unsigned DNS responses in Route 53 public hosted zones

High Risk infrastructure-security
awsroute53dnssecdns-securityinformation-disclosuredns-spoofingtraffic-hijacking

What it is

AWS Route 53 public hosted zones without DNSSEC enabled are vulnerable to DNS spoofing, cache poisoning, and man-in-the-middle attacks. Without cryptographic signatures on DNS responses, attackers can forge DNS records to redirect traffic to malicious servers, enabling credential theft, data interception, and service impersonation attacks.

# VULNERABLE: Route 53 without DNSSEC
resource "aws_route53_zone" "company" {
  name = "company.com"
  
  # VULNERABLE: No DNSSEC configuration
  # No key-signing key
  # DNS responses are unsigned
  
  tags = {
    Environment = "production"
  }
}

resource "aws_route53_record" "www" {
  zone_id = aws_route53_zone.company.zone_id
  name    = "www.company.com"
  type    = "A"
  ttl     = 300
  records = ["203.0.113.1"]
  
  # VULNERABLE: Can be spoofed via DNS cache poisoning
}

resource "aws_route53_record" "api" {
  zone_id = aws_route53_zone.company.zone_id
  name    = "api.company.com"
  type    = "A"
  ttl     = 300
  records = ["203.0.113.2"]
  
  # VULNERABLE: API endpoint can be hijacked
}
# SECURE: Route 53 with DNSSEC enabled

# SECURE: KMS key for DNSSEC signing
resource "aws_kms_key" "dnssec" {
  customer_master_key_spec = "ECC_NIST_P256"
  key_usage                = "SIGN_VERIFY"
  
  policy = jsonencode({
    Statement = [{
      Effect = "Allow"
      Principal = { Service = "dnssec-route53.amazonaws.com" }
      Action = ["kms:Sign", "kms:GetPublicKey"]
      Resource = "*"
    }]
  })
}

resource "aws_route53_zone" "company" {
  name = "company.com"
}

# SECURE: Key-signing key for DNSSEC
resource "aws_route53_key_signing_key" "ksk" {
  hosted_zone_id             = aws_route53_zone.company.id
  key_management_service_arn = aws_kms_key.dnssec.arn
  name                       = "company-ksk"
}

# SECURE: Enable DNSSEC signing
resource "aws_route53_hosted_zone_dnssec" "company" {
  depends_on     = [aws_route53_key_signing_key.ksk]
  hosted_zone_id = aws_route53_zone.company.id
  signing_status = "SIGNING"
}

💡 Why This Fix Works

The vulnerable configuration creates a Route 53 hosted zone without DNSSEC protection, leaving DNS responses unsigned and vulnerable to spoofing and cache poisoning attacks. The secure version creates a customer-managed KMS key with ECC_NIST_P256 specification for cryptographic signing, creates a key-signing key (KSK) linked to the KMS key, and enables DNSSEC signing on the hosted zone. This ensures all DNS responses are cryptographically signed and can be validated by resolvers, preventing attackers from injecting false DNS records or redirecting traffic to malicious servers.

Why it happens

Route 53 public hosted zones created without DNSSEC signing enabled. DNS responses from unsigned zones lack cryptographic signatures, allowing attackers to forge responses and redirect traffic to malicious servers without detection.

Root causes

Unsigned Hosted Zones

Route 53 public hosted zones created without DNSSEC signing enabled. DNS responses from unsigned zones lack cryptographic signatures, allowing attackers to forge responses and redirect traffic to malicious servers without detection.

Missing KMS Key Configuration

No customer-managed KMS key configured with ECC_NIST_P256 specification for DNS signing. DNSSEC requires asymmetric keys for signing operations, and zones cannot be signed without proper KMS key infrastructure.

No Key-Signing Key Created

Hosted zones lack aws_route53_key_signing_key (KSK) resources. The KSK is required to sign zone-signing keys and establish the DNSSEC chain of trust, without which DNS responses remain vulnerable to spoofing.

DNSSEC Signing Not Enabled

The aws_route53_hosted_zone_dnssec resource is not configured or signing_status is not set to 'SIGNING'. Without actively enabling DNSSEC, zones remain unsigned even if key infrastructure exists.

Incomplete Chain of Trust

DS (Delegation Signer) records are not published at the domain registrar to complete the DNSSEC chain of trust. Without DS records in the parent zone, resolvers cannot validate signatures, rendering DNSSEC ineffective.

Fixes

1

Create DNSSEC KMS Key

Create an AWS KMS key with customer_master_key_spec = 'ECC_NIST_P256' and key_usage = 'SIGN_VERIFY'. Configure the key policy to allow the dnssec-route53.amazonaws.com service principal to perform signing operations.

2

Configure Key-Signing Key

Create an aws_route53_key_signing_key resource for your hosted zone, referencing the KMS key ARN. The KSK establishes the root of trust for DNSSEC by signing the zone-signing keys (ZSK) that sign your DNS records.

3

Enable DNSSEC Signing

Deploy aws_route53_hosted_zone_dnssec resource with signing_status = 'SIGNING' for your hosted zone. Ensure proper depends_on relationships so the KSK is created before DNSSEC signing is enabled.

4

Publish DS Records at Registrar

Retrieve the DS records from Route 53 and publish them at your domain registrar to complete the DNSSEC chain of trust. This links your zone's signatures to the parent zone, enabling resolver validation of your DNS responses.

5

Monitor DNSSEC Status

Set up CloudWatch monitoring for DNSSEC validation metrics including DNSSECInternalFailure and DNSSECKeySigningKeysNeedingAction. Configure alarms to alert on signing failures, key rotation requirements, or validation issues.

Detect This Vulnerability in Your Code

Sourcery automatically identifies information disclosure due to unsigned dns responses in route 53 public hosted zones and many other security issues in your codebase.