Subject: [hybi] Computation part of handshake

From: Silvio Ventres <[email-masked]>
Date: Fri, 25 Feb 2011 18:44:31 +0200

Hello, Ian.

Since both prior threads have been swamped in meta-discussions,
starting a new thread to clear up the question.

Based on your (Ian Fette's) comments, the handshake is meant to serve 2 goals:

1. Prevent WS client from _mistakenly_ identifying an HTTP server as
WS-compliant
2. Prevent WS client from _intentfully_ communicating with an HTTP
server via WS protocol.

The first goal is indeed a good idea to prevent confusing WS clients
connecting to legacy HTTP servers.
It is accomplished by using the WS-specific "magic string" and "echo procedure".

The second goal is argued to protect from some kind of an attack.
Since it is not readily apparent what attack vector is being
considered here, and, indeed,
the request from the point-of-view of HTTP server is a standard HTTP request,
this is a formal request:

REQUEST: Please provide an example of an actual attack scenario
possible in case WS does not implement computational-handshake.

Unless such attack scenario cannot be provided, strongly recommend:

RECOMMEND to remove the handshake-computation feature from the specification.

--
 silvio

---

From: John Tamplin <[email-masked]>
Date: Fri, 25 Feb 2011 12:00:57 -0500

> 2. Prevent WS client from _intentfully_ communicating with an HTTP

This is actually a whole family of cross-protocol attacks.  Using
WebSockets to avoid the same-origin restrictions of HTTP as accessed
from a browser is just one category of this attack.  As an example of
the sort of cross-protocol attacks we want to avoid, see where HTTP
POST was used to send spam via vulnerable SMTP servers.  Imagine if
hostile JS could communicate with an SMTP server to send spam just by
browsing to the attacker's web page.

> RECOMMEND to remove the handshake-computation feature from the specification.

As a newcomer, constantly asking us to provide you with proof of
everything that has been decided so far is getting tiresome.  Do you
really think everyone involved here just decided to make things up to
put in the protocol and that someone showing up at the last minute is
the only one that can point out these obvious flaws?  Additional
contributions are certainly welcome, but so far the tone has simply
been "this is ridiculous and I don't see why it is there, please
remove it".

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

---

From: Willy Tarreau <[email-masked]>
Date: Fri, 25 Feb 2011 18:02:14 +0100

> possible in case WS does not implement computational-handshake.

It prevents a client from accidentely validating a handshake with a
caching intermediary which would have cached a WS server's response.

> RECOMMEND to remove the handshake-computation feature from the specification.

Please keep in mind that many more combinations of compliant, buggy, broken
and malicious clients, intermediaries and servers have been studied to reach
what is written in the draft. You won't make it change just because it does
not optimally satisfy your specific needs without considering all the traps
we've tried to avoid.

However you may help things change by proving yourself that the
simplifications you're proposing are possible because they're now already
covered by something else in all possible scenarios. But the number of
possible scenarios is huge, it's not just a compliant browser and a compliant
server.

Regards,
Willy

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Fri, 25 Feb 2011 18:14:26 +0100

>possible in case WS does not implement computational-handshake.

The scenario is quite simply this:

  1. A WS client sends X to a non-WS server to make a WS connection
  2. The server sends f(X) to the client to confirm the connection
  3. The client sends Y to the server which results in harm

This is prevented if the client cannot be made to send Y or if f(X) can
not be computed by servers with no knowledge of Websockets, within some
reasonable limits. The Working Group has decided to do both, making it
hard to send some attacker-chosen Y by masking with a random value, and
making it very unlikely that f(X) is already implemented somewhere by
making f(X) complicated and Websocket-specific.

If f(X) was just something like "echo some part of X" or "send a magic
string independent of X" there would be little reason to believe there
is not now nor is there likely to be a server that sends out f(X) with-
out explicitly choosing to do so, since we know there are servers that
can be made to echo parts of some input.

Again, if you have some suggestion how the specification can communicate
this better, please share it, I certainly agree that these things need
to be clear from the specification and agree they can be summarized
easily without asking people to read over 6,000 mostly unrelated emails.
-- 
Björn Höhrmann · mailto:[email-masked] · http://bjoern.hoehrmann.de
Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de
25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/

---

From: Silvio Ventres <[email-masked]>
Date: Fri, 25 Feb 2011 19:16:45 +0200

> caching intermediary which would have cached a WS server's response.

The goal (2) does not prevent a caching intermediary from caching the
response in any case.

So the attack scenario you provided has to do with the "echo" being a
static value.
To prevent it, you can add a dynamic part to the handshake, for
example, a timestamp
that should be echoed by the remote endpoint.
There is still no need for the computation here.

--
 silvio

---

From: Silvio Ventres <[email-masked]>
Date: Fri, 25 Feb 2011 19:25:51 +0200

>  3. The client sends Y to the server which results in harm

If the step "3" results in harm, and the server is a non-WS server,
what prevents
the JS attacker from simply issuing an HTTP GET request to the same server ?

If the attacker can force the remote end-point to echo values of his choice,
then similarly, he can precompute the correct handshake answer and force
the remote endpoint to echo that, making it look as if the computation
took place.

--
 silvio

---

From: Willy Tarreau <[email-masked]>
Date: Fri, 25 Feb 2011 18:29:58 +0100

> The goal (2) does not prevent a caching intermediary from caching the

If you're talking about the Sec-WebSocket-Accept header, then it's a hash
of the Sec-WebSocket-Key provided by the client. The client is supposed
to use a random key, so there is almost no chance that the same key will
be emitted twice, so a cache will return a hash from a previous key, which
the client will detect.

Willy

---

From: Silvio Ventres <[email-masked]>
Date: Fri, 25 Feb 2011 19:34:54 +0200

> be emitted twice, so a cache will return a hash from a previous key, which

The question is, why use hashing at all ?
Use some simple math, why add complexity ?

--
 silvio

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Fri, 25 Feb 2011 18:54:33 +0100

>the JS attacker from simply issuing an HTTP GET request to the same server ?

The bytes on the wire are a bit different for HTTP GET requests and he
would, generally speaking, have less control over them, so it is quite
possible an attacker could do something with one method but not the
other.

>the remote endpoint to echo that, making it look as if the computation

As I recall, the client picks a random value the server needs to mani-
pulate after the JavaScript code asked the browser to attempt making a
Websocket connection. If the random number generator is unpredictable
to the script, the attacker cannot pre-compute the response.
-- 
Björn Höhrmann · mailto:[email-masked] · http://bjoern.hoehrmann.de
Am Badedeich 7 · Telefon: +49(0)160/4415681 · http://www.bjoernsworld.de
25899 Dagebüll · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/

---

From: Silvio Ventres <[email-masked]>
Date: Fri, 25 Feb 2011 20:36:32 +0200

> possible an attacker could do something with one method but not the

Arguably, it's a _very_ questionable attack vector, as if the attacker
can make the server behave
as WS, he can make the server behave as HTTP also, or any other
protocol, and cause similar harm.

Anyway, understanding that you don't want the attacker from within a
JS script to be
able to make the server pass the handshake, without looking into why
the server would allow that.

A valid point made by someone else was that a caching intermediary
might cache the WS server
response and the client needs to have a way to know such from a real
response. _That_ requires some
dynamic challenge/response from WS in the browser to the server.

But to do that you don't need to add computation complexity. Indeed,
hashing is not a free operation.

--
 silvio

---

From: Willy Tarreau <[email-masked]>
Date: Fri, 25 Feb 2011 20:04:19 +0100

> dynamic challenge/response from WS in the browser to the server.

Ah, at last !

> hashing is not a free operation.

Maybe cheaper alternatives can be proposed, as long as the purpose is
as efficient. The hash only applies to first incoming connections, so
its cost is estimated low, compared to the cost of accepting a new
connection. We've fought on some proposals where it was needed to
compute a hash on each frame, and still some members considered it
not too expensive. So probably that one hash per connection is cheap.

Are you expecting to process millions of new connections per second
on a sub-$1K system ? If so, I'm wondering what usage you're targetting,
maybe you need to use native TCP instead for your application ?

Willy

---

From: Silvio Ventres <[email-masked]>
Date: Fri, 25 Feb 2011 22:35:49 +0200

> It's not a matter of being more or less secure but of safely ensuring
> that the response matches the request. I'm sure that for most server-side
> implementors, running a SHA-1 on a small string is much easier to implement
> than to perform multiplications or such operations.

Willy, the multiplication is simple multiplication, not some complex math.

Basically, instead of putting a function that does
some_lib_SHA1("ws-magic+server-challenge"),
you do (server_challenge + 192739733), or (server_challenge * 192763 mod 2^^32),
with 192739733 being some number
specified statically in the spec.

> Probably that a simple checksum would have been OK too, but those functions
> are rarely present in common frameworks while SHA-1 is available everywhere.
> So in my opinion it's really just a matter of making it easier for the
> developper. Fell free to propose something easier and at least as safe, and
> to defend it here, maybe it could be improved.

What "those functions" ?
Addition, multiplication and mod functions are basic stuff, no
libraries needed :)

