Email Header Forgery & DKIM

SPF only validated envelope senders; attackers spoofed the From header users actually see. DKIM adds cryptographic signatures to prove header authenticity.

MITRE ATT&CK: T1566.001

Timeline: The Cat and Mouse

2004 ← Attack emerges → 2007 ← Industry responds → 2012 ← Attackers adapt → Present

The Evolution

Phase Period What Happened
ATTACK 2004 SPF deployed but header spoofing trivial; users deceived by From: header
  2006 Attackers exploit envelope/header mismatch at scale
RESPONSE 2004 Yahoo releases DomainKeys
  2007 DKIM standardized (RFC 4871) - merges DomainKeys + Cisco IIM
  2011 DKIM updated (RFC 6376) with improved crypto requirements
ADOPTION 2012+ Gmail, Outlook, Yahoo sign all outbound mail by default
LIMITATION Present DKIM widely deployed but requires DMARC for enforcement

Key Events with Sources

Date Event Significance Source
2004 Yahoo releases DomainKeys First email signing system; precursor to DKIM DomainKeys
2005 Cisco proposes IIM Identified Internet Mail - competing signing proposal IETF Archive
2007 DKIM RFC 4871 published Unified standard combining DomainKeys + IIM RFC 4871
2011 DKIM RFC 6376 published Updated spec with refined crypto requirements RFC 6376
2012+ Major provider adoption Gmail, Outlook sign all outbound mail DKIM.org

Overview

SPF solved envelope spoofing, but users don’t see the envelope address. They see the From: header in their email client. Attackers adapted by sending email with a legitimate envelope (passing SPF) but a spoofed header (fooling users). DKIM adds cryptographic signatures to prove that specific headers haven’t been tampered with.

The Attack

The SPF Gap

After SPF deployment, attackers discovered they could pass SPF while still spoofing the visible sender:

MAIL FROM: <bounce@attacker.com>          ← SPF checks this domain
                                            (attacker controls, SPF passes)

From: CEO <ceo@bigbank.com>               ← User sees this (spoofed)
Reply-To: ceo-urgent@attacker.com         ← Replies go here
Subject: Urgent Wire Transfer

The email passes SPF because attacker.com has valid SPF records authorizing their server. But the user sees ceo@bigbank.com and thinks it’s legitimate.

Header Manipulation Attacks

Beyond simple spoofing, attackers modified headers in transit:

Reply-To Hijacking:

From: ceo@company.com
Reply-To: ceo.urgent@gmail.com            ← Attacker's address

Please send the financial report to this email...

Subject Line Manipulation: Compromised mail relays could modify subject lines to add urgency or remove security warnings.

Display Name Tricks:

From: "IT Security Team" <random@attacker.com>
From: "ceo@company.com" <hacker@evil.com>

Users often only see display names in mobile clients, not the actual address.

Why SPF Wasn’t Enough

What SPF Validates What SPF Ignores
Envelope MAIL FROM From: header
Sending server IP Reply-To: header
  Subject, body content
  Any header modification in transit

How DKIM Works

The Defense Mechanism

DKIM uses public key cryptography to sign email headers and body:

  1. Sender publishes public key in DNS as a TXT record
  2. Sending server signs selected headers + body hash with private key
  3. Signature added to email as DKIM-Signature header
  4. Receiving server retrieves public key from DNS
  5. Receiving server verifies signature matches

DKIM Signature Anatomy

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=example.com; s=selector1;
        h=from:to:subject:date:message-id;
        bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;
        b=AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yAUoq
          BMVR8Qh3mDUbjzRzfTBxXpZvC1KcQDPR...
Field Meaning
v=1 DKIM version 1
a=rsa-sha256 Signing algorithm
c=relaxed/relaxed Canonicalization (how to normalize before signing)
d=example.com Signing domain
s=selector1 DNS selector (allows key rotation)
h=from:to:subject:... Headers that are signed
bh=... Body hash
b=... The actual signature

DNS Public Key Record

The receiving server queries selector1._domainkey.example.com:

v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNAD...

What DKIM Protects

When a server signs with d=example.com and includes h=from:to:subject:

  • The From: header cannot be modified without breaking the signature
  • If someone changes the subject, verification fails
  • The body content is protected by the body hash

Attacker Adaptation

DKIM Limitations

1. DKIM Doesn’t Mandate Rejection

A failed DKIM signature doesn’t mean the email gets rejected. Without DMARC:

  • Missing signature? Accepted.
  • Failed signature? Often accepted anyway.
  • No policy tells receivers what to do.

2. Replay Attacks

A legitimately signed email can be resent:

1. Attacker receives legitimate newsletter from bigbank.com
2. Newsletter has valid DKIM signature
3. Attacker forwards to new victims
4. Signature still validates (it's the original message)

The email is authentic—it just wasn’t meant for these recipients.

3. Partial Signing

If a domain only signs some headers, attackers can add unsigned headers:

Original signed headers: From, To, Subject
Attacker adds: Reply-To (unsigned, not validated)

4. Key Management Issues

  • Weak keys (512-bit RSA still seen in the wild)
  • Keys that never rotate
  • Private keys exposed in breaches
  • Selectors that don’t exist (misconfiguration)

5. No Alignment Requirement

DKIM alone doesn’t require the signing domain to match the From header:

From: ceo@bigbank.com
DKIM-Signature: d=attacker.com; ...    ← Valid signature, wrong domain

This is technically a valid DKIM pass, even though it’s not bigbank.com signing.

DKIM proves “this message was signed by d=example.com” but doesn’t answer:

  • Should I reject unsigned messages claiming to be from example.com?
  • Should the signing domain match the From header?
  • What should I do on failure?

These questions are answered by DMARC.

Current State

Status: Limited (requires DMARC for enforcement)

DKIM is essential infrastructure but provides little protection without DMARC:

Scenario DKIM Alone DKIM + DMARC
Unsigned email claiming to be you Accepted Rejected (if policy=reject)
Signature from wrong domain Accepted Rejected (alignment failure)
Modified headers Signature fails, but… Rejected
Failed signature Often accepted anyway Rejected

Detection Guidance

Log Analysis

Check DKIM results in authentication headers:

Authentication-Results: mx.google.com;
       dkim=pass header.i=@example.com header.s=selector1;
       dkim=fail (signature verification failed) header.i=@spoofed.com

Common DKIM Failures

Failure Cause
permerror DNS record missing or malformed
temperror DNS timeout
fail Signature doesn’t match (modification or spoofing)
neutral No signature present

DKIM Record Auditing

Check your DKIM configuration:

dig +short TXT selector1._domainkey.yourdomain.com

Verify key strength:

# Check the key length (should be 2048-bit minimum)
echo "MIGfMA0..." | base64 -d | openssl rsa -pubin -text -noout

Alert Conditions

  • DKIM failures from your own domain (compromise or misconfiguration)
  • High-volume DKIM failures from partner domains
  • Emails with DKIM signatures from unexpected domains

What Killed It (or Weakened It)

Defense Introduced Impact
DomainKeys (Yahoo) 2004 Yahoo's original signing system; precursor to DKIM
DKIM (RFC 4871) 2007 Merged DomainKeys and Cisco's IIM into unified standard
DKIM Updated (RFC 6376) 2011 Refined cryptographic requirements and canonicalization
Major Provider Adoption 2012+ Gmail, Outlook, Yahoo sign all outbound mail by default

Attacker Adaptation