Subject: [hybi] Insight you need to know: Browsers are at fault when servers crash

From: Mike Belshe <[email-masked]>
Date: Thu, 22 Jul 2010 17:04:24 -0700

Even after all of the writeups from Maciej and Adam, I didn't fully
understand the attack they are working to prevent; well - I understood the
attack, but I thought it was ridiculous.  (I want to eliminate the
round-trip of the handshake, so I don't like having to do it synchronously)

I had a brief chat with Adam, and he schooled me on a few things.  This
information is probably all contained in the other threads, but here it is
again, for dummies like me...

The key insight I was missing is that *browsers are at fault when your
server crashes*.  What?  How can this be?  Browsers have to fix all server
bugs?  That's retarded!   Of course browsers don't have to fix them.  But we
do need to avoid opening new attack vectors.

The browser opens network connections on behalf of the user.  A web page can
embed links and script which cause the browser to open links to foreign
sites on any port.  If those servers are poorly implemented, and an attacker
sends the right web request their way, they might crash.  Your natural
instinct, of course, is to tell them to fix the server, which you should.
 But, what if some bad guy convinces a bunch of users at Innotech.com  to
click a link which causes the internal print server to die?  Pretty soon,
the browser which allows this to happen gets banned from the organization.
 This is why browsers today implement port blocking to prevent access to
standard ports.  But it's a pretty weak security.

Fortunately, most traffic from the browser is not very interesting - its
just web stuff, and unlikely to cause a random server to crash.   But in
cases where we forward user content directly onto the network, we need to
take more care.  This is the case for WebSockets.  If we allow sending of
WebSockets data to random servers, they may crash.  And yes, that is the
browser's fault.  You can disagree with this notion, but the browser vendors
don't.  The browser vendors don't want their browsers banned, and will
implement mechanics to ensure it doesn't happen to them.  From the WebSocket
protocol perspective, this means we probably just need to accept that as a
requirement.

At this point, I'm almost 100% in agreement with Adam.   The problem is that
even if WebSockets shields the user's network from this attack, HTTP POST
does not.  Attackers can already do almost all of this.  Adam points out
that it is possible that some servers would be immune to an attack that
starts with "POST..." yet vulnerable to the WebSockets request.  I think
this is a very small window.  (POST attack documented here:
http://www.remote.org/jochen/sec/hfpa/hfpa.pdf)

I believe Adam is going to send out a proposal on how to encrypt all data,
which removes the ability for the attacker to force the browser to forward
arbitrary bytes.  And he can do this in a way without a round-trip.  But we
don't have any fully baked 0-RTT proposals for upgrading to a WebSocket over
port 80 anyway, so this is largely academic.  But it's still cool.

Mike

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 26 Jul 2010 10:07:09 +1000

Mike,

thanks for translating the intent of the browser dudes and explaining why
they are so concerned about this issue.

I am certainly not opposed to taking measures to ensure that websocket is
not a easy-touch for attackers to use against other protocols and also to
make it more robust against attacks itself.    I think these are reasonable
requirements.

However, I still don't see why the only acceptable solution to these
concerns has to be a rigid non compliant HTTP handshake with space counting
and unframed bytes on the wire?

I think this WG has to clearly accept the concerns of browser vendors and
make sure that the requirements clearly capture them.     But in return, the
browser vendors have to accept that there is more than one way to skin a
cat, and perhaps we can consider alternative solutions than the one that is
currently causing significant objections and real world problems.

cheers

---

From: Maciej Stachowiak <[email-masked]>
Date: Sun, 25 Jul 2010 18:45:24 -0700

On Jul 25, 2010, at 5:07 PM, Greg Wilkins wrote:

> Mike,
> 
> thanks for translating the intent of the browser dudes and explaining why they are so concerned about this issue.
> 
> I am certainly not opposed to taking measures to ensure that websocket is not a easy-touch for attackers to use against other protocols and also to make it more robust against attacks itself.    I think these are reasonable requirements.
> 
> However, I still don't see why the only acceptable solution to these concerns has to be a rigid non compliant HTTP handshake with space counting and unframed bytes on the wire?
> 
> I think this WG has to clearly accept the concerns of browser vendors and make sure that the requirements clearly capture them.     But in return, the browser vendors have to accept that there is more than one way to skin a cat, and perhaps we can consider alternative solutions than the one that is currently causing significant objections and real world problems.

>From the perspective of a browser implementor:

(1) I definitely don't think that the current draft WebSocket protocol is the only possible effective defense against cross-protocol attacks.
(2) If anything, I'm not sure that it is effective enough.
(3) I believe there have been proposals made that are more effective at mitigating cross-protocol attacks than the current draft, such as the TLS next protocol mechanism. However, TLS-only has its own downsides.

Regards,
Maciej

---

From: Mike Belshe <[email-masked]>
Date: Sun, 25 Jul 2010 21:00:16 -0700

On Sun, Jul 25, 2010 at 6:45 PM, Maciej Stachowiak <[email-masked]> wrote:

> (1) I definitely don't think that the current draft WebSocket protocol is
> the only possible effective defense against cross-protocol attacks.
> (3) I believe there have been proposals made that are more effective at
> mitigating cross-protocol attacks than the current draft, such as the TLS
> next protocol mechanism. However, TLS-only has its own downsides.
>

Adam has also suggested encrypting the channel.  Even without TLS, this
would go a long way toward preventing attackers from sending particular byte
patterns over the wire, and could probably be done without adding
round-trips.

Mike

---

From: John Tamplin <[email-masked]>
Date: Mon, 26 Jul 2010 00:22:11 -0400

> patterns over the wire, and could probably be done without adding

Would it be worth having a requirement saying something about a target
platform?  I worry about requiring encryption if we are including embedded
devices as target platforms - any encryption worth doing may be an
unacceptable burden for such platforms.

-- 
John A. Tamplin
Software Engineer (GWT), Google

---

From: Mike Belshe <[email-masked]>
Date: Sun, 25 Jul 2010 21:23:53 -0700

> unacceptable burden for such platforms.

Sounds like what you've said is that Android devices are too wimpy to do
encryption?  I bet the iPhone can handle it.  :-)

Mike

---

From: John Tamplin <[email-masked]>
Date: Mon, 26 Jul 2010 00:36:28 -0400

> encryption?  I bet the iPhone can handle it.  :-)