> Not at all, I too am doing that all my time from dirt-cheap hardware. I'm
> just comparing numbers. People running millions of connections per second
> might be as big as Google and still could run this hash on a sub-$1K server,
> which itself could not stand the network traffic at all. Imagining that sites

Yes, but if they can do 10 Million connection handshakes per second compared
to 1 Million, why would you want to limit them to 1 Million ?
And, yes, hash is an expensive function.

> "more complex" than what alternative ? If an alternative is as easy to
> implement, as safe and cheaper, surely most people will accept it, feel
> free to present it.

Mod-Multiplication is easier to implement and cheaper.
It's on the same level of safety regarding the target goal, which is
to add dynamic element to the handshake to prevent cached replies.

--
 silvio

---

From: Dave Cridland <[email-masked]>
Date: Fri, 25 Feb 2011 21:50:25 +0000

> Use some simple math, why add complexity ?

Just thought I'd pick up on this.

It's just a very common method of taking an input and producing an  
output that is both verifiable and very unlikely to clash (ie,  
collide) with an output for a different input, even if the inputs are  
similar.

It's *really* hard to find "simple math" that gets even close to  
this, and hashes are very widely implemented even on hardware, and as  
such a useful building block. In addition, one hash operation is  
pretty cheap, these days.

Dave.
-- 
Dave Cridland - mailto:[email-masked] - xmpp:[email-masked]
  - acap://acap.dave.cridland.net/byowner/user/dwd/bookmarks/
  - http://dave.cridland.net/
