Subject: Public Reset; Connection ID; Attack; Defense

From: Jim Roskind <[email-masked]>
Date: Thu, 30 Mar 2017 19:04:43 -0500

I was asked to write up a vaguely plausible attack on a PublicReset that I
noticed a few years back.  Awareness of this caused me to not push (while I
was at Google) for the implementation and deployment of authenticated
PublicReset (we just deployed the forgeable flavor).  I could see the
resolution required(?) server selected IDs, which was anticipated as being
useful for a variety of additional reasons. Now that we're finally moving
in that direction, it is worth mentioning the issue.

PROBLEM

A PublicReset needs to be created by a server when a server receives
packets that it believes are related to a previously closed connection.
For example, this commonly(?) happens when a server bounces, losing all
state, and is incapable of continuing the encrypted/authenticated dialog
(i.e., the server no longer has applicable key material, and must instead
construct the authenticated PublicReset based only on the ConnectionID and
perhaps some persistent private key material). A PublicReset may similarly
be generated if a connection has been closed for a while, and client sends
a request using a ConnectionID that has been forgotten by a server.

At the same time, the design requires that it is hard (impossible) for a
third party attacker (disrupter?) to send a valid PublicReset.

The general expectation is that a client (involved in an actual connection)
will receive at least enough information to authenticate a PublicReset.
Most critically, when a PublicReset is used, it is very publicly visible,
and can be replayed.  ...but that would only be an issue if the
ConnectionID was reused.

ATTACK:

With client-selected ConnectionID, it was plausible that an adversary could:

   - Observe, and possibly forestall (delay?) transmission of a ClientHello
   containing ConnectionID X sent towards site Y
   - Race off to some server Y' and quickly obtain from Y' (an affiliated
   server?) effectively some PublicReset validation data for ConnectionID X,
   sufficient to be able to forge future PublicReset packets with said
   ConnectionID. For instance, it might receive a sample PublicReset for that
   ConnectionID!
   - Allow the original packet from to proceed to the original site Y,
   creating a connection using said ConnectionID X.

The malicious racer can then disseminate a PublicReset packet at any point
in the future.  This (partially) negates the value of PublicReset feature.

DEFENSE

By allowing the server to specify a connectionID, we prevent a malicious
racer from obtaining such info about an applicable PublicReset.

Since we are already moving in this direction (server selects
ConnectionID), we should probably continue to codify this, before
proceeding deploy or to codify the details of the PublicReset.

---

From: "Lubashev, Igor" <[email-masked]>
Date: Fri, 31 Mar 2017 05:42:12 +0000

This attacker seems interested in denying X communicating with Y and possesses the capability to (a) receive a copy of all X→Y traffic; (b) inject packets toward X, spoofing Y, (c) out-race X→Y packets to Y.  That attacker can simply use its (a) and (c) abilities to capture X’s client-hello, modify it a little -- leaving client-id alone, and race it to Y.  As a result, X’s actual packet will be ignored and the handshake will fail.

I am not confident that server-selected connection id would help here.  This seems to be a hard problem to protect connection initiation from an attacker capable of (a) and (c).

-          Igor

From: Jim Roskind [mailto:[email-masked]]
Sent: Thursday, March 30, 2017 7:05 PM
To: IETF QUIC WG <[email-masked]>
Subject: Public Reset; Connection ID; Attack; Defense

I was asked to write up a vaguely plausible attack on a PublicReset that I noticed a few years back.  Awareness of this caused me to not push (while I was at Google) for the implementation and deployment of authenticated PublicReset (we just deployed the forgeable flavor).  I could see the resolution required(?) server selected IDs, which was anticipated as being useful for a variety of additional reasons. Now that we're finally moving in that direction, it is worth mentioning the issue.

PROBLEM

A PublicReset needs to be created by a server when a server receives packets that it believes are related to a previously closed connection.  For example, this commonly(?) happens when a server bounces, losing all state, and is incapable of continuing the encrypted/authenticated dialog (i.e., the server no longer has applicable key material, and must instead construct the authenticated PublicReset based only on the ConnectionID and perhaps some persistent private key material). A PublicReset may similarly be generated if a connection has been closed for a while, and client sends a request using a ConnectionID that has been forgotten by a server.

At the same time, the design requires that it is hard (impossible) for a third party attacker (disrupter?) to send a valid PublicReset.

The general expectation is that a client (involved in an actual connection) will receive at least enough information to authenticate a PublicReset.  Most critically, when a PublicReset is used, it is very publicly visible, and can be replayed.  ...but that would only be an issue if the ConnectionID was reused.

ATTACK:

  *   Observe, and possibly forestall (delay?) transmission of a ClientHello containing ConnectionID X sent towards site Y
  *   Race off to some server Y' and quickly obtain from Y' (an affiliated server?) effectively some PublicReset validation data for ConnectionID X, sufficient to be able to forge future PublicReset packets with said ConnectionID. For instance, it might receive a sample PublicReset for that ConnectionID!
  *   Allow the original packet from to proceed to the original site Y, creating a connection using said ConnectionID X.
