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

Scott Ferguson <ferg@caucho.com> Mon, 27 September 2010 23:25 UTC

Return-Path: <ferg@caucho.com>
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 3DEFD3A6B97 for <hybi@core3.amsl.com>; Mon, 27 Sep 2010 16:25:38 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.19
X-Spam-Level:
X-Spam-Status: No, score=-2.19 tagged_above=-999 required=5 tests=[AWL=0.075, BAYES_00=-2.599, IP_NOT_FRIENDLY=0.334]
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 lRXHqjufouIn for <hybi@core3.amsl.com>; Mon, 27 Sep 2010 16:25:36 -0700 (PDT)
Received: from smtp114.biz.mail.sp1.yahoo.com (smtp114.biz.mail.sp1.yahoo.com [69.147.92.227]) by core3.amsl.com (Postfix) with SMTP id B52D13A6BBA for <hybi@ietf.org>; Mon, 27 Sep 2010 16:25:36 -0700 (PDT)
Received: (qmail 65347 invoked from network); 27 Sep 2010 23:26:14 -0000
Received: from [192.168.1.11] (ferg@66.92.8.203 with plain) by smtp114.biz.mail.sp1.yahoo.com with SMTP; 27 Sep 2010 16:26:14 -0700 PDT
X-Yahoo-SMTP: L1_TBRiswBB5.MuzAo8Yf89wczFo0A2C
X-YMail-OSG: EOTtIfEVM1lDH30b6PXhvU6FrMpexk0R4jd7M83YhJ3Flqp _qNco3A2OnOuHX8UGpKzhHJa2UC7MlnXGTfu1Ybty0itNnHPCfT.OyDHa.Ao z_.h2epYvzkW3eqYOEMfKLHKkEX7Cugqso0xUIacuPR1oLuibTwys.OYEF30 yVtJ4IVq64WIi7lpdsnD2iUVVwVABDWGg02SK4d5PMNVxqlOFyL2Grb2y7a_ sCAHl_ZUW5PbCObPgwnYLQqeMNQRe9QAS2OFKnH14qKL1JhLHDMwUH66.LMe ad0jb.5lKAoeOgMm1TY0Mh.5kLDmtEO.bKob1sUbhMXUhtL_njELPiA--
X-Yahoo-Newman-Property: ymail-3
Message-ID: <4CA12810.8020006@caucho.com>
Date: Mon, 27 Sep 2010 16:26:08 -0700
From: Scott Ferguson <ferg@caucho.com>
User-Agent: Thunderbird 2.0.0.24 (X11/20100411)
MIME-Version: 1.0
To: Greg Wilkins <gregw@webtide.com>
References: <AANLkTikszM0pVE-0dpZ2kv=i=y5yzS2ekeyZxtz9N=fQ@mail.gmail.com> <62B5CCE3-79AF-4F60-B3A0-5937C9D291D7@apple.com> <AANLkTikKc+4q_Q1+9uDo=ZpFF6S49i6vj2agZOGWVqKm@mail.gmail.com> <E2D38FF3-F1B9-4305-A7FC-A9690D2AEB4A@apple.com> <AANLkTikRYB_suPmSdH3uzGmdynozECRszDx+BpUvtZ4h@mail.gmail.com> <5CBF797D-A58E-4129-96B3-164F6E7409B9@apple.com> <4CA0D0D2.4040006@caucho.com> <AANLkTinACqm-GxUPhvFMf6_sGfeJofwy1r=28o=vgM43@mail.gmail.com>
In-Reply-To: <AANLkTinACqm-GxUPhvFMf6_sGfeJofwy1r=28o=vgM43@mail.gmail.com>
Content-Type: text/plain; charset="UTF-8"; format="flowed"
Content-Transfer-Encoding: 7bit
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: Mon, 27 Sep 2010 23:25:38 -0000

Greg Wilkins wrote:
> Scott,
>
> yes - I glossed over the details of what the actual hash should be in
> the ping packet.  I believe H(c-nonce, "WebSocket") is a good hash
> that indicates the server is a WS.
>   

That's not quite the issue. It's the second hash in the PONG that's 
missing, because we also need to verify the client as a WS client and 
not a hijacked HTTP client (or hijacked future non-websocket client):

The server's PING would have two values in its payload:

  S2. PING
    a. H(c-nonce, "WebSocket")
    b. s-nonce -- missing from your original proposal
    (*c. optional authentication challenge)

And the client's PONG would include the second hash:

  C3. PONG
    a. H(s-nonce, "WebSocket") -- missing from your original proposal
    (*b. optional authentication credentials)

I just re-skimmed the thread, but didn't see any discussion of the 
missing s-nonce, and H(s-nonce, "WebSocket") both of which are needed to 
validate the client. As Maciej pointed out, that client validation is an 
important check.