No, actually I am thinking of even wimpier devices, such as what goes in
some set-top boxes, or various small network attached devices (like
$35 Ethernet switches), etc.  Many of these have some web-based UI, and I
think it would be useful to say decisively whether such platforms are
intended targets for WebSockets.  If they are, I don't think requiring
encryption or compression is acceptable.  I am not saying it is required
that they are supported, just that we need to recognize a decision is being
made there one way or the other and better to make it explicit.

Personally, I think we should make expensive features optional, which means
that a) we have to decide the amateur programmer requirement since that has
previously been used to squelch any suggestion for negotiation and b) these
optional features can't be used for base-level security in the protocol,
such as avoiding cross-protocol attacks.

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 26 Jul 2010 06:54:11 +0200

> such as avoiding cross-protocol attacks.

Well, maybe one solution *could* be to have HTTP-compliant headers
carrying the handshake and an encryption key and the data being
encrypted using a cheap symmetrical algorithm such as AES (or even
cheaper) for which many small implementations already exist ?

It would be a lot cheaper than TLS, would bring the randomness the
security guys are looking for, and allow cheap devices to use it.

And the exchanged key could be the same in each direction and serve
as the nonce as well. The client sends it over a header, expects to
get the same one in response, then both ends use it to exchange
encrypted data over the connection.

Regards,
Willy

---

From: Maciej Stachowiak <[email-masked]>
Date: Sun, 25 Jul 2010 22:02:41 -0700

On Jul 25, 2010, at 9:00 PM, Mike Belshe wrote:

> Adam has also suggested encrypting the channel.  Even without TLS, this would go a long way toward preventing attackers from sending particular byte patterns over the wire, and could probably be done without adding round-trips.

I have a lot of trust in Adam on these kinds of issues, but I'll have to see the details to judge the security.

One question in my mind: would this design plausibly work on a port shared with a non-SSL Web server? Would it be able to go through non-SSL proxies? The inability to do these things is one of the largest downsides of TLS-only. Another downside is the need for a cert, but I imagine there is some way to use TLS without requiring certs.

Regards,
Maciej

---

From: Maciej Stachowiak <[email-masked]>
Date: Sun, 25 Jul 2010 22:03:43 -0700

On Jul 25, 2010, at 9:22 PM, John Tamplin wrote:

