Use the Conformity Knowledge Base AI to help improve your Cloud Posture

Sender Policy Framework In Use

Trend Cloud One™ – Conformity is a continuous assurance tool that provides peace of mind for your cloud infrastructure, delivering over 1000 automated best practice checks.

Risk Level: Medium (should be achieved)
Rule ID: Route53-008

Ensure that your Amazon Route 53 hosted zone has a TXT record that implements the Sender Policy Framework (SPF) for the corresponding MX record available within the DNS zone. The Sender Policy Framework enables your registered domains to publicly state which mail servers are authorized to send emails on their behalf.

This rule can help you with the following compliance standards:

  • NIST4

For further details on compliance standards supported by Conformity, see here.

This rule resolution is part of the Conformity Security & Compliance tool for AWS.

Security

Implementing Sender Policy Framework (SPF) for your Amazon Route 53 domain names will help you detect and stop email address spoofing in order to reduce spam and increase your domains trustworthiness.

Note: This conformity rule assumes that your Amazon Route 53 hosted zones are using MX records for declaring the server(s) that should handle email delivery.


Audit

To determine if your Amazon Route 53 hosted zone contain a TXT DNS record with SPF information for the corresponding MX record, perform the following actions:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon Route 53 console at https://console.aws.amazon.com/route53/.

03 In the main navigation panel, under Dashboard, click Hosted zones.

04 Click on the domain name of the Route 53 hosted zone that you want to examine.

05 In the Records section, select TXT from the Type dropdown menu to return all the TXT DNS records created for the selected hosted zone (domain). If this filtering process does not return any TXT records, the selected Amazon Route 53 domain does not use TXT DNS records to implement the Sender Policy Framework (SPF) for the corresponding MX records. If the filtering process returns one or more TXT records, check each record value listed in Value/Route traffic to column. If the record value does not contain v=spf1 (e.g. "v=spf1 ip4:192.168.0.5/16 -all"), the selected domain is not using the Sender Policy Framework (SPF) for the corresponding MX records.

06 Repeat steps no. 4 and 5 for each DNS hosted zone created with Amazon Route 53 service.

Using AWS CLI

01 Run list-hosted-zones command (OSX/Linux/UNIX) to list the ID of each Amazon Route 53 hosted zone created in your AWS cloud account:

aws route53 list-hosted-zones
  --query "HostedZones[*].Id"

02 The command output should return an array with the requested hosted zone IDs:

[
	"/hostedzone/ABCD1234ABCD1234ABCD",
	"/hostedzone/ABCDABCDABCDABCDABCD"
]

03 Run list-resource-record-sets command (OSX/Linux/UNIX) using the ID of the Route 53 hosted zone that you want to examine as the identifier parameter and custom query filters to list the TXT DNS records created for the selected hosted zone (domain):

aws route53 list-resource-record-sets
  --hosted-zone-id "/hostedzone/ABCD1234ABCD1234ABCD"
  --query "ResourceRecordSets[?Type == 'TXT']"

04 The command output should return an array with all the TXT DNS record sets created for the specified Amazon Route 53 hosted zone:

05 If the array returned as output is empty, i.e. [], the selected domain name does not use TXT DNS records to implement Sender Policy Framework (SPF) for the corresponding MX records:

[]

06 If the command output returns an array with one or more TXT DNS records, as shown in the example below, check the value configured for the "Value"property (highlighted). If this value does not contain v=spf1 (for example, "v=spf1 ip4:192.168.0.5/16 -all"), the selected domain name is not using the Sender Policy Framework (SPF) for the corresponding MX records, therefore the Route 53 domain is not SPF-protected:

[
	{
		"ResourceRecords": [
			{
				"Value": "\"google-site-verification=1234-abcd-1234-abcd\""
			}
		],
		"Type": "TXT",
		"Name": "cloudconformity.com.",
		"TTL": 300
	}
]

07 Repeat steps no. 3 and 4 for each DNS hosted zone created with Amazon Route 53 service within your AWS account.

Remediation / Resolution

To implement Sender Policy Framework (SPF) for all the corresponding MX records within your hosted zones using Amazon Route 53 TXT DNS records, perform the following operations:

Using AWS CloudFormation

01 CloudFormation template (JSON):

