Subject: Nested length: Re: Confirming consensus on using big-endian

From: Phillip Hallam-Baker <[email-masked]>
Date: Wed, 21 Dec 2016 09:10:09 -0500

I agree on big endian.

But one area I would point out as a serious fire hazard is nested length
specifiers. These are a real minefield from a security point of view. In
1980, it was considered OK to use tools that let the less skilled develop
code that would create security holes. Today we are all living with the
consequences of billions of holes created by millions of incompetents.

Specifically, the problem that comes up is encoding structures of the form

x {  { Test1 }, { Test2 } }

Encoding in XML, JSON or any modified S-notation like scheme is safe
because a decoder has to allocate memory as it goes. This is inefficient of
course.

Encoding in ASN.1 BER indefinite length encoding is also safe. Here we
identify the extent of terminal nodes by means of a length specifier but
close the list/set explicitly:

x { 4: "Test" , 5 "Test2" }

Encoding in the ASN.1 DER encoding is not only a pig to write unless you
know the trick, it is also unsafe.

11:  4: "Test" , 5 "Test2"

Specifically the problem comes when an attacker produces something of the
form:

11:  4: "Test" , 66666666: "Test2"

This is one of the main ways to create a buffer overrun and smash the stack.

Nested length encodings are really bad news and require serious coding
effort if a vulnerability isn't going to be created. While early
implementations of QUIC are likely to be at the application layer, we can
expect this sort of code to head to the kernel fairly fast.

The O/S people do not understand the seriousness of this problem. When
someone tried to put some protection macros into the Linux IPv6 code, Linus
himself called out the coder as guilty of 'compiler masturbation' and
publicly vilified him. So much for the many eyes theory of security. It
doesn't work so well if an ignoramus then ignores the result.

I strongly suggest a bar on nested length encodings in the spec and perform
an audit when you are done. It was a style that was acceptable in the 1980s
but we have learned is unsafe and must be avoided.

On Wed, Dec 21, 2016 at 7:55 AM, Eggert, Lars <[email-masked]> wrote:

> Hi,
>
> we had very strong consensus during the Seoul meeting to use big-endian
> encoding for QUIC. We'd like to confirm this consensus on the list.
>
> If you *disagree*, please reply to the list by Jan 6, 2017.
>
> Lars
>

---

From: Brian Trammell <[email-masked]>
Date: Thu, 22 Dec 2016 16:40:05 +0100

hi Phill,

Thanks for raising this point. The current arrangement of the packet header doesn't have nested length encoding issues (unless you count IP length and UDP length), however it does look a bit fiddlier than it needs to be. Simplifying the layout and reducing the permutations of field offset and length will reduce the number of ways packet processing can go wrong. I haven't dug into nested-length issues in the frame format or in TLS 1.3 yet, though.

(and in case there's any question on the pre-hijacked topic of this thread, I'm also in favor of big-endian, for the usual reasons.)

Cheers,

Brian

> On 21 Dec 2016, at 15:10, Phillip Hallam-Baker <[email-masked]> wrote:
> 
> I agree on big endian.
> 
> But one area I would point out as a serious fire hazard is nested length specifiers. These are a real minefield from a security point of view. In 1980, it was considered OK to use tools that let the less skilled develop code that would create security holes. Today we are all living with the consequences of billions of holes created by millions of incompetents.
> 
> 
> Encoding in XML, JSON or any modified S-notation like scheme is safe because a decoder has to allocate memory as it goes. This is inefficient of course.
> 
> Encoding in ASN.1 BER indefinite length encoding is also safe. Here we identify the extent of terminal nodes by means of a length specifier but close the list/set explicitly:
> 
> Encoding in the ASN.1 DER encoding is not only a pig to write unless you know the trick, it is also unsafe.
> 
> Specifically the problem comes when an attacker produces something of the form:
> 
> Nested length encodings are really bad news and require serious coding effort if a vulnerability isn't going to be created. While early implementations of QUIC are likely to be at the application layer, we can expect this sort of code to head to the kernel fairly fast.
> 
> The O/S people do not understand the seriousness of this problem. When someone tried to put some protection macros into the Linux IPv6 code, Linus himself called out the coder as guilty of 'compiler masturbation' and publicly vilified him. So much for the many eyes theory of security. It doesn't work so well if an ignoramus then ignores the result.
> 
> 
> I strongly suggest a bar on nested length encodings in the spec and perform an audit when you are done. It was a style that was acceptable in the 1980s but we have learned is unsafe and must be avoided.
> 
> 
> we had very strong consensus during the Seoul meeting to use big-endian encoding for QUIC. We'd like to confirm this consensus on the list.
>

---

From: Mike Bishop <[email-masked]>
Date: Thu, 22 Dec 2016 17:46:40 +0000

The problem I have with such a fundamental ban is that UDP already has a length field in the outside of the packet.  To prohibit nested length fields would be to prohibit length fields entirely in QUIC, which doesn't appear to be practical.  However, looking at places where they occur and asking whether there are better ways to accomplish the same thing is certainly a useful exercise.

The transport protocol has an obvious nested-length combination, of course: the collection of frames inside a packet.  The UDP packet has a length, by which the length of the AEAD data can be derived.  That data, decrypted, contains a series of frames.  Some frames are fixed-length, some specify their length, and some extend to the end of the packet.  The spec requires that a frame not cross a packet boundary, which could be read as a requirement that implementations check for excessive lengths, but that's not currently called out as explicitly as it could be.  If you have suggestions on how to eliminate this, they would be welcome, I'm sure.  Otherwise, I'd suggest we strengthen that language and move on.

In the HTTP layer, we also have some of this.  We're insulated from QUIC's framing by the bytestream abstraction - if one of our frames extends past the end of a QUIC frame... oh well.  And it often will, I expect.  HTTP/2 typically solves this in one of two ways:  Either the frame is a fixed-length (and any other length MUST be a fatal error), or the frame consists of a potentially-optional fixed-length segment followed by a variable-length segment that runs to the end of the frame.  The same is true for the HTTP/QUIC mapping as it currently stands.

The exception, in both cases, is SETTINGS.  In HTTP/2, each setting takes up six octets, so the SETTINGS frame payload must be a multiple of six octets.  In the current HTTP/QUIC, we've introduced variable-length setting values -- and you have a good point that, since each setting value specifies its own length, that length could run beyond the end of the SETTINGS frame.  If you have any suggestions on how to adapt the safer structures to that scenario, I'd welcome them; I'll give this some thought as well as adding language that the length MUST be compared to the remaining length of the frame.

-----Original Message-----
From: QUIC [mailto:[email-masked]] On Behalf Of Brian Trammell
Sent: Thursday, December 22, 2016 7:40 AM
To: Phillip Hallam-Baker <[email-masked]>
Cc: IETF QUIC WG <[email-masked]>
Subject: Re: Nested length

hi Phill,

Cheers,

Brian

> On 21 Dec 2016, at 15:10, Phillip Hallam-Baker <[email-masked]<mailto:[email-masked]>> wrote:

> On Wed, Dec 21, 2016 at 7:55 AM, Eggert, Lars <[email-masked]<mailto:[email-masked]>> wrote: