Back to blog
Threat Intel
Phishing Forensics

Blind Spot: The BEC Attack We Missed Due to a Malformed 'rua' URI

A single typo in a DMARC record blinded our security team to a months-long spoofing campaign. Here’s the forensic breakdown.

MailSleuth Research
Email Security Team
June 24, 20269 min read
A conceptual illustration of a technical blueprint representing a DMARC record, where a smudged component casts a shadow

It started, as it so often does, with a user's gut feeling. An accounts payable clerk stared at a wire transfer request from our CFO. The amount was within reason, the project name was plausible, but something felt off. Instead of clicking 'approve', she forwarded it to the security helpdesk. That one action pulled the thread on a campaign we should have seen months earlier.

The initial triage was textbook. We pulled the headers. The source IP was from a generic cloud provider, not our mail servers or any sanctioned partner. SPF failed, as expected. The DKIM signature was invalid. Classic direct-IP spoofing. But then we looked at the `Authentication-Results` header. DMARC alignment had failed, too. So why did our mail gateway let it through?

The answer was simple and unsettling: our DMARC policy was set to `p=none`. This wasn't a mistake; we were in a monitoring-only phase to gather intelligence before moving to `p=quarantine`. The real shock came when we checked the mailbox designated to receive DMARC aggregate reports. It was virtually empty. The sustained spoofing campaign targeting our executives was happening in a total blind spot. The alerts we were depending on never fired.

A Wire Request, a Gut Feeling, and a Missing Alert

The reported phish was a beautifully crafted piece of social engineering. It spoofed the display name and email address of our CFO perfectly. No weird character substitutions, no lookalike domains. Just a clean `From: "CFO Name" <cfo@our-domain.com>`. The body of the email was concise and created a sense of urgency without being overtly demanding — a classic Business Email Compromise (BEC) tactic. It asked for a payment to be expedited for a vendor on a confidential project.

Our playbook for this is immediate. The SOC analyst assigned the ticket immediately dove into the raw email headers. The `Received` chain told the story clearly: the email originated from a server in a data center completely unaffiliated with us or Microsoft 365. The `Authentication-Results` header confirmed the mechanical failure of the underlying protocols.

Authentication-Results: mta.our-domain.com; dkim=fail (signature-invalid) header.d=our-domain.com; spf=fail (sender IP is 198.51.100.23) smtp.mailfrom=our-domain.com; dmarc=fail action=none header.from=our-domain.com; — Excerpt from incident mail headers

SPF `fail`. DKIM `fail`. DMARC `fail`. Everything worked as designed. The DMARC `action=none` was also correct, given our policy. DMARC, as defined in RFC 7489, instructs the receiver on what to do. With `p=none`, the instruction is 'do nothing, but please send a report'. The failure wasn't in the policy enforcement; it was in the reporting. The entire point of this monitoring phase was to collect this exact kind of threat intelligence.

Chasing Ghosts in the Gateway Logs

The designated `rua` mailbox for our-domain.com was a ghost town. It received a handful of legitimate aggregate reports each day from Google, Microsoft, and a few other major mailbox providers. But there was nothing from the myriad of smaller ISPs and mail servers that would have processed the attacker's spoofed messages. An active spoofing campaign should be noisy. The silence was deafening.

Pivoting from DMARC to Raw Logs

If the reports weren't coming to us, we had to go find the data ourselves. We moved away from the DMARC reporting infrastructure and started querying our mail gateway logs directly. The search was simple: show us all inbound mail where the `header.from` domain is `our-domain.com`, but the source IP is not in our authorized SPF range.

The results started scrolling, and the scale of the problem became clear. It wasn't one attacker. It was a low-and-slow, distributed campaign. A few messages a day from one IP, then a few from another a week later. They were targeting not just the C-suite, but also key personnel in finance and HR. The campaign had been running for at least three months, completely invisible to our DMARC monitoring.

The Typo That Broke a Protocol

At this point, we knew the issue was with our DMARC record itself. We ran a simple `dig TXT _dmarc.our-domain.com` and stared at the output. It took a second pair of eyes to see it.

v=DMARC1; p=none; sp=quarantine; fo=1; rua=mailt:dmarc-agg@our-domain.com; ruf=mailto:dmarc-forensic@our-domain.com

There it was. A single, catastrophic typo. `rua=mailt:`. Not `mailto:`. A missing 'o' had rendered our entire aggregate reporting strategy useless. The forensic reporting tag, `ruf`, was correct, but since `fo=1` generates forensic reports only when *both* SPF and DKIM fail, and many of these attempts had one or the other pass (due to forwarding scenarios), we weren't getting those either. The vast majority of intelligence is in the aggregate `rua` reports.

Why MTAs Can't 'Just Figure It Out'

You might think a mail server could infer the intent. It's close enough, right? Wrong. RFC 7489 is explicit about URI validation. The `rua` and `ruf` tags must contain a valid URI. The scheme `mailt:` is not registered or recognized. A receiving Mail Transfer Agent (MTA) parsing this record has no choice but to treat it as a syntax error.

