Re: New Version Notification for draft-thomson-http-replay-00.txt

I agree that we could document this attack as an example of what could happen and to reiterate that anything going in 0-RTT could is at risk of both replay and retry.

+1 for documenting the attack and dangers of sending things over 0-RTT, adding the header from the client, and moving forward with the draft.


Subodh

________________________________
From: Benjamin Kaduk <bkaduk@akamai.com>
Sent: Friday, July 21, 2017 8:31:46 AM
To: Willy Tarreau
Cc: Martin Thomson; Subodh Iyengar; Mike Bishop; HTTP Working Group
Subject: Re: New Version Notification for draft-thomson-http-replay-00.txt

On 07/21/2017 02:07 AM, Willy Tarreau wrote:

Hi Ben,

On Thu, Jul 20, 2017 at 01:12:23PM -0500, Benjamin Kaduk wrote:


On 07/20/2017 03:22 AM, Willy Tarreau wrote:


On Thu, Jul 20, 2017 at 09:59:39AM +0200, Martin Thomson wrote:


On 20 July 2017 at 06:25, Willy Tarreau <w@1wt.eu><mailto:w@1wt.eu> wrote:


     * There is no special API to handle 0-rtt data by the TLS terminator, i.e. it is treated as a part of the same 1-rtt stream of data


Does such an implementation really exist ? I mean, for openssl, it's clearly
different :


There's a split in the community on this point.  NSS merges the
streams and 0-RTT reads and writes are not different from other reads
and writes.


OK then I agree it's important to take care of this. One could say that
NSS transparently merging safe and unsafe data could cause trouble over
the long term and should possibly be adapted, but I don't know if that's
still possible.



I think that
we should take the conservative approach here.


I agree on being conservative, which is also why I'm trying to check if
instead we could suggest not to implement it if the underlying layer
doesn't provide the necessary guarantees regarding received data. Do you
have contacts with the people working on NSS to know if that would be
something making sense for them, based on this example ?




The debate in the TLS WG over the question of needing separate APIs for
a (potentially) ideologically separate data stream was ... quite
heated.  So I was hoping to not reopen it here, given that we seem to
have ended up at a consensus that it is possible to reason correctly and
obtain correct results using either philosophical picture.

Perhaps there would only need to be a new API for "did any data on this
stream arrive as early data" (in addition to the "is the handshake
finished" API already known about).



I'm fine with not reopening the debate, but at least we need to know what
grounds we're basing our design on. I understood during discussions at the
workshop that if the server receives the final handshake, it's a guarantee
that the client is the one we expect. But your example shows that it's not
sufficient to distinguish between really safe data and possibly replayed
ones (though my understanding is that the request could only be replayed
once, on the originally established connection).


(Some of this message seems addressed at Subodh and/or Martin, e.g., "your example".)
It may be helpful to distinguish between "replay" (attacker literally resending the bits observed on the wire) and "retry" (attacker incudes the client to send again the same plaintext but with different crypto/bits on the wire).

So in some sense, I would characterize this as a "retry", as the client is induced (by its timeout behavior) to resend the data.  Which set of bits shows up first at the proxy/server does not seem as important to me, for this terminology distinction.  The novel part of this attack is that the proxy could be confused into indicating that the payload was safe (er, into not indicating that it was unsafe, technically).  My first instinct is that having the client always include the header is the simplest remedy, and I'm not sure there's really a whole lot of harm if the header still gets included on a retry that is no longer over 0-RTT.




If we push the concept a bit further, the issue is more widely related to
retries in general, because the same principle could be used to force a
client to retry upon any timeout by holding on its data. Even a plain
regular HTTPS request (you just have to hold the last part containing
the request, delay it for a while and wait for the client to retry, or
even the user to press F5).

Thus what I'm seeing is that the root of the problem is not at all related
to the way we map HTTP on top of TLS, but to the fact that whenever there
is a possibility of retry, there can be a duplicate request. And in fact
it's a well known problem for those of us having to implement persistent
connections to servers.


I think that given the potential attacker abilities, we probably have to assume that anything sent in 0-RTT is something that a clever attacker could cause the client to retry.  That is, reiterating that only safe/idempotent/side-effect-free messages should go in 0-RTT.



The draft suggests that the client may only retry after seeing the 4NN
status code, it doesn't suggest it's allowed before. The intercepting
proxy trying to replay the request in your case will not be able to
deliver this 4NN status code as it would require to spoof the server's
connection. So in such a case there's no reason for the client to retry.

Probably that we should make it clearer in the draft that the client must
not retry on other situations ? But then I fear that we'd be walking on
the feet of existing implementations.

Your attack should probably be documented as an example of how/why blind
retries can be dangerous though, in case some implementers would like to
go too far.



I think it would be counterproductive to require that the client only retry when given 4NN (too early), as that opens up a DoS vector that would cause things to be much more sluggish than if the client had just waited to send it as 1-RTT.

I agree that we could document this attack as an example of what could happen and to reiterate that anything going in 0-RTT could is at risk of both replay and retry.

-Ben

Received on Friday, 21 July 2017 15:53:57 UTC