Spoofing comes in three forms. Direct spoofing forges a domain you control or trust; lookalike domains register a near match; display-name impersonation puts a trusted name over an unrelated address. SPF, DKIM and DMARC address the first. Hunting covers the other two by comparing header fields, domain similarity and sender history.
Signals at a Glance
| Signal | Where | ATT&CK |
|---|---|---|
| DMARC fail, or SPF and DKIM both failing or absent for the From domain | Authentication-Results header | T1656 |
| Composite authentication failure on mail claiming to be internal | Microsoft 365 message trace | T1534 |
| From domain differs from Return-Path or Reply-To domain | Header analysis | T1656 |
| Sender domain within a small edit distance of a protected brand, or using homoglyphs | Domain watch, gateway | T1583.001 |
| Display name of an executive or vendor on a first-contact external address | Gateway impersonation rules | T1656 |
Reading the Results
The receiving server records SPF, DKIM and DMARC outcomes. Microsoft 365 also records a composite result with a reason code. Query them as structured fields and look for failures that were still delivered, because those show a gap in policy rather than a missed detection:
// Defender XDR (KQL) - delivered inbound mail with authentication failures
EmailEvents
| where Timestamp > ago(7d)
| where EmailDirection == "Inbound" and DeliveryAction == "Delivered"
| extend Auth = parse_json(AuthenticationDetails)
| extend SPF = tostring(Auth.SPF), DKIM = tostring(Auth.DKIM), DMARC = tostring(Auth.DMARC), CompAuth = tostring(Auth.CompAuth)
| where DMARC =~ "fail" or CompAuth =~ "fail" or (SPF =~ "fail" and DKIM !~ "pass")
| extend FromDomain = tostring(split(SenderFromAddress, "@")[1]), EnvDomain = tostring(split(SenderMailFromAddress, "@")[1])
| summarize msgs=count(), recipients=dcount(RecipientEmailAddress), subjects=make_set(Subject, 3)
by FromDomain, EnvDomain, SPF, DKIM, DMARC, CompAuth
| order by recipients desc
// tune/validate: legitimate third-party senders (CRM, ticketing, marketing) often fail until configured
Lookalikes and Your Own Policy
A lookalike domain can pass every authentication check because the attacker owns it. Hunt by similarity and age, and audit your own domains so spoofing the exact name fails:
# Audit published policy for the domains you own (replace example.com) dig +short TXT example.com | grep -i "v=spf1" dig +short TXT _dmarc.example.com # Expect an enforcing DMARC policy, for example: # v=DMARC1; p=reject; rua=mailto:dmarc-reports@example.com; adkim=s; aspf=s # p=none only monitors. Move to quarantine then reject once aggregate reports show all legitimate senders aligned. # Check each DKIM selector in use: dig +short TXT selector1._domainkey.example.com # tune/validate: confirm with aggregate (rua) reports before tightening, to avoid breaking legitimate mail streams.
- Maintain a protected list of your brand, executives and top vendors, and alert on external senders whose domain or display name resembles them.
- Monitor newly registered and certificate-transparency domains containing your brand string, and feed confirmed domains to the gateway block list.
- Compare the sender’s history: a vendor address that suddenly arrives from a new domain, or with a changed bank-detail request, is the pattern behind payment diversion.
- Keep internal-domain spoofing blocked at the connector level by rejecting unauthenticated mail that claims your own domain.
Use the SPF, DKIM and DMARC specifications, Microsoft 365 guidance on anti-spoofing and composite authentication, your gateway’s impersonation protection documentation and DMARC aggregate-report tooling. Baseline your own environment — third-party senders are the largest source of authentication noise.
Build Detections That Fire
Mjolnir Security helps blue teams turn threat intelligence into high-fidelity detections across endpoint, network, identity and cloud telemetry.
- Detection Engineering We build and tune detections mapped to ATT&CK from your own telemetry.
- Threat Hunting as a Service Hypothesis-driven hunts for the behaviours on this page.
- 24/7 Incident Response Containment when a detection fires. Call +1 833 403 5875.
Stay ahead of emerging threats. Get notified when we publish new intelligence reports and advisories.
Subscribe to Alerts