RE: CBV

"Seth Goodman" <[email protected]>
Newsgroups gmane.mail.spam.srs.general
Message-ID <[email protected]>
> From: Mark Shewmaker
> Sent: Thursday, May 06, 2004 6:04 AM
>
>

Thanks for the feedback and ideas, Mark.  You've obviously put a lot of
thought into this.

> On Fri, 2004-04-30 at 11:24, Seth Goodman wrote:
> > Let me try to address both Tony's and Wayne's questions at the
> > same time.
> > Wayne's second point is a valid objection about mailing lists breaking
> > content checks.  This is a real problem today and it breaks any content
> > check, including S/MIME.
>
> I don't think these are valid objections.
>
> Mailing lists shouldn't be sending out emails to subscribers using the
> same MAIL FROM given by the original sender anyway, so even if they have
> edited the message contents before sending them to their subscribers,
> they'll have created a new MAIL FROM to go with that edited content.

Wayne's original objection was that mailing lists change the body of the
email by appending list subscription info, etc.  This will break any test of
message body integrity.  This had nothing to do with the MAIL FROM:.

However, mailing lists have to change the MAIL FROM: per RFC2821, so the
original SES-signed MAIL FROM: is discarded after any verification they do.
As you correctly pointed out, the mailing list would have to create a new
MAIL FROM: that included new hashes.  This actually does answer Wayne's
objection while still retaining the full body check.  Thanks for thinking of
this solution!  I should have realized this myself.

That takes care of mailing lists, but any forwarding system that appends or
prepends anything to the body would similarly break any check of the message
body.  The simple answer to that is, "don't do that", but changing any
existing practice is hard.  That was a lot of the motivation behind SES in
the first place, that is, not breaking any existing practice.  Fortunately,
there is an easy fix for forwarding systems that feel the need to prepend
lines like "Virus-checked by XYZ Company's Fabulous AV Product":  put that
very important information in an X-header, where it belongs.  I don't think
that we have to accept the practice of forwarding machines adding anything
to message bodies.  As long as it is a minority of systems, I think that
having their outgoing mail rejected will motivate them to find another
solution.


>
> As far as MS exchange and other MTA's munging the body of emails and
> thus causing checksums to become invalidated--well, I would consider it
> a feature that corrupted emails can be detected.

Strongly agree.  I believe these same MTA's can deliver S/MIME messages that
verify properly, so it appears that the are capable of delivering
uncorrupted message bodies.


<...>

> > Though something ultimately needs to be done about
> > this in general, let's assume that nothing changes and we have
> > to deal with
> > the status quo.  For the purpose at hand, which is preventing a
> > harvested
> > SES address from being used for spoofing, I will change my proposal and
> > suggest that we only need to protect the headers, not the body
> > content to
> > avoid Wayne's valid objection.
>
> Except for being prepared ahead of time for any future SMTP extension
> that allows body headers to be sent before the rest of DATA, I don't see
> any advantage in limiting the checksum to body headers.

Now that you've found a solution to the mailing list problem, I completely
agree with you.  We should return the inner hash to covering the message
body so as to more fully prevent replay attacks.


>
> More below.
>
> > In Wayne's exploit of SES, the spammer harvests signed addresses from
> > responses sent from general sales accounts or other loosely administered
> > accounts at large sites.  Since this method of exploit is now
> > known, you can
> > protect yourself against it by limiting the outgoing mail to a single
> > recipient and include a hash in the MAIL FROM: that protects the same
> > headers that S/MIME would protect.  Please correct me if I have
> > these wrong,
> > but I believe that these are To:, cc:, bcc:, From:, Sender: and
> > Date:.  With
> > a single recipient on the outgoing message and a hash that
> > protects these
> > headers, the signed return path would only be useful for the
> > spammer to spam
> > himself.
>
> I don't think I'd be the only one to object to solutions that disallow
> multiple recipients in the envelope headers.

This restriction was not intended for most email.  It was only intended for
accounts that are very promiscuous and send out responses to anyone who
asks, thereby exposing their signed return-paths to harvesting by malicious
parties.  Now that the inner hash can cover the message body, this
restriction isn't needed anymore.