Infotrope Polymer - ACAP, IMAP, ESMTP, and Lemonade

---

From: Silvio Ventres <[email-masked]>
Date: Sat, 26 Feb 2011 00:49:43 +0200

> It's just a very common method of taking an input and producing an output
> that is both verifiable and very unlikely to clash (ie, collide) with an
> output for a different input, even if the inputs are similar.

But there is no requirement for the results to be cryptographically hashed.

The only requirement is to make the handshake in some way dynamically
depend on the challenge provided by the connecting party.
Indeed, even the requirement above is only applicable to the _clients_
connecting to _servers_, as the problem being prevented lies in caching proxies.

Thus, if the challenge issued by the client is _already_ random, there is
no need to "randomize" by hashing on the server side. Just make sure
the algorithm is easy to implement and verifiable.

Such an algorithm may be:
client_challenge XOR ws_static_32bit_integer
client_challenge * ws_static_32bit_integer mod 32 bit

or, even

client_challenge + ws_static_32bit_integer mod 32 bit

The point here is that the probability of any of these being correct
answers for a different challenge is NULL.
Indeed, take the case of "+". What is the client_challenge that would
be answered
correctly by the response 123456789 ? only (123456789 -
ws_static_32_bit_integer).

Hashing has no place here, serves no purpose and only makes the
handshake more complex.