> Would it be worth having a requirement saying something about a target platform?  I worry about requiring encryption if we are including embedded devices as target platforms - any encryption worth doing may be an unacceptable burden for such platforms. 

I think the idea here would be to use encryption solely to prevent the attacker from predicting either input or output bytes - in effect to scramble the bits, rather than to provide confidentiality.

Regards,
Maciej

---

From: John Tamplin <[email-masked]>
Date: Mon, 26 Jul 2010 01:12:02 -0400

On Mon, Jul 26, 2010 at 1:03 AM, Maciej Stachowiak <[email-masked]> wrote:

> I think the idea here would be to use encryption solely to prevent the
> attacker from predicting either input or output bytes - in effect to
> scramble the bits, rather than to provide confidentiality.
>

Ineffective encryption doesn't really pose a barrier to producing plain text
to produce a desired cipher text.  Maybe if the key can't be controlled by
the attacker and varies on each packet, but it still seems like you are
playing with fire to say you don't have to use a secure encryption method to
prevent this.

---

From: Maciej Stachowiak <[email-masked]>
Date: Sun, 25 Jul 2010 22:15:12 -0700

On Jul 25, 2010, at 10:12 PM, John Tamplin wrote:

> Ineffective encryption doesn't really pose a barrier to producing plain text to produce a desired cipher text.  Maybe if the key can't be controlled by the attacker and varies on each packet, but it still seems like you are playing with fire to say you don't have to use a secure encryption method to prevent this.

Let's see the details of Adam's idea before we discuss further.

Regards,
Maciej

---

From: Mike Belshe <[email-masked]>
Date: Sun, 25 Jul 2010 22:44:50 -0700

> such as avoiding cross-protocol attacks.

Sorry, I was intentionally jabbing your argument a bit because you're
lumping all encryption together as impossible - and I think that is wrong.
 Even the hardware you mention is capable of basic encryption with
reasonable performance.  But the future hardware, which is really where
websockets could be used, is certainly powerful enough.

Rather than dismissing all encryption proposals up front, I think we should
let proposals come forth as appropriate.  Once a proposal is in hand, we can
weigh whether it really is too slow for reasonable hardware.  Then we'll
probably get into some debate over what is "reasonable hardware".  As you
can probably tell, I think we should design for the future, not design for
the past.

Mike

---

From: Adam Barth <[email-masked]>
Date: Mon, 26 Jul 2010 09:39:22 +0200

> Let's see the details of Adam's idea before we discuss further.

Sorry, I'm slightly distracted at the IETF meeting in Maastricht at
the moment.  Here's the main idea.

Mike wanted to know if there was any way to avoid the round-trip in
the current handshake (I think he views round-trips as quite
expensive).  That leaves us with the following requirements:

1) Zero round trips.
2) We can't send attacker-controlled bytes to the server before the
server proves it understands web sockets.

So how can we start sending content before hearing back from the
server?  The idea is to encrypt the bytes using a key that a WebSocket
server can derive but that look uniformly at random to a non-WebSocket
server.  The easiest way to do this is for the client to send the
server a nonce and then for the client and server to hash that nonce
with a GUID that identifies the WebSocket protocol to generate an
encryption key.  You can then encrypt the attacker's content using
that key (e.g., using AES, RC4, or whatever you like).

Now, I should say this give slightly weaker security properties than a
handshake that waits for the server to opt-in.  For example, if the
server falls over (or generates print jobs) when it receives random
bytes, then we'll still get in trouble, but limiting the attacker to
random bytes reduce the attack surface significantly.  It's probably
also a good idea to limit how much data we're willing to send before
hearing back from the server, but this idea allows some flexibility
beyond zero.

There isn't really any dependency between the format of the handshake
and this trick for saving the round-trip.  You can build the entire
handshake using this idea so that the server only receives
random-looking bytes, but, as Maciej mentions, that makes it difficult
to share with an HTTP server.  You can also this this idea at the end
of an HTTP-like handshake to get started sending data without waiting
for the server to reply.

Adam

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 26 Jul 2010 09:55:49 +0200

Hi Adam,

> of an HTTP-like handshake to get started sending data without waiting

This principle sounds good, and in my opinion would be compatible with
Greg's proposal of putting the nonce in a request header. Basically the
client chooses a random key, advertises it as a nonce and can start
sending data encrypted with that key. It must then check once the server
responds that the hash of the key that confirms its will to use it
for all data past the headers.

Willy

---