The malicious racer can then disseminate a PublicReset packet at any point in the future.  This (partially) negates the value of PublicReset feature.

DEFENSE

By allowing the server to specify a connectionID, we prevent a malicious racer from obtaining such info about an applicable PublicReset.

Since we are already moving in this direction (server selects ConnectionID), we should probably continue to codify this, before proceeding deploy or to codify the details of the PublicReset.

---

From: Martin Thomson <[email-masked]>
Date: Fri, 31 Mar 2017 07:20:48 -0500

Thanks for writing this up Jim.  It's an interesting attack, and it
certainly seems plausible.

If you consider a distributed server that doesn't ensure that
connections IDs are unique across a scope larger than the scope of its
PublicReset keys, then this is a problem.

An attacker could exploit that by making a connection to a server that
shares keys but does not guarantee uniqueness of connection IDs.  It
uses a matching connection ID and induces a PublicReset.  Assuming the
authentication design ekr proposes, the only way to generate a spoofed
PublicReset is to get one, but this could be trivially done by sending
a packet with a short header on a new 5-tuple.  Sending the same
PublicReset would then be enough to kill the other connection.

This doesn't really need a race if the attacker is willing to allow
some packets through.  All it needs is the 5-tuple and selected
connection ID for the victim flow.

So Igor, I think that your (a) and (c) are relatively easy to achieve
in practice.  Certainly a lot easier to achieve than I'd like.

The most obvious fix is to use server-selected connection IDs (as we
currently have) and to recommend the scope of uniqueness match (or
exceed) the scope of the keys used for PublicReset.  That could mean
operational burden, so I'd be interested in hearing ideas about better
fixes.

On 31 March 2017 at 00:42, Lubashev, Igor <[email-masked]> wrote:
> This attacker seems interested in denying X communicating with Y and
> possesses the capability to (a) receive a copy of all X→Y traffic; (b)
> inject packets toward X, spoofing Y, (c) out-race X→Y packets to Y.  That
> attacker can simply use its (a) and (c) abilities to capture X’s
> client-hello, modify it a little -- leaving client-id alone, and race it to
> Y.  As a result, X’s actual packet will be ignored and the handshake will
> fail.
>
>
>
> I am not confident that server-selected connection id would help here.  This
> seems to be a hard problem to protect connection initiation from an attacker
> capable of (a) and (c).
>
>
>
> -          Igor
>
>
>
>
>
> useful for a variety of additional reasons. Now that we're finally moving in
> that direction, it is worth mentioning the issue.
>
>
>
> PROBLEM
>
>
>
> A PublicReset needs to be created by a server when a server receives packets
> that it believes are related to a previously closed connection.  For
> example, this commonly(?) happens when a server bounces, losing all state,
> and is incapable of continuing the encrypted/authenticated dialog (i.e., the
> server no longer has applicable key material, and must instead construct the
> authenticated PublicReset based only on the ConnectionID and perhaps some
> persistent private key material). A PublicReset may similarly be generated
> if a connection has been closed for a while, and client sends a request
> using a ConnectionID that has been forgotten by a server.
>
>
>
> and can be replayed.  ...but that would only be an issue if the ConnectionID
> was reused.
>
>
>
> ATTACK:
>
>
>
> Observe, and possibly forestall (delay?) transmission of a ClientHello
> Race off to some server Y' and quickly obtain from Y' (an affiliated
> Allow the original packet from to proceed to the original site Y, creating a
> connection using said ConnectionID X.
>
> Since we are already moving in this direction (server selects ConnectionID),
> we should probably continue to codify this, before proceeding deploy or to
> codify the details of the PublicReset.
>
>

---

From: "Lubashev, Igor" <[email-masked]>
Date: Fri, 31 Mar 2017 14:11:46 +0000

Martin Thomson wrote:
> The most obvious fix is to use server-selected connection IDs (as we currently have) and
> to recommend the scope of uniqueness match (or exceed) the scope of the keys used
> for PublicReset.

This may help against PublicReset killing the connection.  But how do you defend against a simpler attack -- racing client's own client-hello but modifying something (for example packet # or version) ahead of the client's actual client-hello?  (The attack on client-hello does require being able to observe client-hello messages and not just some messages.)

---

From: Martin Thomson <[email-masked]>
Date: Fri, 31 Mar 2017 11:32:01 -0500

That is not something that can be defended against without the server
being willing to tentatively establish multiple concurrent handshakes
on the same 5-tuple.  I suspect that this specific problem falls into
a class of problems that we have to just concede: an attacker can
interfere with the handshake before a common key is established.

---

From: Ryan Hamilton <[email-masked]>
Date: Fri, 31 Mar 2017 10:29:34 -0700

Indeed. I believe that to be somewhat inevitable.

On Fri, Mar 31, 2017 at 9:32 AM, Martin Thomson <[email-masked]>
wrote:

> currently have) and
> > This may help against PublicReset killing the connection.  But how do
> you defend against a simpler attack -- racing client's own client-hello but
> modifying something (for example packet # or version) ahead of the client's
> actual client-hello?  (The attack on client-hello does require being able
> to observe client-hello messages and not just some messages.)
>
>