{
	"AWSTemplateFormatVersion": "2010-09-09",
	"Resources": {
		"EC2Instance": {
			"Type": "AWS::EC2::Instance",
			"Properties": {
				"ImageId": "ami-0123456789abcdef0",
				"InstanceType": "c5.xlarge",
				"KeyName": "cc-ssh-key",
				"SubnetId": "subnet-0123456789abcdefa",
				"SecurityGroupIds": "sg-0123456789abcdef1"
			}
		},
		"Route53HostedZone": {
			"Type": "AWS: : Route53: : HostedZone",
			"Properties": {
				"HostedZoneConfig": {
					"Comment": "Route53 public hosted zone for domain.com"
				},
				"Name": "domain.com",
				"HostedZoneTags": [
					{
						"Key": "Owner",
						"Value": "IT"
					}
				]
			}
		},
		"ARecord": {
			"Type": "AWS::Route53::RecordSet",
			"Properties": {
				"HostedZoneName": {
					"Ref": "Route53HostedZone"
				},
				"Name": "www.domain.com",
				"Type": "A",
				"TTL": "300",
				"ResourceRecords": [
					{
						"Fn::GetAtt": [
							"EC2Instance",
							"PublicIp"
						]
					}
				]
			}
		},
		"SPFRecord": {
			"Type": "AWS::Route53::RecordSet",
			"Properties": {
				"HostedZoneName": {
					"Ref": "Route53HostedZone"
				},
				"Name": "www.domain.com",
				"Type": "TXT",
				"TTL": "3600",
				"ResourceRecords": [
					"v=spf1 include:_spf.google.com ~all"
				]
			}
		}
	}
}

02 CloudFormation template (YAML):

AWSTemplateFormatVersion: '2010-09-09'
	Resources:
	EC2Instance:
		Type: AWS::EC2::Instance
		Properties:
		ImageId: ami-0123456789abcdef0
		InstanceType: c5.xlarge
		KeyName: cc-ssh-key
		SubnetId: subnet-0123456789abcdefa
		SecurityGroupIds: sg-0123456789abcdef1
	Route53HostedZone:
		Type: 'AWS: : Route53: : HostedZone'
		Properties:
		HostedZoneConfig:
			Comment: Route53 public hosted zone for domain.com
		Name: domain.com
		HostedZoneTags:
			- Key: Owner
			Value: IT
	ARecord:
		Type: AWS::Route53::RecordSet
		Properties:
		HostedZoneName: !Ref 'Route53HostedZone'
		Name: www.domain.com
		Type: A
		TTL: '3600'
		ResourceRecords:
			- !GetAtt 'EC2Instance.PublicIp'
	SPFRecord:
		Type: AWS::Route53::RecordSet
		Properties:
		HostedZoneName: !Ref 'Route53HostedZone'
		Name: www.domain.com
		Type: TXT
		TTL: '3600'
		ResourceRecords:
			- v=spf1 include:_spf.google.com ~all

Using Terraform (AWS Provider)

01 Terraform configuration file (.tf):

terraform {
	required_providers {
		aws = {
			source  = "hashicorp/aws"
			version = "~> 4.0"
		}
	}

	required_version = ">= 0.14.9"
}

provider "aws" {
	profile = "default"
	region  = "us-east-1"
}

resource "aws_instance" "ec2-instance" {
	ami                    = "ami-0123456789abcdef0"
	instance_type          = "c5.xlarge"
	key_name               = "cc-ssh-key"
	subnet_id              = "subnet-0123456789abcdefa"
	vpc_security_group_ids = ["sg-0123456789abcdef1"]
}

resource "aws_eip" "elastic-ip" {
	instance = aws_instance.ec2-instance.id
	domain   = "vpc"
}

resource "aws_route53_zone" "route53-hosted-zone" {
	name    = "domain.com"
	comment = "Route53 public hosted zone for domain.com"
	tags    = {
		Owner = "IT"
	}
}

resource "aws_route53_record" "a-record" {
	zone_id = aws_route53_zone.route53-hosted-zone.zone_id
	name    = "www.domain.com"
	type    = "A"
	ttl     = "300"
	records = [aws_eip.elastic-ip.public_ip]
}

