Re: [hybi] Handshake was: The WebSocket protocol issues.

Willy Tarreau <w@1wt.eu> Thu, 30 September 2010 05:46 UTC

Return-Path: <w@1wt.eu>
X-Original-To: hybi@core3.amsl.com
Delivered-To: hybi@core3.amsl.com
Received: from localhost (localhost [127.0.0.1]) by core3.amsl.com (Postfix) with ESMTP id 619913A6C0A for <hybi@core3.amsl.com>; Wed, 29 Sep 2010 22:46:49 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.442
X-Spam-Level:
X-Spam-Status: No, score=-2.442 tagged_above=-999 required=5 tests=[AWL=-0.999, BAYES_00=-2.599, HELO_IS_SMALL6=0.556, J_CHICKENPOX_33=0.6]
Received: from mail.ietf.org ([64.170.98.32]) by localhost (core3.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id m94DS+ImeMrO for <hybi@core3.amsl.com>; Wed, 29 Sep 2010 22:46:48 -0700 (PDT)
Received: from 1wt.eu (1wt.eu [62.212.114.60]) by core3.amsl.com (Postfix) with ESMTP id 96A543A69ED for <hybi@ietf.org>; Wed, 29 Sep 2010 22:46:47 -0700 (PDT)
Received: (from willy@localhost) by mail.home.local (8.14.4/8.14.4/Submit) id o8U5lRFr012739; Thu, 30 Sep 2010 07:47:27 +0200
Date: Thu, 30 Sep 2010 07:47:27 +0200
From: Willy Tarreau <w@1wt.eu>
To: Maciej Stachowiak <mjs@apple.com>
Message-ID: <20100930054727.GE10026@1wt.eu>
References: <AANLkTim+fXj-h6OS3OdcfVfh3Q1UwxD8NLVawb=AWHX+@mail.gmail.com> <4FAC5C93-9BDF-4752-AFBC-162D718397AB@apple.com> <AANLkTikcH1W3bQwumqHbe-Yqa3XdoJqCa2b-mZuvoQ7g@mail.gmail.com> <9746E847-DC8B-45A7-ADF3-2ADB9DA7F82E@apple.com> <AANLkTik9igUwoxVrktoBoZrPoUW=Tjh7HyVbGJgQYes-@mail.gmail.com> <9F595226-FA0A-4C38-A6D0-0F4214BD7D21@apple.com> <20100929171550.GB8583@1wt.eu> <D82A525D-5F37-4392-AE8A-A5246E5694F3@apple.com> <20100929204518.GD10026@1wt.eu> <6B4FE9F4-37E9-4D72-9325-9014F725373E@apple.com>
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
In-Reply-To: <6B4FE9F4-37E9-4D72-9325-9014F725373E@apple.com>
User-Agent: Mutt/1.4.2.3i
Cc: hybi <hybi@ietf.org>
Subject: Re: [hybi] Handshake was: The WebSocket protocol issues.
X-BeenThere: hybi@ietf.org
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: Server-Initiated HTTP <hybi.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/listinfo/hybi>, <mailto:hybi-request@ietf.org?subject=unsubscribe>
List-Archive: <http://www.ietf.org/mail-archive/web/hybi>
List-Post: <mailto:hybi@ietf.org>
List-Help: <mailto:hybi-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/hybi>, <mailto:hybi-request@ietf.org?subject=subscribe>
X-List-Received-Date: Thu, 30 Sep 2010 05:46:49 -0000

On Wed, Sep 29, 2010 at 06:40:52PM -0700, Maciej Stachowiak wrote:
> > OK now I see your point. However I disagree with the need to protect
> > such a broken implementation.
> 
> As a browser implementor, I don't have the luxury of taking that stance.
> Users will blame the browser.

well, right now some blame the protocol for being complex and error-prone.

> > We're back to the "and what if the server-side implementation is buggy ?".
> 
> We can design the protocol so it's easy to make mistakes that cause a security vulnerability. Or we can make it hard to make mistakes. I prefer the latter.

I too do.

> > A publicly accessible server
> > returning 101 to random requests will just get tons of unwanted requests
> > from random HTTP scans which will cause it major trouble anyway.
> 
> Depends on what it's checking. If it looks for a string matching "Sec-WebSocket-Nonce" or what have you, that won't be in most random unwanted requests. Note that one case we are concerned about is severs protected solely by a firewall. In that case, the only way parties outside the firewall can do random scans is by hijacking a user's browser, and using the browser's HTTP capabilities.

The upgrade header won't be in random browser requests either. It's a
well-defined part of the HTTP protocol with specific semantics. Let's
be clear : I have no problem with looking at the WS nonce, and it is
required too. I mean that we must not complexify the handshake "just in
case". HTTP is a well-defined protocol with clear semantics. Some aspects 
of it are not well respected but most of them definitely are.

> But in any case, the very thing I am proposing we do is design the handshake so it's not likely that servers would be at risk from random HTTP scans.

That's my goal too : each side must be protected from the other side,
and must avoid attacking the other side, but we don't have to protect
each side from itself. So :

  - browsers must be able to distinguish between those 3 cases :
    1. servers that don't speak anything that looks like HTTP, so
       we must not blindly send too much data during the handshake.

    2. HTTP servers that don't speak websocket, so the handshake must
       ensure that it quickly fails on such a server (does not return
       101).

    3. real websocket servers

  - servers must be able to distinguish between those 3 cases :
    1. blind attacks with static data (bots, reverse FTP downloads, etc...)
       hence the need of a server-client-server check.

    2. HTTP browsers that try to make HTTP requests to a WS server
       (broken link on a page or CSRF, XHR, etc...). This is indicated
       by the lack of Upgrade and WS-specific headers ;

    3. real WS requests from browsers

Note that the first point for servers above should not even be required,
as HTTP servers don't do that right now. However I agree that it can be
a nice improvement eventhough it sometimes adds one RTT to the handshake
(in the case where the server has to talk first).

> Note that the NPN+TLS handshake won't have this problem. There's no way to produce anything that looks even remotely like it form a browser-hosted HTTP client.

I think that Adam will flame me for saying that, but in my opinion it
is equivalent : either the browser can present all what is needed or
it cannot. The Upgrade: WS header is the equivalent of the WS protocol
you'd announce in the NPN+TLS handshake. What TLS protects from is not
the server against the client, it's the client from connecting to non
WS servers (case 1 for browsers above). The Upgrade header is an HTTP
connection-specific header, it should be controlled by the lower layers
of the browser, basically at the same level as the TLS, where the user
has no control over what is sent.

> > The
> > presence of the Upgrade header *is* the only element that can dictate
> > a valid response. However I agree that the handshake should ensure
> > that a client can quickly escape from such a broken implementation,
> > the same way as right now a browser should reject responses which do
> > not look like HTTP.
> 
> That may be useful in its own right, but it would not in any way help in the case of an HTTP client being used to attack WebSocket. The HTTP client implementation will not be looking for a WebSocket server, broken or otherwise, so nothing the client does can offer any protection.

Yes it will, because a normal HTTP client must not accept 101 as a valid
response to an HTTP request, just as a WS client must not accept a non-101
response. We have two types of valid request/responses :
   - normal requests without Upgrade that cause any status except
     101 to be returned
   - Upgrade requests that cause 101+Upgrade in the response

Any combination of the two is wrong and must be rejected by the browser.
And if we want to help clients that would inadvertently retried the
response as data, that's one more reason to return "content-length:0"
and "connection: close" with the 101 response.

Also, you can't design a protocol that must protect two broken
implementations from talking to each other, because no side can rely on
the other one to do the cleanup. We need at least one compliant side to
apply our rules in order to recover.

Regards,
Willy