This isn't just pedantic compliance. It's a security feature. If receivers tried to guess or correct malformed URIs, it could lead to reports being misdirected. By strictly adhering to the specified format, the protocol ensures that reports are only sent to destinations that have been explicitly and correctly configured. When the `rua` value is invalid, the MTA simply discards the reporting instruction for that tag. It doesn't crash; it just fails silently.

How Receivers Interpret Broken Directives

To confirm our theory, we looked at how different, real-world MTAs handle this specific failure mode. You can't assume uniform behavior across the internet, but on this point, the industry is remarkably consistent.

Postfix with OpenDMARC

Many self-hosted and on-premises mail systems rely on Postfix, often paired with the OpenDMARC milter (mail filter). OpenDMARC is a reference implementation of the DMARC standard. When its parser hits `rua=mailt:...`, it flags it as a syntax error during the policy discovery phase. You'll see a log entry like `dmarc policy is not valid` or `bad URI`. The milter will still evaluate the email against the `p=` policy (`none` in our case), but it will not and cannot generate and send an aggregate report to the malformed URI. The reporting task is simply aborted.

Microsoft Exchange Online Protection (EOP)

The behavior within massive cloud providers like Microsoft and Google is similar, though their internal workings are less public. Analysis of message traces and known-good DMARC setups confirms that their parsers are equally strict. An invalid URI scheme in an `rua` tag means that tag is ignored. They aren't in the business of correcting DNS record typos for millions of domains. The logic is binary: is the URI valid per the RFC? If yes, queue a report. If no, drop the reporting instruction.

The takeaway is stark: no major mail provider will fix your broken DMARC record. The responsibility for correct syntax is 100% on the domain owner. The protocol is built on this assumption.

The Pre-Flight Checklist for DMARC

This incident forced us to completely overhaul how we deploy and manage our public-facing security DNS records. We now treat them with the same rigor as production code, which includes linting, validation, and peer review.

Validate Before You Publish

Never, ever publish a DMARC record (or an update to one) without first passing it through a trusted online DMARC validator. These tools don't just check for a valid tag. They parse the entire record string, checking for syntax errors, invalid characters, misplaced semicolons, and, yes, malformed URIs. A validator would have caught `mailt:` in seconds.

Common errors these tools catch include using a plain email address (`rua=abuse@our-domain.com`) instead of the full URI (`rua=mailto:abuse@our-domain.com`), typos in policy values (`p=rejec` instead of `p=reject`), or incorrect percentage tags (`pct=10O` instead of `pct=100`).

Confirm External Domain Verification

This is a second, crucial step that many admins miss. If your `rua` or `ruf` tag points to a different domain (e.g., a third-party DMARC reporting service), the receiving MTA needs to verify that the external domain has given you permission to send reports there. This prevents abuse.

RFC 7489 defines a mechanism for this. The receiving domain (e.g., `reports.vendor.com`) must publish a special TXT record to authorize reports for your domain (`our-domain.com`). The MTA for a service like Gmail will perform a DNS lookup for `our-domain.com._report._dmarc.reports.vendor.com`. If it doesn't find a `v=DMARC1;` record there, it will not send the report, even if your own DMARC record is perfectly formed. Your reporting vendor should provide clear instructions on how this works.

ARC: A Complication Worth Knowing

No discussion of DMARC failures is complete without mentioning the Authenticated Received Chain (ARC), specified in RFC 8617. ARC is designed to solve a fundamental problem: legitimate forwarding breaks SPF. When an email to you is automatically forwarded by, say, a mailing list or a legacy mail system, the forwarding server's IP address doesn't match your domain's SPF record. DMARC fails.

ARC attempts to fix this by creating a trusted chain of custody. Each intermediary MTA that handles the message can inspect the initial authentication results, and if they were valid, it can sign the message with its own ARC-Seal. The final recipient's MTA can then trace this chain back, see the original `dmarc=pass` verdict, and decide to trust the message despite the broken SPF.

How does this relate to our incident? It doesn't, directly, as this was a direct spoof. But when diagnosing DMARC failures, you must check for `ARC-Authentication-Results` headers. If you see ARC in play, it can explain why a message that *looks* like it should fail DMARC is being delivered. In our case, the absence of any ARC headers confirmed the attack was a simple, direct spoof and not a complicated forwarding scenario.

The takeaway

A `p=none` DMARC policy is not a passive control; it is an active intelligence-gathering system. But a system is only as good as its sensors, and our sensor was broken from the start. We operated for months with a sense of security, believing that the absence of DMARC reports meant the absence of spoofing attempts. The truth was the opposite: we were silently weathering a sustained attack and had no idea.

Treat your security DNS records—SPF, DKIM, and DMARC—like critical infrastructure code. Lint them, test them against spec, and get a second pair of eyes before you hit 'publish'. A simple syntax check with a free online validator or a more comprehensive tool like MailSleuth.AI's health checker can be the difference between proactive threat hunting and a painful post-incident forensic investigation.

#dmarc#bec#email-security#incident-response#malformed-dmarc-rua#spoofing
MailSleuth Research
Email Security Team

We dissect phishing campaigns and email infrastructure so you don't have to.