Re: h2#373 HPACK attack mitigation options

On Wed, Mar 5, 2014 at 11:09 AM, Roberto Peon <grmocg@gmail.com> wrote:

>
>
>
> On Wed, Mar 5, 2014 at 2:23 AM, Martin Thomson <martin.thomson@gmail.com>wrote:
>
>> See https://github.com/http2/http2-spec/issues/373
>>
>> See also
>> http://lists.w3.org/Archives/Public/ietf-http-wg/2014JanMar/0233.html
>>
>> So, we've been discussing ways forward with this, and I think that
>> there is a general desire to proceed with HPACK, something we'll
>> probably confirm today.  But that means that (in Adam's words) we'll
>> have to "require[s] downstream technologies to maintain more
>> invariants in order to avoid leaking sensitive information."
>>
>> I think that we can limit the exposure to this problem to a subset of
>> HTTP implementations, rather than the full community of HTTP users.
>> This would allow us to keep compression, which I think is an important
>> part of the HTTP/2 feature set.  In particular, this would allow us to
>> keep compression without significantly weakening it, as some people
>> have suggested.
>>
>> Firstly, we will need to be super careful about properly identifying
>> the subset of implementations that might be affected by this.  I do
>> not want a situation where some implementers think that they can avoid
>> implementing mitigations for this attack, when in fact they should be.
>>
>> An implementation is potentially affected by this attack if it allows
>> multiple actors to influence the creation of HTTP header fields on the
>> same connection.  It also requires that header fields provided by any
>> one actor be kept secret from any other actor.  In the canonical
>> example of a browser, the invariant we want to maintain is that any
>> origin (the primary class of actor in that context) is unable to
>> access header fields that are created by other origins, or the browser
>> itself.
>>
>> I'll note that this is also potentially an issue for non-browsers that
>> use proxies.
>>
>> In terms of mitigation, I have so far heard two options.  There may be
>> others.  I don't think that we should pick one, but instead describe
>> the principles underpinning both and what it would take to properly
>> implement them.  Then allow implementations to decide what works best
>> for them.
>>
>> Option 1 - Origin isolation
>>
>> This solution relies on identifying the actor that is producing each
>> header field.  Each actor can only access entries in the table that
>> they themselves have caused to be added.  Fields added by other actors
>> cannot be seen and referenced.
>>
>> Browsers can use the web origin model [RFC6454] to identify actors.
>> Much of the mechanisms needed are already used by browsers in other
>> areas (image rendering, cross origin requests, script execution,
>> etc...).
>>
>> The HTTP stack might mark certain header fields as "safe" and make
>> these available to all origins.  For instance, in a browser, the
>> entries for Accept or Accept-Encoding, which is usually fixed in
>> browsers, and not really secret, so exporting those for reuse by other
>> actors is a good idea.
>>
>> I believe that this solves the problem perfectly.  However...
>>
>> The first drawback is that this has worse utilization of the memory we
>> allocate for header compression.
>>
>> When I mentioned this to Nick and Patrick, both basically recoiled in
>> horror at the notion of having to implement this.  This option widens
>> the interface to the HTTP stack and all the tracking adds complexity
>> to what is already the trickiest piece of HTTP/2 to get right.  I can
>> only imagine that this could be even harder for other implementations
>> to get right, especially those that don't integrate their HTTP stack
>> as closely as Firefox does.
>>
>
> This adds some complexity, but doesn't increase memory requirements, at
> least not in non-attack cases.
> Given the mechanism used for expiration of state in HPACK, this mechanism
> results in a decrease in compressor efficiency mostly in the attack case,
> which seems reasonable.
>

Maybe I am misunderstanding. It seems like in the case where you
have (a) sharding and (b) shared cookies across shards, doesn't
this create a lot of replicas of those across the shards for each
origin?


> If no state is carried over from connection-to-connection, then causing
> the connection to be torn down refereshes the counter's state, and it
> becomes equivalent to limiting MAX_CONCURRENT_STREAMS.
> A timer on this state that outlives the connection lifetime would work to
> concretely define the number of bits/second which can be probed.
> I'm confident that variant 1 with this would work.
>  #2 is subtle and depends on more variables (how does the probability
> compound, decrease, etc. Bleh.).
>
>
>>
>>
>> Side note: Limiting SETTINGS_MAX_CONCURRENT_STREAMS
>>
>> My sense is that this is going to be basically ineffectual.  Since
>> we're talking about a network attacker, I'm fairly certain that this
>> attacker can cause a browser to instantiate new connections, simply by
>> breaking an existing one.
>>
>>
> Playing with this limits the number of attempts that can occur without the
> server being informed of the evidence of the attack.
> If there is a timer on reconnects, this ends up limiting the number of
> bits/second which can be probed similarly to option 2 above.
>
> There is a further option, which is "perfect" against this style of
> attack, and is arguably simple. One can think of it as a variant of #1.
> Option #4
> Requests originating from a domain which is not the origin to which the
> request is ultimately directed are disallowed to use *any* dynamic
> compressor state.
>

So this would be the same evaluation as with same origin policy but
more strict? I.e., I have a connection to site A, and then site B
pulls in a GIF from A vs. <img src>, but the second request doesn't
get to use the compressor state?

-Ekr

Received on Wednesday, 5 March 2014 12:50:51 UTC