Subject: [hybi] Summary of issues concerning the default masking algorithm

From: Bruce Atherton <[email-masked]>
Date: Sun, 09 Jan 2011 16:17:02 -0800

Now that masking is officially going to be part of the protocol, I for 
one would find it useful to have all the concerns of the masking 
algorithm in one place to make it easier to reason about. I realize that 
much of this has already been discussed in various threads in all kinds 
of messages and that some (though I do not think all) consider the 
decisions on the algorithm pretty much made, but I think it would be 
easier to reason about and be certain we have consensus on them if the 
information could be gathered in a single thread.

Here is my understanding of the current state of issues around the 
masking algorithm. Please feel free to correct me or add more information.

The problems masking is intended to address are:

   1) to prevent an attacker from using a browser to initiate a 
Websocket connection to a vulnerable intermediary or non-Websocket 
server that can be exploited by sending apparent HTTP or elements of 
other protocols in a Websocket frame

and more controversially:

   2) to prevent an attacker from using a browser to open a cross-site 
scripting HTTP connection that emulates a Websocket connection

   3) to prevent potential unknown future attacks using a browser with a 
Websocket connection that can be avoided by disallowing an attacker's 
control of bits on the wire

If there are other problems masking is seen as a solution for, please 
add them. Those are the ones I am aware of.

The most basic masking suggestion I have seen is to provide a per-frame 
random mask that is sent with the frame and XORed with the contents.

The features which have been suggested to enhance this scheme that I 
know of are:

a) The client nonce should influence the mask

b) The server nonce should influence the mask

c) The mask should be kept off the wire by generating the mask using a 
shared secret
   - This means replacing the per-frame mask with a per-frame key used 
in generating the mask
   - the shared secret that has been suggested is a connection key 
generated from the client and server nonce, thus including features a and b

d) The attacker should not only be prevented from controlling the bits, 
but also the pattern of bits

Again there may be other features that have been suggested but those are 
the ones I am aware of.

I'll leave it to the advocates of each of these features to summarize 
the benefits of them that justify their costs, as I don't think I could 
do justice to them. I can make a stab at the costs, though.

For feature a, the only cost I can see is in the increase in complexity 
in generating the mask.

For feature b, there is the increase in complexity in generating the 
mask as well as the fact that you can not send a payload with the 
initial handshake from the client because you do not yet have the server 
nonce.

The principal cost of feature c that I can see is that it stops tools 
like wireshark from being able to decode streams.

The cost of feature d is increased complexity in implementation and 
added computational cost.

Feel free to add to or argue with any of these points. I've tried to 
state things as neutrally as I can.

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 10 Jan 2011 01:24:05 +0100

Bruce,

there are also proposed  features of:

  e) masking the framing as well as the payload.

  f) making masking use the current frame extension mechanism

 g) make masking be a negotiated extension (either to turn it on or off)

---

From: Bruce Atherton <[email-masked]>
Date: Sun, 09 Jan 2011 17:47:18 -0800

Hi, Greg.

These seem to be questions about where to apply masking rather than 
issues with the masking algorithm itself. I was thinking they deserve 
their own thread, but if you think they are better discussed here then 
let us consider the costs and benefits of each, and where people think 
the right trade-off can be found.

---

From: Bruce Atherton <[email-masked]>
Date: Sun, 09 Jan 2011 18:32:25 -0800

Here is where I currently stand on the trade-offs in costs versus 
benefits from the 4 features I've listed. This is absent an actual list 
of the benefits being provided by anyone else nor of any feedback on the 
costs, so it is perhaps premature. This is my current perspective, though.

> For feature a, the only cost I can see is in the increase in 
> complexity in generating the mask.

I don't understand the benefit, but the cost seems so minimal I can't 
see why it would be a problem.

> initial handshake from the client because you do not yet have the 
> server nonce.

The benefit I can see to this is that it prevents an attacker from 
faking a websocket connection by laying down what looks like perfectly 
valid websocket frames. Without the server nonce, this won't be possible 
because the masks generated by the attacker will not show the influence 
of the server nonce on them.

The cost seems pretty minimal to me in order to get that guarantee.

> like wireshark from being able to decode streams.

The benefit that I can see with this feature is that it will force the 
server to pay attention to whether the server nonce was used to generate 
the mask, since the server will need to generate the mask itself by 
using the nonce.

The cost of losing the ability to decode streams is, to me, extremely 
high. It is beyond that, it is painful. When I have to debug a network 
issue in a customer's environment, a problem that would take me a few 
hours with a decoded stream jumps to days or even weeks. What is worse 
is that it is often difficult if not impossible to demonstrate to the 
customer when the issue is not with my application. Although I can 
create multitudes of logs that show all the bits my application receives 
and sends, the customer has no way of knowing whether there are bits 
that are not logged because they are dealt with via another code path.

Also, without having a decoded stream it can be very difficult to 
pinpoint where in a customer's network the actual problem is arising. 
This is another case of "not my fault, still my problem". If my 
application doesn't work in the customer's environment then I lose the 
customer. Whenever I have to deal with an encrypted stream I groan in agony.

So the benefits would have to be pretty high for me to consider this a 
good trade-off to make. The benefit I listed above doesn't make it.

> added computational cost.

