Subject: [hybi] Doubt about cliente-to-server masking

From: Iñaki Baz Castillo <[email-masked]>
Date: Fri, 28 Jan 2011 12:54:04 +0100

Hi, draft 04 states that client to server frames must be masked as follows:

-----------------------------------------------------------------------------
     masked-frame  = masking-nonce masked-data
     masking-nonce = 4full-octet
     masked-data   = *full-octet
     full-octet    = %x00-FF

   The masked-data is the clear-text frame "encrypted" using a simple
   XOR cipher as follows.

   1.  Let the frame-key be the SHA-1 hash of the concatentation of the
       masking-nonce followed by the masking-key.

   2.  Octet i of the masked-data is the XOR of octet i of the clear
       text frame with octet i modulo 20 of the frame-key:

     frame-key      = SHA-1(masking-nonce || masking-key)
     j              = i MOD 20
     masked-octet-i = clear-text-octet-i XOR octet-j-of-frame-key
-------------------------------------------------------------------------------

After the WS handshake, the server starts receiving bytes and it must
un-mask them. How can know the server when an entire frame has been
received? Maybe the server must wait until it has enough bytes in
order to un-mask the "Payload len" and "Extended payload length"? This
is, the masked-data has the same length than the clear frame, so after
un-masking those frame fields related to frame length the server
already knows how many bytes it must read in order to get the entire
frame. Am I right?

Isn't it becoming a "bit" complex? Just wondering.

Thanks a lot.

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Andy Green <[email-masked]>
Date: Fri, 28 Jan 2011 12:00:14 +0000

On 01/28/11 11:54, Somebody in the thread at some point said:

Hi -

> already knows how many bytes it must read in order to get the entire

Not sure if I get your issue... the masking nonce comes in the clear as 
the first 4 bytes of the packet.

So you can start unmasking immediately at the fifth byte onwards, which 
is the first header byte.  libwebsockets has a bytewise state machine to 
parse this traffic and that works out well.

> Isn't it becoming a "bit" complex? Just wondering.

Simplicity stopped being the goal when the browser vendors disabled 
websockets by default.  Now the goal is keeping the effort to have 
websockets at all alive by piling in whatever the browser vendors that 
disabled it want to see included, whether it is useful or not ie, "masking".

-Andy

---

From: Takeshi Yoshino <[email-masked]>
Date: Fri, 28 Jan 2011 21:05:48 +0900

> Hi, draft 04 states that client to server frames must be masked as follows:
I think so. We need to read N octet (necessary and sufficient) masked data
to get N octet unmasked data. We get the 20 octet frame-key once we receive
4 octets of masking-nonce. Just receive following 2 octets and xor with
frame-key[0 to 1] to know the length of extended payload length. If there's
N octet extended payload length, read N octets and xor with frame-key[1 to
1+N], ..., then payload ... as well.

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

---

From: Greg Wilkins <[email-masked]>
Date: Fri, 28 Jan 2011 23:18:33 +1100

On 28 January 2011 23:00, Andy Green <[email-masked]> wrote:
> So you can start unmasking immediately at the fifth byte onwards, which is
> the first header byte.  libwebsockets has a bytewise state machine to parse
> this traffic and that works out well.

The problem with this, is that it make masking part of the framing. ie
you cannot identify the boundary of a frame without understanding
masking.
Apart from the additional complexity and asymmetry in framing, this
will mean that we unable to ever to change the masking algorithm
(either for a
stronger or weaker algorithm) because it will break too much
infrastructure that gets built to understand masked framing.

I really think that masking should not change the framing that we took
so long to agree on.

---

From: Andy Green <[email-masked]>
Date: Fri, 28 Jan 2011 12:43:21 +0000

On 01/28/11 12:18, Somebody in the thread at some point said:
> On 28 January 2011 23:00, Andy Green<[email-masked]>  wrote:

It's true.

> I really think that masking should not change the framing that we took

I didn't appreciate this was behind your pushing 
masking-as-an-extension, but of course that makes sense to subordinate 
it to the header.

