Subject: Re: [Curdle] Comments on draft-ietf-curdle-ssh-ext-info

From: Peter Gutmann <[email-masked]>
Date: Thu, 6 Apr 2017 12:04:27 +0000

denis bider (Bitvise) <[email-masked]> writes:

>Can you point out some of these subtle problems that could occur in this
>regard in SSH?

I was thinking of the problem that it's essentially impossible to safely do n-
RTT, n < 1, for TLS, which meant that doing the same thing for SSH wasn't
going to be any better.  I was reasoning by analogy from TLS rather than
sitting down and drawing diagrams for SSH to try and figure out all the
possible issues.

>Under the assumption that such an extension were defined, can you point out
>at least one way that sending this info right after NEWKEYS can help an
>attacker?

It depends on the extension.  Without one defined, there's no way to tell at
the moment.  I could invent something that works out badly, but that'd be
creating a strawman... my concern is that in the future someone may define a
problematic extension without realising that they're creating a problem.
Perhaps adding an implementation note to say that at this point the crypto
hasn't been confirmed yet and so you may want to be careful about what you put
into your extension data would be useful?

>But the extension value field is generically a string (it must be same type
>for all extensions, so unsupported extensions can be decoded and ignored).
>"p" and "s" are therefore fitting ways to express this boolean.

Wouldn't "true" and "false" be a better way to express a boolean?  I realise
this is kinda bikeshedding, but having to look up the spec just to figure out
what mysterious magic values in a boolean field specify seems a bit awkward.

>Properly implemented flow control is superior. However, this extension is a
>nod to that not everyone will be using an SSH library that does this right,
>and "no-flow-control" is a better option if your needs are simple, and you
>don't have a few years to get this right.

Given that there are a nonzero number of implementations that send a window
size of ~0 to indicate no flow control, it may be useful to add an
implementation note to point this out.  I enabled some diagnostic code to
throw an exception in my code if it found this from another implementation
(other than mine) and got, uh, feedback from beta-testers about it, so at
least some implementations are using a pseudo-infinite window size to indicate
no flow control.  I'm not saying it should be adopted as an alternative to
"no-flow-control", but merely to alert implementers about the practice, e.g. a
certain big iron vendor whose device would crash and reboot as it tried to
allocate ~0 bytes of memory to match the widow size.

Peter.

---

From: denis bider <[email-masked]>
Date: Thu, 6 Apr 2017 23:32:07 -0600

> I was thinking of the problem that it's essentially
> impossible to safely do n-RTT, n < 1, for TLS, which
> meant that doing the same thing for SSH wasn't going
> to be any better.  I was reasoning by analogy from TLS
> rather than sitting down and drawing diagrams for SSH
> to try and figure out all the possible issues.

OK, but I'm not familiar with the security implications of this on TLS.

Can you link to any resources where this was discussed? Whether for TLS, or
in any other context?

> Perhaps adding an implementation note to say that at this
> point the crypto hasn't been confirmed yet and so you may
> want to be careful about what you put into your extension
> data would be useful?

 I agree, if this is a threat, we should add a warning in Security
Considerations. But to make that warning, I have to understand the threat.

If someone asks me about this warning, I want to be able to explain the
reason in detail. At this point, what I can say is, "Peter said this on the
list." That is, to me, insufficient backing.

> Wouldn't "true" and "false" be a better way to express a
> boolean?

Yes if you could choose the type. But you can't choose the type, because
all extensions have to use the same type. That type is a string.

> I realise this is kinda bikeshedding, but having to look
> up the spec just to figure out what mysterious magic
> values in a boolean field specify seems a bit awkward.

Booleans are equally mysterious.

The third parameter to the Windows API function WaitForMultipleObjects is a
boolean. Suppose an application passes "TRUE". Without checking the docs -
what does that mean?

If you check the docs, you know what "TRUE" in that context means. And if
you check the spec here, you know what "p" and "s" mean.

Booleans are not inherently self-documenting. (In fact - when used in
languages with positional parameters, they are more frequently
self-obfuscating.)

> Given that there are a nonzero number of implementations
> that send a window size of ~0 to indicate no flow control,
> it may be useful to add an implementation note to point
> this out.

OK. I added the following sub-section to my current working copy:

3.3.1.  Implementation Note: Prior "No Flow Control" Practice

  Before this extension, some applications would simply not implement
  SSH flow control, sending an initial channel window size of 2^32 - 1.
  Applications SHOULD NOT do this for the following reasons:

  - It is entirely within the realm of possibility to transfer more than
    2^32 bytes over a channel. The channel will then hang if the other
    party implements SSH flow control according to [RFC4254].

  - There exist implementations which cannot handle such large channel
    window sizes, and will exhibit non-graceful behaviors, including
    disconnection.

denis

On Thu, Apr 6, 2017 at 6:04 AM, Peter Gutmann <[email-masked]>
wrote:

> _______________________________________________
> Curdle mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/curdle
>

---

From: Eric Rescorla <[email-masked]>
Date: Fri, 7 Apr 2017 08:21:13 -0700

On Thu, Apr 6, 2017 at 10:32 PM, denis bider <[email-masked]>
wrote:

> Can you link to any resources where this was discussed? Whether for TLS,
> or in any other context?
>

Here is the section of TLS 1.3 that describes the security implications of
0-RTT data:

https://tlswg.github.io/tls13-spec/#zero-rtt-data

FWIW, it's less clear to me that these apply to SSH because at least the
replay issues stem from the desire to have loosely coupled distributed
servers and seamless fall back from server state or synchronization failure.

-Ekr

> The third parameter to the Windows API function WaitForMultipleObjects is
> a boolean. Suppose an application passes "TRUE". Without checking the docs
> - what does that mean?
>

---

From: Peter Gutmann <[email-masked]>
Date: Sat, 8 Apr 2017 03:24:16 +0000

>Can you link to any resources where this was discussed? Whether for TLS, or

It's difficult providing a useful link because it's been discussed on and off
in various threads on the TLS WG list for quite some time.  There are a range
of opinions on how safe it is, but in general it seems 0RTT is bad and 0.5RTT
is iffy.  That is, you can do 0RTT if you're incredibly careful (I talked to a
dev at a large content provider and he said their analysis showed they'd have
to implement nonzero-RTT at the application layer in order to deal with 0RTT
at the TLS layer, which kinda defeats the point), but if anyone ever tries it
I foresee a range of Black Hat/Defcon talks and conference papers on how to
exploit it following shortly afterwards.

>Yes if you could choose the type. But you can't choose the type, because all
>extensions have to use the same type. That type is a string.

What I meant was use the string value "true" for boolean true and "false" for
boolean false.  It seemed pretty intuitive :-).

>OK. I added the following sub-section to my current working copy:

Thanks, that helps to document existing practice and alert implementers.

Incidentally, the places where I've found this is typically embedded, where
there's no chance of every transferring anywhere near ~0 bytes, so it's not a
problem.  OTOH the second issue is real, you can force a reboot of one
vendor's carrier-grade routers by opening an SSH connection to it with a
window size of ~0.

Speaking of embedded, would there be any interest in adding an extension to
say that an implementation only supports one channel, and for the other side
to not try anything fancy beyond treating it as an encrypted telnet?  This is
also fairly common in embedded, where you're emulating encrypted telnet and
nothing more.  scp/SFTP is handled by moving the binary data over the
encrypted-telnet channel, with various degrees of hackery.

Peter.

---

From: denis bider <[email-masked]>
Date: Sat, 8 Apr 2017 04:40:39 -0600

Thank you for providing this link, Eric.

What this TLS section terms Zero-RTT, and what Peter appears to imply is
0RTT, seem to be completely different things.

In TLS, "0RTT" data appears to be data that are sent upfront in the
client's first packet to the server, encrypted using a pre-shared key
before the handshake has derived a traffic secret.

In SSH, there is no such concept at all. This would be equivalent to
sending data encrypted with some type of pre-shared key as part of the
client's KEXINIT, which is not what is happening here.

The EXT_INFO packet sent by the client after NEWKEYS is not Zero-RTT. It is
data sent after a full and completed key exchange.

---

From: denis bider <[email-masked]>
Date: Sat, 8 Apr 2017 04:56:24 -0600

> There are a range of opinions on how safe it is,
> but in general it seems 0RTT is bad

According to the link provided by Eric, Zero-RTT in TLS is a concept that
does not even exist in SSH. I can see why people would have concerns about
sending data upfront encrypted with a make-do key based only on a
pre-shared secret. That is inherently problematic and needs care.

If SSH had this concept, it would involve bundling some kind of
pre-encrypted data with the client's original KEXINIT. We do not have
anything like that.

EXT_INFO is sent after several round-trips, encrypted after a full,
completed key exchange. I don't see any way that's similar to Zero-RTT.

> What I meant was use the string value "true" for
> boolean true and "false" for boolean false.

In that case I would prefer to go for full strings like "preferred" and
"supported", but that seemed like a waste. :)