From: Roderick Baier <[email-masked]>
Date: Mon, 26 Jul 2010 11:11:54 +0200

> for all data past the headers.

So you want to encrypt the data with a key which was transmitted without 
encryption? Did I get you right?

Best regards
Roderick

---

From: Adam Barth <[email-masked]>
Date: Mon, 26 Jul 2010 11:17:29 +0200

> encryption? Did I get you right?

That's correct.

Adam

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 26 Jul 2010 11:18:18 +0200

> encryption? Did I get you right?

yes, the principle of this "encryption" here is not to provide any
confidentiality but only to scramble the data in a way not controllable
by the client, so that it cannot send arbitrary bytes after the handshake.

And you make me think that we'd better talk about scrambling than
encryption to avoid any mis-understanding resulting in a misuse.

Willy

---

From: Maciej Stachowiak <[email-masked]>
Date: Mon, 26 Jul 2010 02:45:44 -0700

On Jul 26, 2010, at 12:39 AM, Adam Barth wrote:
> to share with an HTTP server.  

Indeed. And it might be hard to share with an HTTPS server too, or go through either HTTP or HTTPS proxies.

> You can also this this idea at the end

Doesn't this second design make WebSocket services potentially vulnerable to cross-protocol attacks from HTTP? It's easy for the HTTP attacker to make up a key and encrypt the attack payload with it, unless the server has to prove it understands WebSocket based on part of the handshake that the in-browser HTTP attacker can't control before it is allowed to process messages.

Regards,
Maciej

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 26 Jul 2010 11:57:04 +0200

> Doesn't this second design make WebSocket services potentially vulnerable to cross-protocol attacks from HTTP? It's easy for the HTTP attacker to make up a key and encrypt the attack payload with i…

In my opinion, if the protocol relies on a real HTTP handshake, what
it will get from an attacker's browser will be a real HTTP request
that it will be able to proceed with. We must keep in mind that WS
servers will be exposed to the net, so while browser-based attacks
can be massive (and imply we should be able to protect against), it
does not mean that the server must end up in an unexpected state.

Also, from what I understood, on a normal browser, the attacker has
no control over the headers. If the key is sent in such headers, an
attacker should not be able to direct browsers at WS servers as those
ones will reject the request as invalid.

Regards,
Willy

---

From: Adam Barth <[email-masked]>
Date: Mon, 26 Jul 2010 12:16:29 +0200

On Mon, Jul 26, 2010 at 11:45 AM, Maciej Stachowiak <[email-masked]> wrote:
> Doesn't this second design make WebSocket services potentially vulnerable to
> cross-protocol attacks from HTTP? It's easy for the HTTP attacker to make up
> a key and encrypt the attack payload with it, unless the server has to prove
> it understands WebSocket based on part of the handshake that the in-browser
> HTTP attacker can't control before it is allowed to process messages.

I don't quite follow.  You seem to be worried about the WebSocket
server being attacked by a non-WebSocket client.  How does that relate
to whether a WebSocket client waits for the server to acknowledge?

Adam

---

From: Maciej Stachowiak <[email-masked]>
Date: Mon, 26 Jul 2010 03:37:41 -0700

> to whether a WebSocket client waits for the server to acknowledge?

The current design requires the server to fairly thoroughly validate the handshake before it is even possible for it to process messages. A previous design made it easy for the server to ignore the handshake and just start processing messages. If the key for decoding messages is in the HTTP body, or any part of the request that could plausibly be controlled by an attacker, then we are back to that earlier state where it is much easier to accidentally write a vulnerable server. If the key appears in HTTP headers, then some amount of "rigidity" may be required to make it hard to forge it with a non-WebSocket HTTP request.

Regards,
Maciej

---

From: Adam Barth <[email-masked]>
Date: Mon, 26 Jul 2010 12:52:10 +0200

> The current design requires the server to fairly thoroughly validate the handshake before it is even possible for it to process messages. A previous design made it easy for the server to ignore the…

Ah, I understand.  We're worried about the consequences of common bugs
in server implementations.  One approach is to use whatever value the
server would have sent back to the client to verify that the server
understood the handshake as part of the key for decrypting the body.
That way the server is forced to do the same computation, we're just
verifying it's correctness cryptographically.

Adam

---

From: Maciej Stachowiak <[email-masked]>
Date: Mon, 26 Jul 2010 04:35:44 -0700

> verifying it's correctness cryptographically.