(*c and *b are just to show where an auth extension might fit.)

> With regards to using a WEBSOCKET method,  I would not like to see
> that as mandatory, as I still hold out some hope of using the
> handshake request as a useful GET or POST in the case that the
> websocket upgrade is unsuccessful.   It will take many years for
> websocket to be ubiquitous in browsers and intermediaries, so fall
> back transports will be a must for some time.  If an unsuccessful
> handshake can be used to initiate a comet transport, then we will save
> a RTT.
>
> I understand that there is no capability in the clients for this
> today, and it would greatly complicate the discussion to consider such
> a mechanism now.   So it is a thought bubble for the future.  So at
> this stage all I'm advocating is that we don't close off this options.
>
> Maybe the spec can say we SHOULD use the WEBSOCKET method unless the
> client is able to handle the response of another method, should the
> websocket upgrade be unsuccessful.
>   

These are good points.

I just wanted to raise the idea because it would be very nice for a 
non-websocket server to quickly detect and reject a websocket request 
just by looking at the first few characters, before any header or url 
attacks are possible. (The websocket method only helps well-written 
servers, of course, not broken servers like SMTP, but it's still a help.)

> I don't see using ping/pong in the handshake as overloading their
> purpose.  They are there to test the connection and keep it open, so
> it appears like the right purpose to me.  But then if others support a
> HELLO opcode, that also works for me.
>   

Either way.

I'd think HELLO would be cleaner because the payload's semantics are 
significantly different from the usual meaning of PING/PONG, but it 
doesn't really matter. The implementation is basically the same in 
either case.

-- Scott
> cheers
>
>
>
>
> On 28 September 2010 03:13, Scott Ferguson <ferg@caucho.com> wrote:
>   
>> Maciej Stachowiak wrote:
>>     
>>> On Sep 26, 2010, at 6:22 PM, Greg Wilkins wrote:
>>>
>>>
>>>       
>>>> 2010/9/27 Maciej Stachowiak <mjs@apple.com>:
>>>>
>>>>         
>>>>> Here is an email from February where I summarized some of the risks from
>>>>> cross-protocol attacks for WebSocket:
>>>>>
>>>>>           
>>>> Maciej,
>>>>
>>>> thanks for the reference, but I didn't and still don't fully
>>>> understand the actual risk posed by those descriptions and that we are
>>>> still shadow boxing against perceived rather than real threats.
>>>>
>>>>         
>>> The reason I am skeptical of your proposed ping-poing handshake as a
>>> defense against cross-protocol attacks is that the *only* defense protecting
>>> WebSocket servers from attacks over HTTP is the assumed inability of
>>> browser-hosted HTTP clients to send whatever carries the random nonce, or
>>> something that looks sufficiently similar. Your summary doesn't specify
>>> exactly how the nonce is sent, but I'll assume it is using a header that
>>> normally cannot be sent via cross-site XHR or similar APIs.
>>>
>>>       
>> Yes, the "ping" packet is missing a hash, which is needed to validate the
>> browser as a websocket browser. Modifying Greg's proposal:
>>
>> C1: c-nonce=...
>>
>> S2: H(c-nonce, "WebSocket")
>>     s-nonce=...
>>
>> C3: H(s-nonce, "WebSocket")
>>
>> With that modification, the client does not send websocket data until the
>> server has been validated as a websocket server, and the server does not
>> process websocket data until the client has been validated as a websocket
>> client. (There's no need for a S4 "pong" packet since the server is already
>> validated as websocket when the client validates S2.) That protocol is
>> pretty much the minimum required, and doesn't add overhead beyond the
>> current handshake.
>>
>> I'd propose two additional changes that aren't required, strictly speaking,
>> but would be helpful for other security-related reasons:
>>
>> 1. Use "WEBSOCKET" instead of "GET" as the HTTP method. This is helpful
>> because it lets validating servers quickly reject websocket requests (e.g.
>> well-behaved HTTP servers), and lets server administrators use existing
>> security frameworks (which are often HTTP method based), to specify
>> websocket security easily. With the current "GET", it's somewhat of a
>> problem for a server administrator to specify a different policy for GET vs
>> websockets.
>>
>> 2. Use a new AUTH or HELLO opcode/packet for the C3 hash instead of
>> overloading PING. This would make the packet's purpose clear and give a
>> space for any future challenge-based authentication to put its credentials
>> in a future spec extension. (I'd recommend any authentication
>> extension/C3-payload use HTTP style authentication headers so the extension
>> could just use existing security handshakes.)
>>
>>     
>>> A potential improvement would be to require the server to produce a random
>>> number, which is included in the ping and must be in the pong in addition to
>>> the hash. In that case, an attacker could not queue up the correct pong
>>> without looking at the server's response at all. But going down this road
>>> results in increasingly elaborate schemes, along the lines of the -76
>>> handshake. It's also likely there are more complicated flaws that we simply
>>> haven't thought of yet. I don't think we can stake the security of this
>>> protocol just on our own ability to think up attacks within a period of only
>>> a few weeks.
>>>
>>>       
>> No, it's different from -76, because the properties of the nonce/hash
>> pattern are well known. The flaw with -76 is just what you describe: it's
>> inventing new security patterns and is likely to have complicated flaws.
>> Sticking to a well-known pattern is the right way to go.
>>
>> -- Scott
>>     
>>> As I have thought about these issues, I am increasingly convinced that an
>>> NPN-style solution is much more robust. Attempting to make a TLS connection
>>> to a vanilla HTTP server, or an HTTPS server that does not understand NPN,
>>> will reject the connection at a very low level, greatly limiting the
>>> potential for shenanigans. Browser clients in general do not offer APIs that
>>> would allow a Web attacker any control of the outgoing TLS handshake, and
>>> the TLS layer would fail a bad connection before server software even had
>>> the opportunity to make a mistake. This approach seems much more robust to
>>> me. Rather than just barely being secure, it fails hard before the attacker
>>> can even do anything tricky. I think it is much likely there would be future
>>> attacks. I hope the WG strongly considers the NPN approach, despite the
>>> costs and challenges imposed by using TLS.
>>>
>>> Regards,
>>> Maciej
>>>
>>>
>>>
>>>
>>>
>>>       
>>>>> 1) Hostile JavaScript could use WebSocket for a cross-protocol attack
>>>>> against
>>>>> vanilla HTTP resources or non-HTTP servers.
>>>>> If the attacker can trick a non-WebSocket server into echoing back
>>>>> chosen text (for
>>>>> example through something in the URL part of the request), then they
>>>>> could make
>>>>> it give what appears to be a valid WebSocket handshake response. This
>>>>> could result
>>>>> in unauthorized access.
>>>>>
>>>>>           
>>>> I don't understand "unauthorized access" in this context.   If a
>>>> server, HTTP or otherwise want to protect it's content, then it needs
>>>> to have both authentication and authorization, which typically means
>>>> that the client will possess some credentials that the server must
>>>> check.     If the server does not protect its resources or the
>>>> attacker already has access to credentials (or can trick the
>>>> browser/user into providing credentials), then the easiest way to
>>>> access a non-websocket server would be with existing HTTP mechanisms
>>>> in the browser.
>>>>
>>>> Is there anything about WS that would make a vulnerable HTTP server
>>>> easier to exploit than just using the existing HTTP mechanisms
>>>> available in the browser? ie are there any exploit HTTP requests that
>>>> can be generated using the WS client that could not be generated
>>>> anyway?
>>>>
>>>>
>>>>
>>>>
>>>>         
>>>>> 2) Cross-site XMLHttpRequest (using CORS or XDomainRequest) could be
>>>>> used for a
>>>>> cross-protocol attack against WebSocket resources, potentially violating
>>>>> integrity (though not confidentiality).
>>>>>
>>>>> The WebSocket protocol currently does not require any checking of the
>>>>> client handshake. However, any
>>>>> WebSocket server that performs any side effects in response to messages
>>>>> from the client has a security
>>>>> vulnerability if it does not check correctness of the handshake request
>>>>> from the client.
>>>>>
>>>>>           
>>>> I think that any server that "performs any side effects in response to
>>>> messages from the client" will have a security vulnerability if they
>>>> do not correctly check the authentication and authorization of the
>>>> client. Eventually most browsers will have WS available to the
>>>> javascript, so a server that is so vulnerable will be able to be
>>>> exploited just with WS instead of trying to trick HTTP.
>>>>
>>>> The read question should be - are there any WS
>>>> authentication/authorization mechanisms that can be subverted by using
>>>> a HTTP mechanism instead of a the WS API?
>>>>
>>>>
>>>> I still think that we should take reasonable measures to prevent cross
>>>> protocol handshakes - even if there are no identified real security
>>>> issues.  But I think that the usage of Sec- headers and a simple nonce
>>>> will give very good protection and that we only need do more if there
>>>> is a real clearly identified risk.
>>>>
>>>> regards
>>>> _______________________________________________
>>>> hybi mailing list
>>>> hybi@ietf.org
>>>> https://www.ietf.org/mailman/listinfo/hybi
>>>>
>>>>         
>>> _______________________________________________
>>> hybi mailing list
>>> hybi@ietf.org
>>> https://www.ietf.org/mailman/listinfo/hybi
>>>
>>>
>>>
>>>
>>>       
>>     
>
>
>
>