Will people agree to having ten bytes or whatever in plain?  Nobody 
wanted to make a list of attacks that are websocket business or not to 
worry about so it's just arbitrary if people will allow it or not.

-Andy

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Fri, 28 Jan 2011 13:55:18 +0100

>> you cannot identify the boundary of a frame without understanding

Perhaps the masking should be done into the frame Application data
field? This is: client-to-server frame would contain masking in the
data, instead of masking the whoole frame as it is specified in
draft-04.
Would it be better?

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Fri, 28 Jan 2011 14:00:28 +0100

2011/1/28 Andy Green <[email-masked]>:
> Not sure if I get your issue... the masking nonce comes in the clear as the
> first 4 bytes of the packet.
>

Ok, understood. Thanks.

> disabled it want to see included, whether it is useful or not ie, "masking".

This wouldn't occur if browser vendors wouldn't implement the draft
when it's still unstable. I strongly can't understand how the browser
vendors have decided to implement an "in-progress" draft so far from
being stable. Neither I can't understand that there are already
commercial products based on websockets. It's annoying IMHO.

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Fri, 28 Jan 2011 14:04:28 +0100

2011/1/28 Andy Green <[email-masked]>:
> Now the goal is keeping the effort to have websockets at all alive by piling
> in whatever the browser vendors that disabled it want to see included,
> whether it is useful or not ie, "masking".

draft-04 says:

   Frames sent from the client to the server are masked to
   avoid confusing network intermediaries, such as intercepting proxies.

For sure I miss something, but I cannot understand how a masked frame
avoids such problems in intermediaries while non mased frames don't
avoid it. At the end, a frame (as defined in 04) contains various
bytes at the beginning which make impossible for an intermediary to
interpret such data is "more HTTP requests", am I wrong?

Which is the real advantage of masking? shouldn't the draft describe it?

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Andy Green <[email-masked]>
Date: Fri, 28 Jan 2011 13:04:53 +0000

On 01/28/11 12:55, Somebody in the thread at some point said:
> 2011/1/28 Andy Green<[email-masked]>:

That's what Greg has been suggesting for some time; it got somewhat lost 
in the "we need masking" / "we don't need masking" debate.  I think it 
would be better to do that.

The political problem is a lot of funny claims were made about how 
dangerous it is to allow even just a few bytes controlled by the client 
to come from the client, through any intermediaries, to the server.  For 
example if GET appears even after GB of garbage through a websocket 
connection was held by some to be deadly for some (unidentified and so 
theoretical) intermediaries.

In the situation you describe, at least 8 bytes of the header can 
contain whatever you want just by setting the long length and it goes 
out unmunged.  That will likely lead some people to say it is a security 
problem (to exactly what, has not been described).

-Andy

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Fri, 28 Jan 2011 14:10:28 +0100

2011/1/28 Andy Green <[email-masked]>:
> That's what Greg has been suggesting for some time; it got somewhat lost in
> the "we need masking" / "we don't need masking" debate.  I think it would be
> better to do that.
>
> The political problem is a lot of funny claims were made about how dangerous
> it is to allow even just a few bytes controlled by the client to come from
> the client, through any intermediaries, to the server.  For example if GET
> appears even after GB of garbage through a websocket connection was held by
> some to be deadly for some (unidentified and so theoretical) intermediaries.
>
> In the situation you describe, at least 8 bytes of the header can contain
> whatever you want just by setting the long length and it goes out unmunged.
>  That will likely lead some people to say it is a security problem (to
> exactly what, has not been described).

Even when using masking, a malicius client can send literal "GET
/xxxxx" as the first bytes of the stream (after the handshake), so
what does masking avoid? an intermediary proxy still would read such
"malicius" clear GET sent fom the client after the WS handshake.

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Andy Green <[email-masked]>
Date: Fri, 28 Jan 2011 13:14:39 +0000

> "malicius" clear GET sent fom the client after the WS handshake.

That is true.

But to be fair, Javascript can't do that since it doesn't know the nonce 
and masking key.

Although I agree, if that vulnerable intermediary exists, he is 
vulnerable to the same sequence of packets via websockets or something else.

-Andy