resource "aws_route53_record" "spf-record" {
	zone_id = aws_route53_zone.route53-hosted-zone.zone_id
	name    = "www.domain.com"
	type    = "TXT"
	ttl     = "3600"
	records = [
		"v=spf1 include:_spf.google.com ~all"
	]
}

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon Route 53 console at https://console.aws.amazon.com/route53/.

03 In the main navigation panel, under Dashboard, click Hosted zones.

04 Click on the domain name of the hosted zone that you want to reconfigure.

05 In the Records section, choose Create recordto initiate the TXT DNS record setup process, then perform the following actions:

  1. For Record name, leave the field blank to route traffic for the name of the domain.
  2. For Record type, select TXT – Used to verify email senders and for application-specific values.
  3. For Value, enter the required SPF value, for example "v=spf1 include:_spf.google.com ~all". If you don't use Google mail servers, replace include:_spf.google.com with your mail server hostame/IPv4 address, e.g. "v=spf1 ip4:192.168.0.5/16 -all".
  4. For TTL (seconds), enter a value of 3600 as Time to Live (TTL) value (i.e. the amount of time, in seconds, that you want DNS recursive resolvers to cache information about this record).
  5. For Routing policy dropdown list, choose Simple routing. The routing policy lets you choose how Amazon Route 53 routes traffic to your resources.
  6. Choose Create records to create a new TXT DNS record that implements the Sender Policy Framework (SPF) for the corresponding MX record.

06 Repeat steps no. 4 and 5 to implement the Sender Policy Framework (SPF) for each Amazon Route 53 domain name with corresponding MX records.

Using AWS CLI

01 To define the required SPF TXT-based record set and add it to your DNS hosted zone, you must create an Amazon Route 53 change file, declare the new DNS record set, and save the record definition to a JSON file named spf-txt-record-set.json. The following example describes a TXT record definition that implements the Sender Policy Framework (SPF) for a domain name called cloudconformity.com, using Google mail servers as servers that are allowed to send mail for the specified domain:

{
	"Comment": "SPF TXT-based record set for cloudconformity.com domain",
	"Changes": [
		{
			"Action": "CREATE",
			"ResourceRecordSet": {
				"Name": "cloudconformity.com.",
				"Type": "TXT",
				"TTL": 3600,
				"ResourceRecords": [
					{
						"Value": "\"v=spf1 include:_spf.google.com ~all\""
					}
				]
			}
		}
	]
}

02 Run change-resource-record-sets command (OSX/Linux/UNIX) using the ID of the DNS hosted zone that you want to reconfigure as the identifier parameter and the Amazon Route 53 change file defined at the previous step (i.e. spf-txt-record-set.json) to add the new TXT DNS record that implement the Sender Policy Framework (SPF) to the selected hosted zone:

aws route53 change-resource-record-sets
  --hosted-zone-id "/hostedzone/ABCD1234ABCD1234ABCD"
  --change-batch file://spf-txt-record-set.json

03 The command output should return the metadata for the new DNS record set (including the ID of the change file used – highlighted):

{
	"ChangeInfo": {
		"Status": "PENDING",
		"Comment": "SPF TXT-based record set for cloudconformity.com domain",
		"SubmittedAt": "2020-08-11T15:00:00.000Z",
		"Id": "/change/ABCDABCDABCDABCDABCD"
	}
}

04 Run get-change command (OSX/Linux/UNIX) using the ID of the Route 53 change file returned at the previous step as the identifier parameter, to describe the status of the newly created record set:

aws route53 get-change
  --id "/change/ABCDABCDABCDABCDABCD"

05 The command output should return the current status of the DNS record batch request. The current status should be INSYNC, which indicates that the change was fully propagated to all Amazon Route 53 DNS server nodes:

{
	"ChangeInfo": {
		"Status": "INSYNC",
		"Comment": "SPF TXT-based record set for cloudconformity.com domain",
		"SubmittedAt": "2021-08-12T15:00:00.000Z",
		"Id": "/change/ABCDABCDABCDABCDABCD"
	}
}

06 Repeat steps no. 1 – 5 to implement the Sender Policy Framework (SPF) for each Amazon Route 53 domain name with corresponding MX records.

References

Publication date Aug 17, 2020