The difficulty is that the computation has to validate the HTTP-level handshake, looking at elements that cannot easily be forged, or it suffers from the same problem I described above. If it is derived solely from portions of the request that could be attacker-controlled, then it is predictable to the attacker, so using it as part of the crypto key for the body is no obstacle to injecting chosen plaintext.

This means we'd need something with similar complexity to the current handshake, except we'd have the benefit that the first client --> server message can save a round trip.

On the other hand, using your scheme straight-up without a prior HTTP header is probably safe without any additional rigidity.

Regards,
Maciej

---

From: Adam Barth <[email-masked]>
Date: Mon, 26 Jul 2010 13:43:43 +0200

> On the other hand, using your scheme straight-up without a prior HTTP header is probably safe without any additional rigidity.

Yes, the idea is to save a round trip.  Their are costs, of course,
but Mike asked if was possible.

Adam

---

From: Scott Ferguson <[email-masked]>
Date: Mon, 26 Jul 2010 12:09:38 -0700

> The difficulty is that the computation has to validate the HTTP-level handshake, looking at elements that cannot easily be forged, or it suffers from the same problem I described above. If it is de…
But there are two separate validations: validating the client and 
validating the server. The same computation doesn't validate both at 
once. (It can't validate both at once, because the client validates the 
server but the server validates the client.)

Your proposed attack is the client-validation problem: is the client a 
real websocket client? (where the server is a websocket server.)

Adam's proposal is for the server-validation problem: is the server a 
real websocket server? (where the client is a websocket client.) It 
doesn't address the client-validation problem.

But it's not a flaw in Adam's proposal that it doesn't address the 
client-validation problem. It would only be a flaw if the attack showed 
a weakness in solving the server-validation problem.

(Just to be clear, it's not possible to have both issues in the same 
attack, because a non-websocket client talking to a non-websocket server 
isn't our problem.)
> This means we'd need something with similar complexity to the current handshake, except we'd have the benefit that the first client --> server message can save a round trip.
The client-validation problem could be solved if there are elements in 
the initial request that cannot be forged, as you pointed out. For 
example, if the HTTP method cannot be forged, changing the HTTP method 
to something like "WEBSOCKET" would validate the client as a real 
websocket client.

If the entire request can be forged by a non-web-socket client, then you 
do need a second client response to the server's initial response. If 
the entire request can be forged, the server needs to send a random 
nonce and force the client to compute a hash to prove the client is a 
real client.

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

---

From: Roberto Peon <[email-masked]>
Date: Mon, 26 Jul 2010 16:05:34 -0700

> that key (e.g., using AES, RC4, or whatever you like).
Isn't a client-generated nonce good enough so long as the API user doesn't
have control over it, nor can easily guess it?
This is likely a non-issue if we're waiting for the 100-continue before
sending WS data. If not, it saves a round trip.

-=R

---

From: "Thomson, Martin" <[email-masked]>
Date: Tue, 27 Jul 2010 13:57:39 +0800

Is it also possible that the client can be validated by virtue of it providing and using the nonce?

Given the nature of the protocol, the same key can be used to "randomize" the stream in both directions after the handshake.

This reduces the problem to the one where an attacker coerces the client into providing such a nonce (or having it appear so).  That requires control over the key parts of the handshake.

--Martin

p.s. This problem really needs a concrete mechanism at this stage.  Even an example or two might help.

> -----Original Message-----
> From: [email-masked] [mailto:[email-masked]] On Behalf Of
> Scott Ferguson
> Sent: Monday, 26 July 2010 9:10 PM
> To: Maciej Stachowiak
> Cc: [email-masked]
> Subject: Re: [hybi] Insight you need to know: Browsers are at fault
> when servers crash
> 
> Maciej Stachowiak wrote:
> > The difficulty is that the computation has to validate the HTTP-level
> handshake, looking at elements that cannot easily be forged, or it
> suffers from the same problem I described above. If it is derived
> solely from portions of the request that could be attacker-controlled,
> then it is predictable to the attacker, so using it as part of the
> crypto key for the body is no obstacle to injecting chosen plaintext.
> >
> > This means we'd need something with similar complexity to the current
> handshake, except we'd have the benefit that the first client -->
> server message can save a round trip.
> >
> > On the other hand, using your scheme straight-up without a prior HTTP
> header is probably safe without any additional rigidity.
> >
> > Regards,
> > Maciej
> >