>
> > Wayne's first point was that we couldn't really protect the
> > content with a
> > checksum.  I certainly agree with that and I proposed a SHA-1
> > hash rather
> > than a checksum to fix this.  If we are protecting only headers
> > and not the
> > message body, I think it becomes an intractable problem to synthesize a
> > group of headers that generates the same SHA-1 hash as the
> > original message
> > headers.
>
> I disagree with the implication that an attacker would effectively find
> it any easier to find a collision by adding/changing random characters
> in the full message body versus adding/changing random characters in a
> limited set of message body headers.
>
> Remember that for a good hash, when you change one bit of the data being
> hashed, there's a 50% chance that each bit in the hash output is
> flipped.
>
> You don't get any advantage when searching for a hash-collision in
> altered 10M files versus 10k files, if a hash collision is your only
> goal.  (In fact, it's probably slightly easier, given that the hash will
> have less data to have to, well, hash.)
>
> The attacker could simply limit the search to changing and testing bits
> in *any* of the headers that are looked at.  If you're truncating the
> hash to four characters then there's more than enough space in even
> these few headers in which one could find a collision.  (Most users
> wouldn't notice a CC: to "dfb89q3n028 <[email protected]>", just as they
> wouldn't notics an html comment of "dfb89q3n028bas98hjg" were it
> embedded in the message body instead.)
>
> BTW, I think four characters is not nearly enough..

I believe you're right here, but only for the header/body hash.  Computing
the outer hash that protects the MAIL FROM: requires knowing the hash
secret.  Unless you can crack that, you can't verify that a modified address
string will produce the correct outer hash value.  Therefore, the outer hash
length only has to be long enough to prevent cracking the hash secret.


>
> If the hash data is truncated to four characters, (as you suggest in
> another message I've quoted below) then you should expect a 50%
> likelyhood of finding a hash collision by going through every
> just-as-many-bits changes as bits in the truncated hash output.

OK.


> In this
> case that's 4 characters multiplied by 6 bits per character, or 24 bits,
> meaning 16 million tests--pretty easy to run through, and no matter if
> the data being hashed is limited to a few headers or consists of the
> entire body, you're still merely cpu bound.
>
> I'm typing this email on a 1.6GHz Athlon, where doing an sha1sum of
> /etc/inittab took me .002 seconds.  Making the simplifying assumption
> that I can do any sha1sum in .002 seconds means that in less than 9
> hours and twenty minutes I can test 64^4=2^24=16777216 combinations of
> data, for which I would expect a 50% likelyhood of coming across any
> specific truncated-to-4-base-64-characters hash I wanted to find.
>
> (In reality the time should be much less, as I wouldn't be actually
> loading and dynamically linking the same sha1sum program 64^4 times, but
> the point is that this is very doable.)
>
> In any event, four characters is not possibly enough.

For the inner (header/body) hash where the algorithm is defined ahead of
time and no hash secret is required, you are right and this is a real
vulnerability.  This makes it clear that the header/body hash in MAIL FROM:
needs to be longer, or we can use another trick that I propose below.


>
> Truncating less would obviously improve things, perhaps having the SES
> format allow for a variable number of characters for the
> verifiable-SES-hash section, and just including enough characters so
> that the cpu bound process is intractable at any given time.

This is a nifty idea and I really like it.  The only difficulty is that
getting everyone to gradually lengthen it over time will not be easy.


<...>

> 1.  Imagine an SES-enabled MTA sends out emails with the following
>     mail_from format, slightly different from the above:
>
>     SES0=H27=T4=L27=local-part@domain
>
>     Or:
>
>     SES0=   Unchanged.
>     H27=    A 27-character base-64 representation of all 160 sha1
>             bits of all of the following:  ("SES0", local secret,
>             T4, C27, local-part@domain).
>     T4=     A 4-character base-64 representation of a 32-bit time_t,
>             the number of seconds since the epoch.
>     L27=    A 27-character base-64 representation of all 160 sha1
>             bits of all of the following ("SES0", local secret, TT,
>             local-part@domain.)
>
>     For completeness:
>
>     B27=    A 27-character base-64 representation of all 160 sha1
>             bits of all of the following ("SES0", TT,
>             local-part@domain, message body.)
>
>             Note that C27 is not included in this mail_from, but
>             it is included in the computation of H27.

I assume that B27 above was a typo and you meant C27.

As I've argued above, the outer hash doesn't need to be 160-bits long.
Since the attacker would need the hash secret to check possible new return
paths, the outer hash only needs to be long enough to prevent cracking the
hash secret.  Shevek did look into this and suggested 24-bits as adequate.
Therefore, I suggest that we stay with a 24-bit outer hash.

Next let's consider the timestamp.  The timestamp has two possible
functions:  to date the signed return path so it can be expired and to act
as a salt for the outer hash.  For the purpose of expiring the timestamp,
all we really need is resolution in days.  Once we add an inner hash, there
is no longer a need to salt the outer hash calculation.  Therefore, I
suggest that we stay with two base-32 digits with one day resolution.

Making the inner hash longer is definitely one way to fix the vulnerability
that you found.  Assuming my arguments above hold water, what we're left
with is:


SES0=HHHH=C27=TT=local-part@domain

where

   HHHH = first four base-64 digits of the SHA-1
          hash of "C27=TT=local-part@domain"
          prepended with the hash secret
          (MSA login password) for
          local-part@domain

   C27  = 27 base-64 digits comprising the SHA-1
          hash of the concatenation of the From:,
          Sender:, Reply-To:, Date: and Subject:
          headers plus the message body in
          unencoded form

   TT   = first two base-32 digits of the UNIX
          integer day number mod 1024

The "SES0=HHHH=C27=TT=" overhead is 41 characters, leaving only 23
characters left for "local-part" before we exceed the 64-byte limit.  We
don't really need the full 160-bits to protect the message, so we can
shorten it somewhat to accommodate longer local parts.  How much we can
shorten it is unfortunately a moving target.

Given the above, I can suggest three possible courses of action.  There are
probably lots of others.

1) Use the full 160-bit inner (content) hash and live with the fact that any
local part longer than 23 characters will break the RFC2821 64-byte limit.
This will not occur often and it is not without precedent.  SRS can cause a
local part to exceed 64-characters and no one has gotten particularly upset
about that.  SRS does not have as much overhead as the above address format,
so the problem will occur less often but it will still occur.  This is the
simplest approach of the three.


2) Use Mark's nifty variable length inner hash idea as follows.  Reduce the
inner hash length as necessary in order to keep the total local part down to
64 bytes, but never reduce the inner hash length below 14 base-64 digits
(84-bits; arbitrary, suggest your own number).  The hash digits will always
represent a contiguous range of the 160-bit hash starting with the first
bit.  This will allow up to 36 characters in "local-part" before breaking
the 64-byte limit at the cost of less security.


3) Use a short inner hash that protects a full SHA-1 hash inside the message
headers.  Here is one possible format:

SES0=HHHH=hhhh=TT=local-part@domain

where

   HHHH = first four base-64 digits of the SHA-1
          hash of "hhhh=TT=local-part@domain"
          prepended with the hash secret
          (MSA login password) for
          local-part@domain

   hhhh = first four base-64 digits of the SHA-1
          hash of the X-Content-Hash: header line

   TT   = first two base-32 digits of the UNIX
          integer day number mod 1024

header line added to message:

   X-Content-Hash:C27

where

   C27  = 27 base-64 digits comprising the SHA-1
          hash of the From:, Sender:, Reply-To:,
          Date: and Subject: header lines plus the
          message body in unencoded form

This will allow a 46 byte "local-part" before breaking the 64-byte limit
while retaining the full security of #1, above.  Though the inner hash
length in the MAIL FROM: is short, it protects a 160-bit hash inside the
message headers, so it still puts an insurmountable computational burden on
an attacker.  The inner hash still needs to be there to tie the MAIL FROM:
to a particular message.  Otherwise, the signed MAIL FROM: could be used in
a replay attack.

One possible form of forgery attack would be to create a message that gives
the same 160-bit hash as contained in the X-Content-Hash: header.  This is
not currently realistic.  A second approach is to come up with a new 160-bit
hash that results in the same 24-bit inner hash (hhhh) in the MAIL FROM:,
which you showed is achievable.  However, the attacker is again left with
the problem of constructing a message that gives the new 160-bit hash, which
is not tractable.

I think this third option is best, since it requires the attacker to either
crack the outer hash secret or construct a message that yields an arbitrary
160-bit SHA-1 hash result.  It also allows the longest "local-part" before
breaking the 64-byte limit.

--

Seth Goodman
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.