I have no idea what the benefit to this is, but I trust that the people 
arguing about it have a reason for believing there is one and I hope 
they describe it here in simple words I can understand.

I find it interesting how we have gone from requiring the simplest of 
possible Websocket servers to ones that require teasing out highly 
optimized versions of HMAC from other libraries. I think that keeping 
things as simple to implement as possible is the sensible thing to do, 
but I am uncertain about what definition to give "possible".

I don't have the expertise to properly evaluate the computational cost. 
Willy seems to know a lot about the subject, though, so he has my proxy. 
If Willy is convinced it is worth it then so am I.

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 10 Jan 2011 07:20:51 +0100

On 10 January 2011 02:47, Bruce Atherton <[email-masked]> wrote:
> Hi, Greg.
>
> These seem to be questions about where to apply masking rather than issues
> with the masking algorithm itself. I was thinking they deserve their own
> thread, but if you think they are better discussed here then let us consider
> the costs and benefits of each, and where people think the right trade-off
> can be found.
>

I think they are very closely bound.

If masking uses a crypto algorithm, then having the flexibility of an
extension to change the algorithm is more important.
If masking is just XOR of a random mask, then perhaps it such agility
is less important.

If masking is stream based, then masking the framing becomes even more
of a PITA that it would be otherwise.  Multiplexing become very
complex and Debugging tools would not even be able to identify frames
without tracking the entire stream.

regards

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 10 Jan 2011 07:39:30 +0100

> that are not logged because they are dealt with via another code path.

+1, that's an experience I share all the day too the other way around,
proving from network captures that the application is faulty, despite
how expensive it was !

Willy

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 10 Jan 2011 15:07:50 +0100

> a) The client nonce should influence the mask

PROS: None that I can think of over a good random mask
CONS: Makes the mask stream dependent, preventing debugging of partial
streams.  If masking is applied to framing, this make multiplexing and
debugging significantly more complex.

> b) The server nonce should influence the mask

same as a)

> c) The mask should be kept off the wire by generating the mask using a

same as a)

> d) The attacker should not only be prevented from controlling the bits, but
> also the pattern of bits

Not sure what this means?  If it is referring to using and algorithm
such that the a mask pattern does not repeat

PROS: Increases the data that must be sent to achieve some plain text
from a huge amount to a humongous amount.
CONS: Only increases the data that must be sent and does not actually
prevent any clear text data.

> e) masking the framing as well as the payload.

PROS: none that I can think of
CONS: makes decoding framing more complex.  Means that all WS aware
code must implement the specific masking algorithm, which effectively
means that it will never be able to be turned off.

> f) making masking use the current frame extension mechanism

PROS: Puts masking inside the frame, so avoids CONS of e).   Validates
the extension mechanism. Allows intermediaries that do not care about
payload to ignore masking.
CONS: None that I can think of.

> g) make masking be a negotiated extension (either to turn it on or off)

PROS: Allows crypto agility. Allows no masking deployments.
CONS: An extension negotiation mechanism will need to be implemented.
Slightly more verbose handshake.

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 10 Jan 2011 07:43:50 -0800

> proving from network captures that the application is faulty, despite

Building tools to process this kind of masked data is trivial. Heck, tools to
decode full SSL aren't even that hard. I know because I've built them.

-Ekr

---

From: Bruce Atherton <[email-masked]>
Date: Mon, 10 Jan 2011 10:44:19 -0800

> decode full SSL aren't even that hard. I know because I've built them.

I don't understand how you can reliably decode the streams with the 
currently proposed masking strategy, but I am ready to be proved wrong.

First, let me more fully flesh out what is required for these debugging 
sessions. Bidirectional protocols tend to be much longer lived than 
others. It is not unusual to get ones that last hours or days or weeks, 
or even ones that only reset when one end or the other does a reboot.

You want to keep your capture logs as short-lived as possible. The 
bigger the capture log is, the more expensive it is to fix the problem. 
They take up time not only in storage space and transfer time, but most 
importantly in time spent analyzing the results. One very common idiom 
for keeping the capture logs short is to identify an action that 
triggers the bug, have a customer start the capture, perform the action, 
give enough time for the bug to manifest, and stop the capture. You 
still may have tens of thousands of sessions to wade through and filter 
as best you can, but at least you can be fairly sure the one you want is 
in there somewhere.

Ok, so given all that, how do we deal with a connection that only sends 
shared secret information at the beginning of the connection when you 
are less likely to be doing a capture?

Well, I guess the shared secret could be repeatedly sent out 
periodically during the life of the connection. But how often? 30 
seconds can be a whole lot of capture on a busy system. Every 2 seconds? 
What does that do to mobile batteries, or the bandwidth usage of mobile 
users?

Then again, you could put the shared secret on every frame. That would 
prevent the mask itself from being on the wire and would allow capture 
tools to decode the stream. But it would also bulk up the data sent with 
every frame, which I think many would find undesirable.

And what would all this data on the wire bring you? A guarantee that 
naively implemented servers couldn't ignore the influence of the server 
nonce on the mask? Have you seen the complexity of the masking being 
proposed? I think we are well past the point where there are going to be 
naively implemented servers. We left simple implementations as a design 
concern in a roadside grave 100 miles back.