---

From: Joe Mason <[email-masked]>
Date: Fri, 28 Jan 2011 11:36:00 -0500

> -----Original Message-----
> From: [email-masked] [mailto:[email-masked]] On Behalf Of
> Iñaki Baz Castillo
> 

A fully malicious client will not be running behind corporate firewalls.  The attack we are trying to defend from is a malicious script running in a trusted browser behind the firewall.  This script can only manipulate the unmasked data, not the protocol itself.

Joe

---------------------------------------------------------------------
This transmission (including any attachments) may contain confidential information, privileged material (including material protected by the solicitor-client or other applicable privileges), or constitute non-public information. Any use of this information by anyone other than the intended recipient is prohibited. If you have received this transmission in error, please immediately reply to the sender and delete this information from your system. Use, dissemination, distribution, or reproduction of this transmission by unintended recipients is not authorized and may be unlawful.

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Fri, 28 Jan 2011 18:39:57 +0100

> A fully malicious client will not be running behind corporate firewalls.  The attack we are trying to defend from is a malicious script running in a trusted browser behind the firewall.  This scrip…

Ok, but how to defend from a malicius ActionScript code (a .swf file)
which opens a TCP connection and behaves as a WS client?

-- 
Iñaki Baz Castillo
<[email-masked]>

---

From: Joe Mason <[email-masked]>
Date: Fri, 28 Jan 2011 12:43:28 -0500

> From: Iñaki Baz Castillo [mailto:[email-masked]]
> 

Malicious ActionScript code doesn't need to fake being a WS client to perform a cross-protocol attack - it can perform a cross-protocol attack directly.  If administrators are worried about this they need to ban Flash or pressure Adobe to fix Flash's security holes.  We are only concerned with fixing WS security holes so that administrators who ban Flash don't have to ban WS as well.

Joe

---

From: Greg Wilkins <[email-masked]>
Date: Sat, 29 Jan 2011 10:31:41 +1100

On 28 January 2011 23:43, Andy Green <[email-masked]> wrote:
> I didn't appreciate this was behind your pushing masking-as-an-extension,
> but of course that makes sense to subordinate it to the header.

It is one of the prime reasons behind my push for
masking-as-an-extension - but there are other reasons such as agility.

Note also that if there is significant opposition to
masking-as-an-extension, then there is also a middle ground, where the
masking key is the first 4 bytes of the frame payload.  This option is
acceptable (but is really just a special case extension, and I hate
special cases).

cheers

---

From: Willy Tarreau <[email-masked]>
Date: Sat, 29 Jan 2011 08:09:20 +0100

> interpret such data is "more HTTP requests", am I wrong?

No, you're perfectly right. It was suspected that *some* poorly coded
caching intermediaries would be able to skip the bytes they don't
understand until they can match an HTTP request. Since the debate between
those who claimed they surely exist and the ones who claim they surely
don't exist could not come to an end, masking was proposed as a way to
get everyone agree on a middle position.

I really invite you to read the list archives of the last 2-3 months,
you'll get better background.

> Which is the real advantage of masking? shouldn't the draft describe it?

The principle is to prevent the client from sending a controlled string
that can look like an HTTP request. In theory, escaping CR/LF or encoding
all the stream (eg: base64) was enough for this but it was also difficult
to implement and would have implied additional bandwidth overhead.

The advantage of masking is that the client side application does not know
the key, which is a random that is generated just before the data is sent
over the wire. So the client cannot decide what the on-wire data will look
like. Of course, random means that once in a while the key itself could look
like the beginning of a request. But the chances are low enough so that this
does not become an easily exploitable attack vector.

Again, all this has been long discussed, so do not hesitate to consult the
list archives.

Regards,
willy

---

From: Iñaki Baz Castillo <[email-masked]>
Date: Sat, 29 Jan 2011 13:12:17 +0100

> you'll get better background.

Ok, I'll check them. I've arrived a bit late to this maillist :)

> Again, all this has been long discussed, so do not hesitate to consult the

Thanks a lot for the explanation.

-- 
Iñaki Baz Castillo
<[email-masked]>