Memory Hole discussion / OpenPGP e-mail header protection

Daniel Kahn Gillmor dkg at
Wed Jul 1 06:18:25 CEST 2015

On Tue 2015-06-30 04:10:04 -0400, Bjarni Runar Einarsson wrote:
> True. It did occur to me that naming the header after an RFC actually
> accomplishes the versioning that was requested, but that's probably
> bordering on "too clever".  I agree that protected-headers is fine.

That's if we end up needing it a versioning header at all, of course :)

> This is an important point. However, I think my scheme makes such
> tampering easy to detect.

sure, the detection of tampering is easy!  it's figuring out what to do
about it that's hard.

> Consider that the proposed protected-headers attribute is not user
> configurable; this attribute is not created if you attach a
> message/rfc822-headers part by hand, and is not generated by the bounces
> or delivery reports the MIME type is commonly used for.
> However, the protected-headers attribute *is* protected by the PGP
> encryption envelope or signature and is thus tamper resistant.
> That means that IF it is present, then it MUST be contained within a
> RFC2822 part with a matching message-ID. If that constraint is violated,
> then the message has been tampered with.
> Because message-IDs are important for so many things, threading etc.,
> they are generally NOT routinely modified by MTAs or mailing lists. So
> the rate of false posities should be quite low.

is the rate really what we're concerned with, though?  It seems to me
that we're discussing here is defense against an active adversary who is
trying to convince you of something counterfactual related to the
signatures.  The worst counterfactual is to convince you that something
in the unsigned context is included in the signed material.  Maybe there
are other possible attacks?

> We were never going to be able to prevent tampering, the best we can do
> is detect it. This scheme accomplishes that.
> Does that hold water?

I think the argument here is that there are two kinds of attacks on
signed headers:

 0) make you think a correctly-signed header is invalid

 1) make you think some other arbitrary data is correctly-signed

attack (0) has so many easy ways to accomplish (random bit flips,
whitespace injection) that we shouldn't presume to defend against it.

attack (1) is harder to understand and work out.  I think you're
claiming that it's impossible, but i don't see an exhaustive argument
for it.  there are all kinds of ways that it could be repurposed in a
bad way.

Consider an attack like the following:

 A) Bob sends Alice two signed messages, X and Y.  Both of them are
    memory-hole, multi-part/signed messages.  Message X is "Subject:
    Xavier" with body "I think we should fire him." and message Y is
    "Subject: Yuri" with body "We are lucky to work with him."

 B) Alice wants to cause some trouble.  She creates a new message Z
    that is multipart/mixed, with two subparts, each of which are the
    multipart-signed bodies of X and Y.  the part containing X's body is
    marked Content-Disposition: inline, and the part containing Y's body
    is marked Content-Disposition: attachment.

 C) in the headers of message Z, she copies the Message-ID from message

 D) Alice shares message Z with Yuri, telling him separately: "watch out
    for Bob, he wants to fire you!"

 E) Yuri sees a message with a signed header from Bob and a signed body
    from Bob, but the message he gets is the opposite of Bob's intended

> It is possible, but it becomes very awkward to work with. Since MIME is
> effectively designed as a stream protocol (you can generate an infinite
> stream of data which is also infinitely nested, and is still valid
> MIME), it's just not designed to make inferring position (or relative
> position) easy to do.
> If you try to infer position you have two choices:
> 1. Parse the entire message into an intermediate data structure and
>    then evaluate that.
> 2. Write code which evaluates a stream on the fly.

I'm not sure we're talking about the same thing when we're talking about
"inferring position".  CSS selectors also work on tree-structured
documents and they're able to recognize things like :

 body > div > span.mhole

 message/rfc822 > multipart/signed > multipart/mixed > message/rfc822-headers

> Option 1 perpetuates the performance nightmares of PGP/MIME: you can't
> do anything useful with a message without parsing the whole thing. I'd
> like to avoid encoding this bad behavior into the spec.

if we're looking at signatures, you're right that we won't be able to
evaluate them until the entire message is processed.  This is not
particularly negotiable.

If we want to talk about message signature structures that can sign
messages piecemeal, that introduce whole new semantics and UI concerns,
which i think we really don't want to get into.

> Option 2 is only marginally more performant than option 1, in that you
> can stop parsing when you've found what you need - but you still need
> to start at the beginning and parse everything from there, updating
> counters as you go and hoping that your MIME library traverses the
> message tree in a stable and predictable way.

Surely these are requirements of any sane mime library in the first place?

> Yes, but Patrick is correct that the verifiation parser will need to
> correctly decode before comparing with the public header section.
> The simple case is simple: encodings on the public header and the
> protected one should simply be the same by default. If they're
> different, then the message has been tampered with.
> Unfortunately, such tampering is common. If I send 8bit headers (not
> an uncommon thing to do in Iceland a few years ago), some MTAs might
> helpfully re-encode the header section. A good implementation of Memory
> Hole will avoid raising a false positive here, but I'm not sure how much
> work is involved.
> As always, signtures are the difficult bit and some implementations
> might choose to not perform header validation at all just because it's
> hard to get it right.

Why shouldn't the signed embedded header (if you have a valid signature
that covers it) should just replace any tampered external header?

> Encryption is easy: protected-headers in an encrypted part can just be
> trusted blindly and overwrite whatever was in the public section. Is
> there any need to warn the user about tampering (considering the high
> expected rate of false positives), if we're able to recover from it
> gracefully?

I'm not convinced this is as easy of an argument; the encryption doesn't
necessarily contain a signature, right?


More information about the Gnupg-devel mailing list