- From: Benjamin Kaduk <bkaduk@akamai.com>
- Date: Fri, 21 Jul 2017 10:31:46 -0500
- To: Willy Tarreau <w@1wt.eu>
- Cc: Martin Thomson <martin.thomson@gmail.com>, Subodh Iyengar <subodh@fb.com>, Mike Bishop <Michael.Bishop@microsoft.com>, HTTP Working Group <ietf-http-wg@w3.org>
- Message-ID: <801fd823-b583-fbea-eb13-33f6e20b031d@akamai.com>
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> 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:32:39 UTC