> Speaking of embedded, would there be any interest in
> adding an extension to say that an implementation only
> supports one channel, and for the other side to not try
> anything fancy beyond treating it as an encrypted telnet?

As-is, the "no-flow-control" extension already dictates there will be no
more than one concurrent channel. What do you have in mind beyond that?

denis

On Fri, Apr 7, 2017 at 9:24 PM, Peter Gutmann <[email-masked]>
wrote:

> or
> all

---

From: Eric Rescorla <[email-masked]>
Date: Sat, 8 Apr 2017 07:52:12 -0700

> before the handshake has derived a traffic secret.

That's more-or-less correct. You don't actually use the PSK but derive a
separate key from the PSK. The security challenges mostly derive from the
fact that the
server doesn't have an opportunity to provide a nonce.

> The EXT_INFO packet sent by the client after NEWKEYS is not Zero-RTT. It
> is data sent after a full and completed key exchange.
>

I'm not familiar enough with SSH to have an opinion here.

-Ekr

>>> The third parameter to the Windows API function WaitForMultipleObjects
>>> is a boolean. Suppose an application passes "TRUE". Without checking the
>>> docs - what does that mean?
>>>
>>> If you check the docs, you know what "TRUE" in that context means. And
>>> if you check the spec here, you know what "p" and "s" mean.
>>>
>>> On Thu, Apr 6, 2017 at 6:04 AM, Peter Gutmann <[email-masked]
>>> > wrote:
>>>

---

From: Peter Gutmann <[email-masked]>
Date: Tue, 11 Apr 2017 00:11:06 +0000

denis bider <[email-masked]> writes:

>does not even exist in SSH. 

Yeah, as I said, I was reasoning by analogy, that there were concerns in TLS
about sending data before mutual confirmation of crypto parameters had taken
place.  Obviously SSH isn't TLS, but in this case it would also be sending
data before the mutual conf. had occurred, i.e. before the other side's
NEWKEYS had been received.

>As-is, the "no-flow-control" extension already dictates there will be no more
>than one concurrent channel. What do you have in mind beyond that?

Hmm, but the text around it is a bit confusing, it says "MUST refuse" (= MUST
NOT I assume?) but then immediately follows it with SHOULD allow it, so it
doesn't really appear to say "only one channel".

That text really is confusing since it contradicts itself across the two
sentences.  What about replacing it with:

  Implementations MUST NOT open more than one simultaneous channel when this
  extension is in effect.

Peter.

---

From: Peter Gutmann <[email-masked]>
Date: Tue, 11 Apr 2017 00:26:48 +0000

>  Implementations MUST NOT open more than one simultaneous channel when this

Following up to this, I'm not sure that no-flow-control would restrict you to
only using one channel.  You can still multiplex several channels onto the SSH
link without flow control, you just get n non-flow-controlled channels instead
of one.

Peter.

---

From: denis bider <[email-masked]>
Date: Mon, 10 Apr 2017 23:39:07 -0600

> Yeah, as I said, I was reasoning by analogy [...]

At this time, I'm mentally filing this under "probable misinterpretation".

I don't think this warrants further attention.

> Hmm, but the text around it is a bit confusing, it says "MUST
> refuse" (= MUST NOT I assume?) but then immediately follows
> it with SHOULD allow it, so it doesn't really appear to say
> "only one channel".

The text right now is:

  Implementations MUST refuse to open more than one simultaneous channel
  when this extension is in effect. Nevertheless, server implementations
  SHOULD support clients opening more than one non-simultaneous channel.

This seems to me unambiguous:

- There MUST NOT be more than one concurrent channel in a session with
"no-flow-control" enabled.

- There MAY be any number of consecutive (non-simultaneous) channels.

Do you propose some way to make it clearer than this?

> Following up to this, I'm not sure that no-flow-control would
> restrict you to only using one channel.  You can still multiplex
> several channels onto the SSH link without flow control,
> you just get n non-flow-controlled channels instead of one.

Allowing this provides the receiver with no option to pause reception on
one channel without blocking the entire connection. This introduces
additional complexity for any implementation that properly implements flow
control, which would prefer to use the SSH flow control mechanism in this
circumstance, but has to implement special measures to block the entire
connection if one channel backs up.

"no-flow-control" is intended for simple use cases. For multiplexing
channels, we have a better solution, it is to implement flow control.

denis

On Mon, Apr 10, 2017 at 6:11 PM, Peter Gutmann <[email-masked]>
wrote:

> more