spf-discuss
[Top] [All Lists]

RE: A hole in planned phishing-prevention?

2004-06-14 13:27:46
From: Tony Finch
Sent: Monday, June 14, 2004 1:10 PM



<...>

I should explain what I mean by return addresses and destination addresses
more carefully, since it's subtle. This is a classification of addresses
according to where they may validly appear in a message's envelope, and is
a property of the address independent of any message. The current usual
case is that a valid address is valid anywhere, but it is becoming
increasingly common to reject bounces to addresses that are never used in
the return path, i.e. "destination addresses" are only valid in RCPT TO
commands that follow a non-empty MAIL FROM address. Similarly, VERP
techniques such as SES and SRS have introduced a class of addresses that
are only used in the return path of outgoing messages or the RCPT TO of a
bounce, i.e. "return addresses" are not valid after a non-empty MAIL FROM.

(I should probably call addresses that are restricted this way
"destination-only" and "return-only" addresses, and addresses that
might or might not be restricted "destination-valid" and "return-valid"
addresses.)

This makes sense.  I like the -only and -valid designations, as it is
explicit what is meant.


The subtlety comes when you consider the message header. Obviously you put
destination-valid addresses in the To: and CC: headers. You must also put
destination-valid addresses in the headers that the recipient may use to
send a reply, i.e. the Reply-To: and From: headers. Finally, the semantics
of the Sender: header imply that it contains the same kind of address as
the From: header, and in some circumstances it may also be used to address
replies -- RFC 822 says

        Sometimes, a recipient may actually wish to  communicate  with
        the  person  that  initiated  the  message  transfer.  In such
        cases, it is reasonable to use the "Sender" address.

SES (or VERP or SRS) does turn plain email addresses into return-only
addresses for use only in the return-path (or RCPT TO: for null-sender
messages).  Similarly, if all outgoing email is SES signed, then all plain
email addresses become destination-only email addresses for use in RCPT TO:
for non-null-sender messages, To:, From:, Sender: and Reply-To:.  I think
this accomplishes the separation of address usage that you suggest.



Therefore a system that signs the envelope return paths of outgoing
messages should not also sign the Sender: header, and recipient systems
should not assume that the PRA is the same as the return path, and if
you're really keen on callout verification you should verify addresses in
the message header using the call-forward form not the call-back form.

This is where I'm confused.  Sorry for the terribly long post, but there are
a lot of related issues.  As I see it, the ultimate goal of our 2821
validation is to validate the originating return-path.  Everything else is a
means to that end.  The originating system does sign the envelope
return-path (MAIL FROM:), but does not sign any other addresses.  The
signature in the envelope return-path has two functions:  it allows
detecting forged null-sender messages and it allows recipients to validate
the envelope return-path by doing sender callbacks.  Such callbacks could be
by the ever-unpopular CBV or via a DNS query to a special-purpose DNS server
that can validate signed return-paths with ultra-low network and CPU
overhead (for the MTA).

None of this has anything directly to do with PRA, which is the current
sender.  That sender may be the originator or a forwarder.  If the current
sender is the originator, doing an SPF check validates the return-path.  If
the current sender is a forwarder, we can explicitly trust the forwarder to
do SPF checks on incoming and thus assume indirect validation of the
return-path.  For this particular scenario, validating current sender (PRA)
via SPF does validate the originating return-path.  I wish this described
the whole situation and we could stop right there.

However, it is slightly more complicated than that.  An exploit that many
SPF-compliant MTA's will accept is a forward with a forged _originating_
return-path and forged From: (the joe-job victim) when sent from an MTA that
is a designated sender for its (disposable) domain.  That domain will not be
an explicitly trusted forwarder, so sites that maintain a trusted forwarder
whitelist _may_ reject the message.  Sites that don't use a trusted
forwarder list will probably accept the message.  Trusting a forwarder is
more complicated than believing that they do SPF checks on incoming.  It
also involves knowing how they qualify sites that _they_ designate as
trusted forwarders on incoming.  This describes a web of trust that is
extremely hard, if not impossible, to unravel.  One reasonable position is
that it is safe to trust a forwarder who has _no_ incoming trusted forwarder
list and validates the originating envelope-sender for all incoming
forwards.  I think it highly unlikely that any forwarders will actually
operate this way.

This may seem contrived, since forwards are something the recipient normally
sets up pointing to his own account.  However, a forger posing as a
forwarder does not have that restriction.  In order to reject this kind of
forgery where the forger's domain passes SPF, an originating envelope-sender
check is necessary.  This, in turn, requires some type of verifiable signed
envelope return-path.

One way around this dilemma is that whenever there is any reason to doubt
the originating envelope-sender address, validate the signed originating
envelope-sender address using a sender callback (preferably the
to-be-developed DNS type).  If the envelope-sender address is unsigned, you
can't validate it and should reject the message.  The simplest algorithm for
this is to always validate the envelope-sender address on a forward.  If we
_really_ trust specific forwarders to have already done this, then we can
skip this check.  For any untrusted forwarders, we could simply reject all
messages, or we could attempt to validate the originator envelope-sender.
This would allow us to confidently accept the message, despite the
forwarders lack of explicit trust by us.

What it boils down to is that any of the following are reasonably secure
strategies for SPF:

i)   accept only original messages or messages from trusted forwarders when
the SMTP-client passes SPF

ii)  accept original messages or messages from trusted forwarders when the
SMTP-client passes SPF; accept messages from untrusted forwarders only when
it is possible to validate a signed originating return-path with the
originating domain; SPF tests on untrusted forwarders are optional but
redundant

iii) accept original messages when the SMTP-client passes SPF; accept
forwarded messages only when it is possible to validate a signed originating
return-path with the originating domain; SPF tests on any forwarders are
optional but redundant


While iii) is the most secure and would accept virtually no forgeries,
accept virtually no joe-jobs and generate the fewest bogus bounces, very few
sites would be willing to restrict themselves like this.  However, if SES
signing of outgoing messages were a _requirement_ of SPF, this would be
possible, eventually.  Scheme ii) can also be safely used as a transition
path from scheme i) to scheme iii).  All mail from originators and trusted
forwarders that passes SPF will be accepted.  Some legitimate mail from
untrusted forwarders that would otherwise be rejected can now be accepted.
When enough sites adopt SES signing of return-paths, scheme iii) can be
adopted.

If the system works, the end result must be that the recipient either has
good reason to trust the return-path or reject the message.  Here is where
my original proposal comes in.  Once the recipient trusts the return-path, I
proposed to "unwrap" the signed return-path address (if signed) and make
sure that it either matches Sender:, if that exists, or From:, if Sender:
does not exist.  This will verify the key fields visible to the user and do
so at extremely low cost.  I have not proposed, nor was I contemplating, any
other checks during the DATA phase.  However, it seems that this check is so
lightweight and the gain is potentially so large as to make it worthwhile,
hopefully, even to those who presently resist _any_ checks during the DATA
phase for SPFv1.  This is not a slippery slope:  it is a great place to draw
the line.  If practical, it would largely obviate the need for _any_ XML
schema, which may never happen or if it does, could easily become a
bottomless tar pit (think Windows, Explorer, Outlook, exploit, patch,
exploit, patch, exploit, patch, ...).

Could you explain the use of call-forward verification?


It is perhaps OK to require that the de-signed return path is the same as
the PRA, but if that's what you mean, that is what you should say :-)

As you can see from the above, this has nothing to do with PRA.

--

Seth Goodman