Subject: Re: [spfbis] #22: RFC 4408: Section 2.5.7 PermError on invalid domains after macro expansion

From: Alessandro Vesely <[email-masked]>
Date: Sat, 01 Sep 2012 13:06:47 +0200

On Fri 31/Aug/2012 16:18:32 +0200 Murray S. Kucherawy wrote:
> On Fri, Aug 31, 2012 at 1:17 AM, Alessandro Vesely <[email-masked]> wrote:
>> Non-match makes sense in case the record is correct, but the parameter
>> is malicious, e.g.:
> 
> Is there a deterministic way to identify abuse?
> 
> "Do X if the input data is malicious" is not a recipe for normative
> guidance.

Right.  Scott said to leave specific wording aside for a moment.  I
don't think it's worth attempting an exact definition of "malicious"
anyway.

An idea is to do something like the following after macro expansion
but before DNS lookup:

  if (is_malformed(term.domain) || strlen(term.domain) > 63)
  {
    if (is_malformed(parameter) ||
      strlen(parameter) > REASONABLE_LENGTH)
        return NO_MATCH;

    report_error(spf_rec, &term, ERR_MALFORMED);
    return PERMERROR;
  }

> We need to pick the one that's more generally applicable, and move
> forward with it.

It seems to me that not only local macros are involved, but also
intermixed use of domain macros during HELO evaluation, and %h during
MAIL FROM.

We could have restricted the use of those macros to terms that imply
no DNS query, such as explanations.  Now, assuming we didn't intend to
do that, we need to grant them a fair usability.  Taking into account
that SPF grammar provides no way to guard against malformed
parameters, /any/ non-trivial use of those macros can result in a
malformed domain, potentially.

Hence, inflexibly mandating permerror implies an unintentional penalty
for users of those macros, inasmuch as (1) there is an attack path
whereby an abuser of the domain name can get --by design-- a permerror
rather than the stipulated result, and (2) the rr=e tag of RFC 6652
will not be limited to real errors, but include items rather akin to
rr=f or similar.

---

From: Scott Kitterman <[email-masked]>
Date: Mon, 03 Sep 2012 01:28:26 -0400

> will not be limited to real errors, but include items rather akin to

I think the 'attack' path is limited to 'p'.  In all other cases additional 
information that's looked up in DNS is based on the domain owner's DNS.

Scott K

---

From: Alessandro Vesely <[email-masked]>
Date: Mon, 03 Sep 2012 10:45:56 +0200

> information that's looked up in DNS is based on the domain owner's DNS.

Can you make an example with 'p'?

What I meant is, say:

   domain.example TXT "v=spf1 exists:{%h}._spf.domain.example -all"

Dunno why anyone would do so.  It is a non-trivial use of %h.  Now, an
abuser who knows no valid host name can avoid to "fail" like so:

S: 220 some.server.example
C: HELO some..funny.name..U..never.find..or..longer..stuff...
S: 250 Ok.
C: MAIL FROM:<[email-masked]>

Now the verifier finds the SPF record and gets a malformed domain
name.  Instead of "fail" it gets "permerror", which is incorrect IMHO.

A symmetric example could be built using %o during a helo check.  It
would looks less significant because tricking just the helo check
isn't worth.

BTW, several implementation evaluate HELO before getting MAIL FROM.
(That is, before a transaction gets started.)  What do they do if they
find %{o} in the record?  And does %{d} expand the same as %{h} in
that case?  I'm not sure the I-D explains that beyond any doubt.

---

From: Scott Kitterman <[email-masked]>
Date: Mon, 03 Sep 2012 14:03:46 -0400

>that case?  I'm not sure the I-D explains that beyond any doubt.

The SPF record for both the Mail From and HELO domains are published by the domain owner, so in order for the concerning behavior you describe to occur, the domain owner would have had to published a record asking for it.

PTR and the "p" macro are different because they involve name attributes associated with the connecting IP address, which is under control of the attacker or their ISP.

Given that there is a precise description of what to use for localpart in HELO checks, I don't understand what's confusing?

Scott K

---

From: Alessandro Vesely <[email-masked]>
Date: Tue, 04 Sep 2012 08:49:43 +0200

On Mon 03/Sep/2012 20:03:46 +0200 Scott Kitterman wrote:
>> Dunno why anyone would do so.  It is a non-trivial use of %h.
>> Now, an abuser who knows no valid host name can avoid to "fail"
>> like so:
>>
>> Now the verifier finds the SPF record and gets a malformed
>> domain name.  Instead of "fail" it gets "permerror", which is
>> incorrect IMHO.
> 
> The SPF record for both the Mail From and HELO domains are
> published by the domain owner, so in order for the concerning
> behavior you describe to occur, the domain owner would have had to
> publish a record asking for it.

There would be no invalid domain issues if %h were used in exp=.  The
SPF record shown above uses %h so as to affect the result, which is
what I call non-trivial use.  The question is:  Is it possible to use
%h in such a way?  My claim is that if invalid domains MUST result in
PermError, then there is _no good way_ to use %h.  That is, such that
authorized senders pass and attackers match -all.

Thus, if we solve #22 by mandating PermError, we should state that %h
is a sort of second-class macro.  BTW, is it used?

> PTR and the "p" macro are different because they involve name
> attributes associated with the connecting IP address, which is
> under control of the attacker or their ISP.

Is this point related to invalid domains/PermError?

> Given that there is a precise description of what to use for
> localpart in HELO checks, I don't understand what's confusing?

This is a different subject.  I'll post a separate message on it.