--
 silvio

>
> It's *really* hard to find "simple math" that gets even close to this, and
> hashes are very widely implemented even on hardware, and as such a useful
> building block. In addition, one hash operation is pretty cheap, these days.
>
> Dave.
> --

---

From: Ian Fette (イアンフェッティ) <[email-masked]>
Date: Fri, 25 Feb 2011 15:27:38 -0800

> Hashing has no place here, serves no purpose and only makes the

This is not getting anywhere. Hashing is straight forward, well understood,
and relatively cheap compared to the overall cost of establishing a
connection. Please stop wasting everyone's time. You are not contributing
anything useful to this group.

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

---

From: Silvio Ventres <[email-masked]>
Date: Sat, 26 Feb 2011 01:50:21 +0200

> anything useful to this group.

Ian, as was shown in the previous post, hashing serves no purpose here.
Why are you comparing it to the overall cost and not to cost of
alternative solutions ?

Why would you force the server implementer to include an MD5 library
_just_ for the
WS handshake, although it serves no purpose ?

Does it have any benefits over an operation of addition,
multiplication, even XOR ?

--
 silvio

---

From: Silvio Ventres <[email-masked]>
Date: Sat, 26 Feb 2011 02:06:18 +0200

>> anything useful to this group.

Actually, Maciej said himself in the post:
http://www.ietf.org/mail-archive/web/hybi/current/msg01198.html
"There is no need for the hash to be cryptographically strong."
and then:
"the hash used here is MD5; we could use a weaker hash that is faster
to compute however".
The actual procedure is not meant to hash anything, but simply make
the response differ from the challenge
in a predictable and verifiable way.
Any operation such as addition, multiplication or XOR can do that.

How did this become an SHA-1 when Maciej accepted that even MD5 was an
overkill ?
Why would you want to burden both the client and a server with
computations that have no practical benefit?

--
 silvio

---

From: Willy Tarreau <[email-masked]>
Date: Sat, 26 Feb 2011 01:54:07 +0100

> How did this become an SHA-1 when Maciej accepted that even MD5 was an

As some of us already told you, simply because it appeared simpler
without any noticeable additional cost. Hashes were used at several
places anyway when this choice was made.

> computations that have no practical benefit?

Why don't you propose an alternative that looks like something everybody
can understand and discuss, with a minimum analysis of benefits vs risks
compared to what it's supposed to replace ? I mean, something concrete,
not just random ideas with and sentences all beginning with "Why".

There's nothing wrong with proposing argumented improvements, the WG is
there for this reason. What's wrong is to constantly harrass participants
asking them to justify some choices that were made months ago and that
you don't accept.

Maybe your idea will be accepted, maybe it will be rejected with strong
arguments but at least it will have been developped and discussed.

Willy

---

From: Silvio Ventres <[email-masked]>
Date: Sat, 26 Feb 2011 20:56:37 +0200

> not just random ideas with and sentences all beginning with "Why".

Well, here's a proposition:
A static 32-bit number is added to the client's challenge (whether
called Sec-Websocket-Key or
Sec-Websocket-Challenge) and returned in the server response.
That is a much simpler operation than SHA-1, and provides exactly THE SAME
guarantees regarding unique mapping to a specific server challenge.

Hash randomizes the output, but it's not needed here.
Whether challenges (x) and (x+1) produce completely different
and unrelated outputs (y) and (z) or outputs or easily-related
(y) and (y+1) makes no difference from the protocol perspective.
The fact that the outputs are different and verifiable is all that matters.

If the output has same amount of bits as input, for each unique
challenge, the server will always provide a different response.

SHA-1 is an overkill. It slows down connection handshake and provides
not benefit as compared to a simple addition, or any other simple function.

--
 silvio