Re: Hello from Mozilla

From: Amos Jeffries <squid3_at_treenet.co.nz>
Date: Wed, 05 Aug 2009 13:42:11 +1200

On Wed, 5 Aug 2009 00:57:18 +0000 (UTC), Ian Hickson <ian_at_hixie.ch> wrote:
> On Thu, 30 Jul 2009, Robert Collins wrote:
>> On Wed, 2009-07-29 at 23:48 +0000, Ian Hickson wrote:
>> >
>> > Surely once the HTTP server has decided that it can Upgrade, it
>> > doesn't actually need to worry about sending back something HTTP-valid

>> > at all, since we can just say the entire connection was always using
>> > the WebSocket protocol, and was never HTTP.
>>
>> 10.1.2 101 Switching Protocols
>>
>> The server understands and is willing to comply with the client's
>> request, via the Upgrade message header field (section 14.42), for a
>> change in the application protocol being used on this connection. The
>> server will switch protocols to those defined by the response's
>> Upgrade header field immediately after the empty line which
>> terminates the 101 response.
>>
>> So the server has to send a response before switching.
>
> The above text has no normative conformance criteria ("the server will"
is
> an informative statement that is unsupported as far as I can tell).

Point to note: if webserver fails to switch the WebSockets handshake to
verify said switch actually occurred will fail. Detecting such bad servers
and acting properly.
If web server successfully switched then WebSockets client needs to handle
the HTTP response correctly and begin to do a WebSockets native handshake
and verify the link is safe _after_ the 101 message is received.

>
> In any case, the WebSocket protocol handshake does do a complete HTTP
> Upgrade including the empty line, it just requires that the handshake be
> done in a particular way. It's "profiling" the HTTP spec.

No, our whole point repeated over and over in different ways is that the
specd description for the upgrade request is _incomplete_. And does not
account for an enormous number of byte-level variations. All of which can
be safely discarded without affecting security.
Being sensitive to whether the server replies "101 Blah" versus "101 blah"
absolutely cripples WebSockets. We want to help you fix this problem.

>
>
>> This is because if it doesn't, how can it say 'I won't upgrade'.
>
> It can just not upgrade. Returning anything but the correct handshake
will
> be treated as a failed connection by the WebSocket client.

Correct.

>
>
> On Thu, 30 Jul 2009, Robert Collins wrote:
>> >
>> > Suppose we had no handshake at all, and that there was no data
>> > framing, so that as soon as we connected to a port, we could send
>> > arbitrary data down.
>> >
>> > A Web page, say evil.example.net, could open a Web Socket connection
>> > to http://www.corp.example.com/, send it a GET request for
>> > /secret-plans, and then forward the contents of the file to a remote
>> > host. If they could then trick someone on example.com's intranet to
>> > look at this file, and assuming www.corp.example.com did nothing more
>> > than rely on connectivitity for authentication (pretty common in small

>> > intranets), then evil.example.net could steal the company's secret
>> > plans.
>>
>> Can't the web page just send an ajax request to corp.example.com anyway?

>
> It can't read the response, no.
>

Can you explain this please?
AFAIK, Sending a request then closing the connection immediately is the
only way said response might be unreadable. I don't understand what you
mean.

>
>> And if it can't, why doesn't the same browser security model prevent
>> websockets being used in the same way?
>
> The same-origin model would prevent any WebSocket traffic at all, since
> it's a different scheme than the document.
>
>
>> > Now, Web Socket has a multi-layered approach to dealing with this.
>> >
>> > - there is the handshake, which requires that the server respond with
a
>> >
>> > very specific set of bytes, thus guaranteeing that the server is in
>> > fact
>> > WebSocket-aware. Any "wildcard" part to this handshake increases the
>> > risk
>> > that there will be a server somewhere that can be tricked. For
example,
>> > if
>> > the handshake were "HTTP" followed by anything followed by
"WebSocket",
>> >
>> > then some HTTP servers could be tricked into doing the handshake --
for
>> >
>> > example, the response to "GET /WebSocket" on the ietf.org host (not
>> > www.ietf.org) includes the word WebSocket in the response.
>> >
>> > HTTP servers aren't the only concern, of course; we want the handshake
>> > to
>> > be as secure as possible against any other protocol that may exist on
>> > any
>> > server that may be deployed. We don't know what's out there
(especially
>> > in
>> > intranets), so the handshake has to be pretty stringent to make it as
>> > unlikely as possible.
>>
>> Dumping the ability to look like HTTP altogether is your best bet IMO:
>> even on port 443. For port 443, someone running a websocket server
>> should just not run an HTTPS server there. Or define port 815 as
>> websocket/s.
>
> Port 815 is the preferred port, but in certain situations, only ports 80
> and 443 are allowed, and port 80 is mitm'ed, so that only leaves 443.
>
> You don't always have the option of using a different host, that's why we

