<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
<!-- NERF is a trademark of defconxt. -->
---
name: performing-email-authentication-testing
description: >-
  Test and validate email authentication mechanisms including SPF, DKIM, DMARC,
  ARC, and BIMI configurations. Verify policy enforcement, alignment modes,
  reporting pipelines, and identify misconfigurations that allow spoofing.
domain: cybersecurity
subdomain: email-security
tags:
  - spf
  - dkim
  - dmarc
  - arc
  - bimi
  - authentication
  - dns
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1566.001", "T1566.002"]
  tools: [dig, swaks, python3, openssl, nslookup]
---

# Performing Email Authentication Testing

## Overview

Email authentication (SPF, DKIM, DMARC) prevents spoofing but misconfiguration
is endemic. Testing validates DNS records are correctly published, policies
enforce reject/quarantine, DKIM signatures verify, alignment modes match,
and aggregate/forensic reports flow to the right endpoints.

## Prerequisites

| Requirement | Purpose |
|---|---|
| dig / nslookup | DNS record queries for SPF, DKIM, DMARC |
| swaks | SMTP test message injection |
| openssl | DKIM key verification |
| Domain admin access | Fix identified misconfigurations |

## Workflow

### Step 1: SPF Record Validation

```bash
# Retrieve and display SPF record
dig TXT example.com +short | grep "v=spf1"

# Count DNS lookups (max 10 per RFC 7208)
python3 -c "
import dns.resolver
def count_lookups(domain, depth=0):
    if depth > 10: return 0
    total = 0
    try:
        answers = dns.resolver.resolve(domain, 'TXT')
        for r in answers:
            txt = r.to_text().strip('\"')
            if 'v=spf1' not in txt: continue
            for part in txt.split():
                if part.startswith(('include:', 'redirect=')):
                    target = part.split(':', 1)[-1].split('=', 1)[-1]
                    total += 1 + count_lookups(target, depth + 1)
                elif part.startswith(('a', 'mx', 'ptr')):
                    total += 1
    except Exception:
        pass
    return total
print(f'DNS lookups: {count_lookups(\"example.com\")}')
"

# Test SPF with swaks — should PASS
swaks --to test@example.com --from legit@example.com --server mx.example.com

# Test SPF — should FAIL (unauthorized sender)
swaks --to test@example.com --from ceo@example.com --server external-relay.com
```

### Step 2: DKIM Validation

```bash
# Retrieve DKIM public key
dig TXT selector1._domainkey.example.com +short

# Verify DKIM key format
python3 -c "
import base64
key = 'MIGfMA0GCS...'  # from DNS record p= value
try:
    decoded = base64.b64decode(key)
    print(f'Valid base64 key, {len(decoded)} bytes')
except Exception as e:
    print(f'Invalid key: {e}')
"

# Send test message and check DKIM signature in headers
swaks --to test@example.com --from sender@example.com --server mx.example.com \
  --header "Subject: DKIM Test" --body "DKIM validation test"
```

### Step 3: DMARC Policy Testing

```bash
# Retrieve DMARC record
dig TXT _dmarc.example.com +short

# Validate DMARC policy components
python3 -c "
record = 'v=DMARC1; p=reject; rua=mailto:dmarc@example.com; pct=100'
parts = dict(kv.strip().split('=', 1) for kv in record.split(';') if '=' in kv)
issues = []
if parts.get('p') == 'none':
    issues.append('WARN: Policy is none — no enforcement')
if 'rua' not in parts:
    issues.append('WARN: No aggregate report URI')
if parts.get('pct', '100') != '100':
    issues.append(f'INFO: Only {parts[\"pct\"]}% of messages evaluated')
if parts.get('sp', parts.get('p')) == 'none':
    issues.append('WARN: Subdomain policy is none')
for i in issues:
    print(i)
if not issues:
    print('OK: DMARC policy looks correct')
"
```

### Step 4: ARC Chain Verification

```bash
# Check for ARC headers in forwarded messages
grep -E "^(ARC-Seal|ARC-Message-Signature|ARC-Authentication-Results):" forwarded.eml

# Validate ARC chain instance numbers are sequential
grep "^ARC-Seal:" forwarded.eml | grep -oP 'i=\d+' | sort -t= -k2 -n
```

## Detection Opportunities

| Signal | Source | Description |
|--------|--------|-------------|
| DMARC failures | DMARC aggregate reports | Messages failing alignment |
| SPF permerror | DNS logs | Exceeding 10 DNS lookup limit |
| Missing DKIM | Email gateway | Messages from own domain without DKIM signature |

```yaml
title: Email Authentication Testing Detection
id: a86fc2a7-28e9-4c8c-83b1-c5def83c5895
status: experimental
description: Detects suspicious activity related to performing email authentication testing techniques in email security context
logsource:
  category: email
  service: exchange
detection:
  selection:
    Subject: "*urgent*"
  condition: selection
level: medium
tags:
  - attack.t1566.001
  - attack.t1566.002
  - attack.initial_access
falsepositives:
  - Bulk email migration by authorized IT administration tools
```

## Verification

- [ ] SPF record published with DNS lookup count ≤ 10
- [ ] DKIM selector resolves and key validates
- [ ] DMARC policy set to reject or quarantine with pct=100
- [ ] Aggregate report URI receives DMARC reports
- [ ] Test messages from unauthorized sources are rejected
- [ ] ARC chain validates for forwarded messages

## References

- [RFC 7208 — SPF](https://datatracker.ietf.org/doc/html/rfc7208)
- [RFC 6376 — DKIM](https://datatracker.ietf.org/doc/html/rfc6376)
- [RFC 7489 — DMARC](https://datatracker.ietf.org/doc/html/rfc7489)
- [RFC 8617 — ARC](https://datatracker.ietf.org/doc/html/rfc8617)

---
v1.0 | Validated: 2026-03-18