> need to share the port sometimes. (There have also been statements to the

> effect that just sending a new protocol over ports 80 or 443 without
using
> the Upgrade mechanism would be a violation of the semantics of those
> ports.)
>

Understood. However strange protocols (torrent is one example) on port 80
can be detected and dealt with easily.
Something that appears to be perfect HTTP cannot be detected as non-HTTP.
When HTTP operations are done to the traffic it will break badly and in
nasty invisible ways.

>
>> > - there is origin checking and location checking, and the location
>> > checking isn't just an echo of the original request's data. This makes

>> > causing the server to send back particular data harder. (It's also
part
>> > of
>> > our cross-origin security model and our shared hosting support; but
>> > that's
>> > a separate discussion.)
>> >
>> > - there is the framing, which does provide a modicum of protection by
>> > forcing another byte in front of the first author-controlled packet
>> > sent.
>> > (This isn't really a security feature, it's just a lucky accident of
>> > the
>> > framing that we needed to turn TCP streams into packets.)
>>
>> To summarise, if I have it right, you want to make sure that *the
>> browser* can be sure that corp.example.com really was intending to be a
>> websocket server when it opened the connection.
>
> Right.
>
>
>> If its not, it should bail. That seems reasonable :). We can definitely
>> (and have been :)) advising on how to do that with HTTP, but it means
>> *having a decent HTTP stack*. The response to a HTTP request is always
>> an HTTP response. Upgrade: changes the way the wire behaves after that.
>
> It seems that just having a WebSocket "stack" is adequate also.

When all layers of the stack confirm to the appropriate protocols, yes
agreed.
Point of this discussion is that the WebSockets layer _when sitting on top
of HTTP_ needs to be using HTTP layer correctly.

>
>> > Yes, but the client is a WebSocket client, not an HTTP client, so why
>> > would it send anything but the WebSocket handshake?
>>
>> Because its asking an HTTP server to upgrade.
>
> How can it know that ahead of time?
>

When using port 80 is must assume to be doing so.
a) because it _is_
b) because any WebSockets server on port 80 is expecting that HTTP upgrade
request of yours to come in.

Therefore, doing proper HTTP Upgrade and discarding the junk headers is no
loss, remains secure, and a net gain when MITM are present doing perfectly
normal HTTP things.

>
>> That makes it an HTTP client and a WebSocket client... as in fact you
>> note below ..
>
> It's both. It's not an HTTP client in that it doesn't do anything but
what
> the WebSocket spec says it should do. It's an HTTP client in that it
> speaks something that can be interpreted as HTTP.

Your spec says otherwise. Simply by defining the byte-level content of the
headers the server and client are now speaking non-HTTP.
Were they spec'd as speaking HTTP this entire argument would not be
ocurring.

>
>
>> > No. I'm intending to do stuff over port 81. There is a desire in
>> > certain cases to be able to share this traffic with servers running on

>> > port 80, and in those cases, the content sent and the content required

>> > to be returned by the server is valid HTTP until the Upgrade succeeds,

>> > at which point it isn't HTTP.
>> >
>> > > Ian, are you absolutely certain that everywhere you use "the
>> > > internet", there is no "man in the middle" between you and the
>> > > server you're speaking to?
>> >
>> > In the case of TLS connections, yes.
>>
>> In corporate networking, TLS MITM is a 'feature': company signed
>> certificates are used to sign the TLS connection to the corporate
>> firewall, and the firewall validate the SSL connection to the outside
>> world. I haven't personally used this, so can't really say much more
>> about it. Squid's ssl-bump feature can be used for this, but I believe
>> browser config is needed (again on a corporate basis) to tell it that
>> this is expected.
>
> I can't think of any way of getting a WebSocket connection through such a

> situation, so there's not much point doing anything to handle this case.
> If you can think of a way of handling it that _would_ allow WebSocket
> through, let me know, as then it would make sense to support it.

Don't confuse TLS MITM with regular MITM. Regular MITM are still very
common and can be tunneled over without trouble just by accepting regular
HTTP changes during the upgrade request and reply headers.

Amos
Received on Wed Aug 05 2009 - 01:42:17 MDT

This archive was generated by hypermail 2.2.0 : Thu Aug 13 2009 - 12:00:04 MDT