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

From: Greg Wilkins <[email-masked]>
Date: Sat, 2 Oct 2010 09:35:12 +1000

Adam,

thanks for sharing the details of the experiments that you almost made
work in your private lab.  Strangely enough we didn't know about these
unpublished efforts of yours, nor gave you any "authority" for them,
because you've didn't tell us about them.

But in the end, your experiment indicated that DNS servers cannot
generally be attacked by HTTP requests, so WS handshakes are also
currently OK, with or without framed nonces and no space encoded
headers.  WS also has extra defences, in that it cannot send an entity
body with the handshake, so that any target server that uses
characters from GET or POST as a binary length (as DNS apparently
does), will see a very long packet and the WS client has no way to put
data there unless the WS handshake is successful.

So this experiment is not an argument against the current proposal.
But I think it is very valuable to step through such potential attacks
(hence I keep asking for details), so we can analyse our defences and
perhaps consider others.

I've never argued against defence in depth, I simply do not believe
that unframe nonces and space injected keys are any significant
defences and that there are better alternatives.

So from your experiment, I would propose that we explicitly restrict
the ports that WS clients can contact other than 80/443 that are below
1024.  I see no reason at all to allow WS connection attempts to port
53.

---

From: Scott Ferguson <[email-masked]>
Date: Fri, 01 Oct 2010 17:45:12 -0700

Adam Barth wrote:
> On Thu, Sep 30, 2010 at 6:50 PM, Scott Ferguson <[email-masked]> wrote:
>   
>> To repeat the key pieces:
>>  a) c-nonce must not be available to or predictable by the hijacker
>>  b) "WebSocket" is not possessed by a non-websocket server
>>     
>
> You're making a bunch of assumptions about how non-websocket servers
> behave.  In particular, consider a protocol like DNS.  It's entirely
> possible that a DNS-like protocol could relay the c-nonce to the
> attacker and give the attacker an opportunity to response with the
> appropriate hash, which the server would then relay to the client.
> Attacks of this general class (even against DNS) are known for HTTP.
>   

No, Adam, you can't just handwave that scenario. Let's take your attack 
in detail.

  1) Hijacker has taken control of a browser and initiates a websocket 
connection.
  2) That websocket connection is to a DNS server.
  3) The DNS server relays the c-nonce to the hijacked browser (???)

       browser -> DNS -> browser

  4) The hijacked browser can now compute H(c-nonce, "WebSocket")
  5) The browser somehow sends the H(c-nonce, "WebSocket") to the DNS 
proxy which now that it has the hash redirects to the actual target, 
which echos the hash through the theoretical proxy chain. Or it acts as 
a web-socket relay itself

       browser -> DNS -> browser -> target

None of which makes any sense.

I am making some assumptions:

  1) there are no websocket open relays. If there are, the issue isn't a 
cross-protocol attack, but an open relay attack. Your description 
proposes the browser itself as a websocket open relay ("could relay the 
c-nonce to the attacker").

  2) there are no open relays that compute H(xxxx, "WebSocket") or open 
relays that calculate arbitrary hashes H(xxxx).  Your proposed DNS 
attack does neither, nor does it propose a relay that does calculate 
either. Instead, you handwave to the hijacked browser itself as an open 
websocket relay.

> The security of this protocol relies on more assumptions than you've
> listed in your message.  Reasoning about security here is very subtle,
> especially when reasoning about the behavior of non-WebSocket servers.
>  We need to be prepared for them to do a wide variety of things.
>   

This statement is not particularly useful.

If you assume the existence of open relays which implement arbitrary 
protocols and compute arbitrary functions, that's equivalent to assuming 
the relay is a valid websocket proxy, which is no longer a 
cross-protocol attack.

Does your "wide variety of things" include calculation of arbitrary hashes?

> As a side note, using an exotic HTTP method is not a good idea.  The
> first few bytes of the clients initial message are absolutely
> critical.  Picking an exotic HTTP method is just rolling the dice
> w.r.t. what protocols an attacker can exploit.  For example, some
> attacks from HTTP to DNS rely critically on the fact that the first
> byte of an HTTP POST message is an uppercase P.  The kinds of things
> you can do with an uppercase W as the first byte are largely
> unstudied.
>   

You misunderstand entirely.

It's not an exotic HTTP method; it's identifying the protocol by the 
initial sequence of bytes.

If every client for every protocol sent a non-hijackable unique protocol 
identifier as its initial sequence, and every server for every protocol 
verified the protocol identifier before accepting any further bytes, 
then cross protocol attacks would be impossible.

We can't fix the older protocols that don't identify themselves 
immediately and don't validate, but we can ensure that new protocols do.

-- Scott

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Sat, 02 Oct 2010 03:08:08 +0200

>immediately and don't validate, but we can ensure that new protocols do.

I am not sure you understood Adam's point. Right now an attacker cannot
trick some person into opening a web page where the browser will then
open a TCP connection to a host and port of the attackers choosing and
have it send "WEBSOCKET ..." to it, and there may be environments and
protocols where that allows some form of attack. Since the attacker has
a good amount of control over the path that follows the verb, that's not
entirely impossible and should be considered if the group decides to use
a "WEBSOCKET" method.
-- 
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: Adam Barth <[email-masked]>
Date: Fri, 1 Oct 2010 18:08:07 -0700

Please read my later message.  That should give you a more concrete
understanding of the issue.

(minor points inline)

On Fri, Oct 1, 2010 at 5:45 PM, Scott Ferguson <[email-masked]> wrote:
> No, Adam, you can't just handwave that scenario. Let's take your attack in
> detail.
>
>  5) The browser somehow sends the H(c-nonce, "WebSocket") to the DNS proxy
> which now that it has the hash redirects to the actual target, which echos
> the hash through the theoretical proxy chain. Or it acts as a web-socket
> relay itself
>
> cross-protocol attack, but an open relay attack. Your description proposes
> the browser itself as a websocket open relay ("could relay the c-nonce to
> the attacker").
>
> relays that calculate arbitrary hashes H(xxxx).  Your proposed DNS attack
> does neither, nor does it propose a relay that does calculate either.
> Instead, you handwave to the hijacked browser itself as an open websocket
> relay.
>
> protocols and compute arbitrary functions, that's equivalent to assuming the
> relay is a valid websocket proxy, which is no longer a cross-protocol
> attack.
>
> It's not an exotic HTTP method; it's identifying the protocol by the initial
> sequence of bytes.

Exotic => can't be sent by web sites to arbitrary hosts today in browsers.

> verified the protocol identifier before accepting any further bytes, then
> cross protocol attacks would be impossible.

Sure, but there are plenty of protocols that don't do that.

> We can't fix the older protocols that don't identify themselves immediately
> and don't validate, but we can ensure that new protocols do.

Unfortunately, we don't have the luxury of ignoring attacks against
these "older" protocols.

Adam

---

From: Greg Wilkins <[email-masked]>
Date: Sat, 2 Oct 2010 21:09:20 +1000

> Unfortunately, we don't have the luxury of ignoring attacks against

Nobody is ignoring the attacks on "older" protocols.

Your efforts have show that with the capabilities of XHR you could
almost but not quiet make a cross protocol to DNS.
So we know that DNS is not vulnerable to the wide range of HTTP
requests that XHR can send  (eg with lots of application provided
data).

WebSocket uses a very specific HTTP request in it's handshake. The
attacker has no control over most of the headers or the method. They
can supply only a URL and a subprotocol string, but no content body.
 So if DNS is not vulnerable to arbitrary HTTP requests, then it is
not vulnerable to this very specific HTTP request.

The fact that DNS is almost vulnerable to HTTP is interesting, but not
really relevant to the proposals we have to refine the WS handshake.
Are you really saying that because DNS is almost vulnerable to crafted
HTTP requests, that we must space inject the nonces in websocket
handshakes or leave our hashes unframed?

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Sat, 02 Oct 2010 14:36:44 +0200

>requests that XHR can send  (eg with lots of application provided

(Adam's example depends on the server emitting a string under the
attackers control and uses a form post so that script is executed
in an unexpected context. You can't make an attack "like that"
using XMLHttpRequest.)
-- 
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: Adam Barth <[email-masked]>
Date: Sat, 2 Oct 2010 09:24:11 -0700

> handshakes or leave our hashes unframed?

I'm saying these issue are subtle and require careful thought.  The
success or failure of HTTP POST to attack DNS depends critically on a
number of seemingly irrelevant details about how browsers generate and
process network messages.

I brought up the example of DNS to show how an attacker might be able
to get a non-WebSocket server to rely the c-nonce to the attacker and
let the attacker relay back with the HMAC of the c-nonce.  This
example might not completely break the c-nonce handshake, but it's
evidence that relying upon an HMAC alone is probably unwise.

Adam

---

From: Scott Ferguson <[email-masked]>
Date: Sat, 02 Oct 2010 10:32:12 -0700

> Exotic => can't be sent by web sites to arbitrary hosts today in browsers.

Understood, but that describes any new protocol added to the browser.

Without initial identifying bytes, no server (new protocol or old) can 
detect and reject a websocket request without scanning past a large 
number of hijackable bytes. I'd like to give servers the ability to 
identify and reject a websocket request before scanning hijackable 
bytes, even if not all servers can take advantage of that information.
> Sure, but there are plenty of protocols that don't do that.

Which is why we still need server validation before sending the client 
payload. I'm not suggesting removing the nonce/hash check at all.

If this increases security for existing validating protocols and all new 
protocols, it increases security.  As you point out, it cannot be the 
only defense.

> Unfortunately, we don't have the luxury of ignoring attacks against

It is true that you will need to re-analyze url/header attacks against 
non-validating legacy servers, but the added security of the identifying 
bytes for the benefit of validating servers and future protocols is 
worth the trouble.

-- Scott

---

From: Scott Ferguson <[email-masked]>
Date: Sat, 02 Oct 2010 10:38:55 -0700

> entirely impossible and should be considered if the group decides to use

Right, but that's balanced against the added value of enabling servers 
to identify and reject a websocket request quickly.

The issue, of course, is that we're talking about different servers when 
evaluating the tradeoff. But I don't think Adam's point about the known 
problems with existing non-validating servers is a sufficient reason to 
weaken security for validating servers and future protocols.

-- Scott

---

From: Scott Ferguson <[email-masked]>
Date: Sat, 02 Oct 2010 10:57:53 -0700

> evidence that relying upon an HMAC alone is probably unwise.

Let's focus on this point.

To successfully attack the nonce/hash, the hijacker must do all of the 
following:

  1) Find a server or proxy (or sequence of proxies) that calculates H(x,y)
  2) Extract c-nonce from the request bytes and inject it into x.
  3) Inject "WebSocket" into the request and inject into y.
  4) Induce the server/proxy to return/forward the calculated hash in 
the proper format.

To keep the discussion focused on #1, lets give the hijacker 2-4.

There are two restrictions however:

  a) The hijacker can't use a websocket proxy.
  b) No time travel allowed.

Your DNS example did not weaken requirement #1, because it didn't 
identify a server or proxy that could calculate the hash. Your "relay 
back" either used the browser itself as a websocket proxy or it meant 
time travel.

-- Scott

---

From: Adam Barth <[email-masked]>
Date: Sat, 2 Oct 2010 14:51:52 -0700

On Sat, Oct 2, 2010 at 10:57 AM, Scott Ferguson <[email-masked]> wrote:
> Your DNS example did not weaken requirement #1, because it didn't identify a
> server or proxy that could calculate the hash. Your "relay back" either used
> the browser itself as a websocket proxy or it meant time travel.

I'm not sure you understood the DNS example correctly.  The forged DNS
request is for foo.attacker.com, which means the nonce is sent to the
attacker's DNS server.  The attacker's DNS server can easily compute
the HMAC and send it back in a DNS response.  The HMAC will then get
relayed through the DNS and returned to the browser.

Adam

---

From: Greg Wilkins <[email-masked]>
Date: Tue, 5 Oct 2010 11:20:20 +1100

On 3 October 2010 03:24, Adam Barth <[email-masked]> wrote:

> I'm saying these issue are subtle and require careful thought.

Exactly - and careful thought and analysis is what some are trying to
achieve in this thread.

It is not really helpful to imply that we are not giving it careful
thought or  that we are somehow not qualified enough for our careful
thought to count.

Your DNS example was a good one for us to analyse.  But in the end,
it re-enforced that our defence in depth is indeed working and that
DNS is safe from arbitrary XHR HTTP, so it is safer from our more
restricted HTTP handshake.  It is not an argument against the proposed
changes to the handshake.

So if you have other possible attack vectors, please post them and we
can also walk through the defences and see how they stand up.  With
such careful thought and analysis we might actually make progress on
the protocol proposals.

---

From: Adam Barth <[email-masked]>
Date: Mon, 4 Oct 2010 17:46:45 -0700

> such careful thought and analysis we might actually make progress on

I'm working on a detailed analysis.  Hopefully I'll have it ready to
post to the list sometime this week.

Adam

---

From: Scott Ferguson <[email-masked]>
Date: Tue, 05 Oct 2010 18:08:10 -0700

> relayed through the DNS and returned to the browser.

If you assume the hijacker has control of a DNS server to act as a 
proxy, you may as well assume he has control of an actual WebSocket 
server to act as a proxy.

-- Scott

---

From: Adam Barth <[email-masked]>
Date: Tue, 5 Oct 2010 18:11:11 -0700

On Tue, Oct 5, 2010 at 6:08 PM, Scott Ferguson <[email-masked]> wrote:
>>> identify a
> If you assume the hijacker has control of a DNS server to act as a proxy,
> you may as well assume he has control of an actual WebSocket server to act
> as a proxy.

Huh?  That doesn't make any sense.  If you run a stock DNS server, it
will proxy lots of information from authoritative DNS servers around
the world.  That's the whole point of DNS.

Adam

---

From: Scott Ferguson <[email-masked]>
Date: Tue, 05 Oct 2010 18:30:07 -0700

> the world.  That's the whole point of DNS.

C1: Browser at 192.168.1.10 makes TCP websocket connection with local 
port 8888 to DNS server 10.0.0.1.

S2: DNS server returns DNS response to 192.168.1.10:8888 which contains 
H(c-nonce, "WebSocket") somewhere in the payload

C3: Browser notices that DNS reponse does not have the same syntax as a 
WebSocket  response, and closes the connection.

How is this an attack?

-- Scott

---

From: Adam Barth <[email-masked]>
Date: Tue, 5 Oct 2010 18:40:39 -0700

On Tue, Oct 5, 2010 at 6:30 PM, Scott Ferguson <[email-masked]> wrote:
> C1: Browser at 192.168.1.10 makes TCP websocket connection with local port
> 8888 to DNS server 10.0.0.1.
>

The claim was that the presence of H(c-nonce, "WebSocket") in the
payload was sufficient to prove that the respondent understood what
was going on.  Notice that in this example, you're also relying upon
the rigidity of the bytes surrounding the HMAC for security, which
proves my point: the HMAC alone is insufficient.

In any case, I'd encourage you to thinking about this proposal instead:

http://www.ietf.org/mail-archive/web/hybi/current/msg04285.html

Adam

---

From: Scott Ferguson <[email-masked]>
Date: Wed, 06 Oct 2010 09:40:07 -0700

Adam Barth wrote:
> Consider, for example, a virtual hosting environment in which the
> attacker can place PHP scripts on the server.  For example, such
> hosting environments are widely available commercially, such as from
> 1and1.com.  Now, the attacker can complete the WebSocket handshake
> because the PHP script can compute the HMAC and send the appropriate
> response header.

That's the same hand-waving in lieu of an actual attack. Let's review.

Proposed attack: Attack server S with the help of DNS (or hosted HTTP 
server.)

Since your attack in the previous mail did not include a connection to 
server S, your description did not demonstrate the validity of your 
attack against S. (If you want to attack DNS itself, we can discuss that 
as a new attack, but you would need to withdraw your broader claim first.)

You need to demonstrate a sequence of connections to make that attack 
work (without using a WebServer proxy or time travel). For discussion, 
I've granted you syntax, but you must still demonstrate your sequence of 
connections and propagation of the c-nonce and H to complete the attack.

At very least, you need to make clear whether you mean the PHP server to 
act as a proxy or if you mean to establish a second WebSocket from the 
browser. You may not, however, change the target IP address of the first 
WebSocket connection from the PHP server to the target server using the 
original socket.

-- Scott

> /www.ietf.org/mail-archive/web/hybi/current/msg04285.html
>
> Adam
>
>
>
>

---

From: Scott Ferguson <[email-masked]>
Date: Fri, 08 Oct 2010 15:04:57 -0700

Scott Ferguson wrote:
>> attacker can place PHP scripts on the server....  Now, the attacker 
>> can complete the WebSocket handshake
> I've granted you syntax, but you must still demonstrate your sequence 
> of connections and propagation of the c-nonce and H to complete the 
> attack.

You still need to demonstrate a sequence of connections to make this 
attack work because your attack appears impossible to complete using TCP 
as currently described.

At very minimum, you need to describe how the WebSocket connection from 
the hijacked browser connects to both the HTTP (or DNS) server that 
computes the hash, and to the target server S to complete the attack.

-- Scott

---

From: Adam Barth <[email-masked]>
Date: Fri, 8 Oct 2010 15:06:33 -0700

On Fri, Oct 8, 2010 at 3:04 PM, Scott Ferguson <[email-masked]> wrote:
>>> attacker can place PHP scripts on the server....  Now, the attacker can
>>> complete the WebSocket handshake
>> You need to demonstrate a sequence of connections to make that attack work
>> (without using a WebServer proxy or time travel). For discussion, I've
>> granted you syntax, but you must still demonstrate your sequence of
> You still need to demonstrate a sequence of connections to make this attack
> work because your attack appears impossible to complete using TCP as
> currently described.
>
> At very minimum, you need to describe how the WebSocket connection from the
> hijacked browser connects to both the HTTP (or DNS) server that computes the
> hash, and to the target server S to complete the attack.

The DNS server is the target server.

Adam

---

From: Scott Ferguson <[email-masked]>
Date: Fri, 08 Oct 2010 15:50:43 -0700

> The DNS server is the target server.

Then please retract your more general claimed attack against server S 
using DNS/HTTP.

Let me repeat the important claim from your proposal (also quoted above):

> "Consider, for example, a virtual hosting environment in which the 
> can complete the WebSocket handshake because the PHP script can 
> compute the HMAC and send the appropriate response header."

Is the PHP server owned by the attacker also the target server S? If so, 
you need to make that restricted claim clear, because you've given the 
impression that the target server S is not owned by the attacker.

-- Scott

---

From: Adam Barth <[email-masked]>
Date: Fri, 8 Oct 2010 16:03:42 -0700

On Fri, Oct 8, 2010 at 3:50 PM, Scott Ferguson <[email-masked]> wrote:
>>>> work
>>> attack
>>> the
> Then please retract your more general claimed attack against server S using
> DNS/HTTP.
>

Oh, I thought we were still talking about the earlier example that
involved a DNS server.

>> complete the WebSocket handshake because the PHP script can compute the HMAC
>> and send the appropriate response header."
>
> Is the PHP server owned by the attacker also the target server S? If so, you
> need to make that restricted claim clear, because you've given the

This is a virtual hosting environment.  That's what I meant when I
said "consider, for example, a virtual hosting environment in which
the attacker can place PHP scripts on the server."  The attacker has
access to one virtual host on the server but does not own the entire
server.

Concretely, consider http://www.adambarth.com/.  My web site is a
virtual host on a physical server in a 1and1 datacenter.  I'm
perfectly capable of placing a PHP script on my virtual host.  If the
PHP script is able to complete the web socket handshake, then I can
open a WebSocket connection to www.adambarth.com on port 80 from the
user's browser.  Once the WebSocket handshake completes, I can now
talk directly to the 1and1 server over more-or-less a raw socket,
which means I can spoof further HTTP requests and potentially attack
other virtual hosts that happen to be on the same physical machine,
which is bad news bears.

Adam

---

From: Scott Ferguson <[email-masked]>
Date: Fri, 08 Oct 2010 16:41:31 -0700

> Oh, I thought we were still talking about the earlier example that

As long as we're clear that DNS itself and DNS only is the target and 
not some second server using information from DNS, this is fine. 
"involved" is more general than "is the target".

> other virtual hosts that happen to be on the same physical machine,

So the attacker has a PHP script running on the same physical machine as 
the target site, on the same VM guest as the target, and using the same 
shared web server as the target, and has decided that a cross protocol 
attack is the appropriate vector against a target on the same machine as 
his PHP script.

I'll let others decide if that scenario is something the WebSocket 
protocol needs to address.

However, I will point out that using "WEBSOCKET" as the HTTP method 
would let the ISP reject the initial request, protecting other virtual 
hosts from this attack.

-- Scott

---

From: Adam Barth <[email-masked]>
Date: Fri, 8 Oct 2010 16:57:21 -0700

On Fri, Oct 8, 2010 at 4:41 PM, Scott Ferguson <[email-masked]> wrote:
> So the attacker has a PHP script running on the same physical machine as the
> target site, on the same VM guest as the target, and using the same shared
> web server as the target, and has decided that a cross protocol attack is
> the appropriate vector against a target on the same machine as his PHP
> script.
>
> I'll let others decide if that scenario is something the WebSocket protocol
> needs to address.

These scenarios are very real.  My web site is certainly not the only
virtual PHP hosting on the Internet.  :)

> However, I will point out that using "WEBSOCKET" as the HTTP method would
> let the ISP reject the initial request, protecting other virtual hosts from
> this attack.

That assumes the ISP is aware of WebSockets.  We're considering
vulnerabilities in servers that are not upgraded to understand
WebSockets.

Adam

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Sat, 09 Oct 2010 02:00:18 +0200

>attack is the appropriate vector against a target on the same machine as 

In the scenario the browser thinks it is talking Websocket while the
server thinks the browser is talking HTTP, so basically

  +----------------+                    +------------------+
  | User's browser | -- "Websocket" +-- | attacker.example |
  +----------------+                |   +------------------+
                                  HTTP
                                    |   +------------------+
                                    +-- | target.example   |
                                        +------------------+

How attacker.example and target.example are organized is up to the
web server, it could just be some kind of firewall where the two sites
are actually hosted on physically separate machines behind it and they
may be unable to talk to each other. I do think this is something that
the Websocket protocol needs to address.
-- 
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: Adam Barth <[email-masked]>
Date: Fri, 8 Oct 2010 17:03:55 -0700

> server thinks the browser is talking HTTP, so basically

Yes, precisely.  The proposal I sent recently addresses this issue by
putting the virtual host dispatch information in a place that's only
visible to a server that understands WebSockets.  That way we know
it's making an informed decision about accepting the handshake.

Adam

---

From: Scott Ferguson <[email-masked]>
Date: Fri, 08 Oct 2010 17:28:20 -0700

> vulnerabilities in servers that are not upgraded to understand

Existing servers can already reject HTTP methods. That's one of the 
reasons I've suggested it:

  <Limit WEBSOCKET>
    Deny from all
  </Limit>

Yes, your ISP would need to add those lines or something similar to the 
web server configuration. ISPs in shared hosting environments do need to 
be aware of security issues, even if they can't upgrade servers arbitrarily.

-- Scott

---

From: Adam Barth <[email-masked]>
Date: Fri, 8 Oct 2010 17:36:47 -0700

On Fri, Oct 8, 2010 at 5:28 PM, Scott Ferguson <[email-masked]> wrote:
> Existing servers can already reject HTTP methods. That's one of the reasons
> I've suggested it:
>
>  <Limit WEBSOCKET>
>   Deny from all
>  </Limit>
>
> Yes, your ISP would need to add those lines or something similar to the web
> server configuration. ISPs in shared hosting environments do need to be
> aware of security issues, even if they can't upgrade servers arbitrarily.

Requiring existing servers to update themselves to be secure from new
browser features is a non-starter.

Adam

---

From: Greg Wilkins <[email-masked]>
Date: Sat, 9 Oct 2010 11:37:50 +1100

Adam,

the key phrase in this description is "Once the Websocket handshake completes".
That just glosses over several defences:

 + It is not certain that the HTTP server will allow a PHP script to
generate a 101 response.
 + The HTTP server will not allow the PHP script to generate a WS ping
frame (or the unframed bytes of the current draft).
 + The HTTP server will not accept the pong response as a valid HTTP
request. This will almost certainly result in a 400 Bad request and
the connection being closed.

Currently there is no attack vector to get past these defences, other
than to assume that the server is already vulnerable to significant
attacks without the need to use a WS client.

Even if the handshake could complete - which it couldn't.  Then the
server does not have a more or less raw socket.  It has a WS socket
and only WS frames can be sent.  I am dubious that a valid websocket
frame could be a meaningful HTTP request.

However I do believe that this is very good exercise that we should do
- examine if it is possible to form a WS frame that looks like a
GET/POST/PUT etc request.  We should also test how common servers
treat characters such as would be expected in a WS header.  There may
be some tweaks we can make to the framing (eg setting RSV bits to 1)
that will further reduce the possibility of WS frames looking like
HTTP requests/

I will try to find some time to do this analysis next week.

regards

---

From: Scott Ferguson <[email-masked]>
Date: Fri, 08 Oct 2010 17:39:32 -0700

> server thinks the browser is talking HTTP, so basically

To consider the original scenario, do you think the case where the 
attacker's PHP script is on the same physical and virtual machine as the 
target is something WebSockets needs to address? Or that the shared 
machine configuration is already so compromised that complicating 
WebSockets to address that scenario adds no real value.

Your proxy case needs to be considered separately, because a proxied 
attacker has less power over the web server than a PHP script on the 
same server does.

-- Scott

---

From: Greg Wilkins <[email-masked]>
Date: Sat, 9 Oct 2010 11:41:46 +1100

> browser features is a non-starter.

Existing servers must continually update their operating systems and
server software if they are to stay secure.

So I agree that requiring an update in order to secure websockets is
not reasonable. But  I do believe that we could add some extra levels
of defence and close of some areas where we may have some slight
concerns, by proposing some reasonable updates to add some more layers
of defence and these would be applied to a large proportion of servers
in a reasonable time frame.

regards

---

From: Eric Rescorla <[email-masked]>
Date: Fri, 8 Oct 2010 17:43:06 -0700

On Fri, Oct 8, 2010 at 5:39 PM, Scott Ferguson <[email-masked]> wrote:

>>> attack is the appropriate vector against a target on the same machine as his
>>> PHP script.
>>>
>>>
>>
> target is something WebSockets needs to address? Or that the shared machine
> configuration is already so compromised that complicating WebSockets to
> address that scenario adds no real value.
>
>
This case definitely needs to be addressed. It's a completely standard
hosting
configuration.

-Ekr

---

From: Adam Barth <[email-masked]>
Date: Fri, 8 Oct 2010 17:43:51 -0700

>  + It is not certain that the HTTP server will allow a PHP script to

I don't know why you think that's so hard to set the response status.
There's a PHP function does exactly that:

http://php.net/manual/en/function.http-send-status.php

According to the documentation it can set any status between 100 and 599.  Etc.

Anyway, we have a handshake that nukes these vulnerabilities from
orbit.  We should just use that instead of crossing our fingers and
hoping for the best.

Adam

---

From: Scott Ferguson <[email-masked]>
Date: Fri, 08 Oct 2010 17:55:17 -0700

> That just glosses over several defences:

All good points.

> frame could be a meaningful HTTP request.

And even if this were all possible, the browser could now ...

... wait for it ...

... make HTTP requests to a HTTP server using websockets instead of the 
browser's HTTP client.

-- Scott

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Sat, 09 Oct 2010 03:08:59 +0200

>attacker has less power over the web server than a PHP script on the 

I believe that if the latter case is addressed, then the former case is
no longer possible (if you consider the web server the browser attempts
to connect with a black box then they are really identical). I do think
in the former case an attacker will try many other things first. Note
that the attacker would only attempt this if the user knows something,
or can represent something, the attacker does not or cannot, like ensure
the request is coming from a particular IP address. Otherwise he could
just send whatever bytes to the server he feels like sending.
-- 
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: Adam Barth <[email-masked]>
Date: Fri, 8 Oct 2010 18:21:23 -0700

> ... make HTTP requests to a HTTP server using websockets instead of the

Which is, of course, problematic because now the attacker is free of
all the security restrictions the browser places on his use of HTTP.
For example, the attacker can now forge the Host header.

Adam

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Sat, 09 Oct 2010 03:25:37 +0200

>... make HTTP requests to a HTTP server using websockets instead of the 

By now there are quite a number of handshake proposals floating around,
but if a single response is sufficient to make the web browser consider
the connection to have been upgraded to a Websocket connection, and the
framing allows to make frames that look like HTTP requests, and last I
checked "DELETE..." was a properly formed frame (though that relied on
the browser setting a flag that is currently reserved), then this setup
would allow attackers do to things they currently cannot do, as browsers
excercise considerable control over what requests a possibly malicious
web site can trigger for an unrelated site.
-- 
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: Bjoern Hoehrmann <[email-masked]>
Date: Sat, 09 Oct 2010 03:41:05 +0200

> + It is not certain that the HTTP server will allow a PHP script to

A typical Apache configuration allows you to make "nph" scripts where
the server will essentially send whatever bytes a script generates back
to the client. I am not sure if recent versions of Apache have anything
in place to handle Upgrade requests in a special manner, or what happens
if the browser sends more data while the nph script is generating out-
put, or what happens after the script is done generating output, but if
you only need to send a certain octet sequence derived from the request,
then you will most likely be able to establish the connection in common
setups. If that allows for any notable attack is unclear for the reasons
I just mentioned.
-- 
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: Scott Ferguson <[email-masked]>
Date: Fri, 08 Oct 2010 19:20:11 -0700

Eric Rescorla wrote:
>
>
> On Fri, Oct 8, 2010 at 5:39 PM, Scott Ferguson <[email-masked] 
> <mailto:[email-masked]>> wrote:
>
>
>
>     attacker's PHP script is on the same physical and virtual machine
>     as the target is something WebSockets needs to address? Or that
>     the shared machine configuration is already so compromised that
>     complicating WebSockets to address that scenario adds no real value.
>
>

To clarify, this scenario has the attacker to run an arbitrary program 
on the same physical/virtual machine as the target. Standard 
configuration or not isn't the issue.

The issues are:

  1) When the attacker can already run a program on the same machine as 
the target, the existing vulnerabilities of that environment swamp any 
theoretical websocket cross-protocol vulnerability.

  2) The attacker has to somehow get assigned to the exact same instance 
as the target. Somehow. I'm not sure how that would be accomplished.

  3) The ISP has to be too lazy to add <Limit WEBSOCKET> to their shared 
http server.

  4) The scope of potential targets is limited to those sites unwilling 
to even pay for its own virtual instance ($11/month on rackspace). Not 
that hobby sites aren't important to their owners, but you'd need to 
argue that they're worth the effort of attacking using 1-3.

Just to clarify, that's the case we're considering.

-- Scott

---

From: Willy Tarreau <[email-masked]>
Date: Sat, 9 Oct 2010 07:54:12 +0200

> other virtual hosts that happen to be on the same physical machine,

No Adam. All what you're trying to do is to protect against a socket data
being taken as a new request. As I already said it several times now, we
just have to set "Connection: close" in the request to put an end on that.
We definitely don't want to risk that confusion !

>From draft-ietf-httpbis-p1-messaging-11 :
   7.1.2.1. Negotiation
   An HTTP/1.1 server MAY assume that a HTTP/1.1 client intends to
   maintain a persistent connection unless a Connection header including
   the connection-token "close" was sent in the request.
   ...
   If either the client or the server sends the close token in the
   Connection header, that request becomes the last one for the
   connection.

As you see, this is by definition, so we must use the close header and
we need to focus on real cross-protocol attacks, not the ones between
WS and HTTP servers based on the second request.

Regards,
Willy

---

From: Willy Tarreau <[email-masked]>
Date: Sat, 9 Oct 2010 07:57:23 +0200

> This case definitely needs to be addressed. It's a completely standard

it is correctly addressed by respecting the HTTP protocol which consists in
sending Connection: close in the request so that there is no risk that either
the web server or any intermediary consider additional data as a second request.

Regards,
Willy

---

From: Greg Wilkins <[email-masked]>
Date: Sat, 9 Oct 2010 19:18:45 +1100

> There's a PHP function does exactly that:

Interesting - I tested it with apache2 and it does allow 1xx
responses, even though they are not actually legal HTTP, specially to
send 1xx responses with message bodies.

But that's why we have defence in depth.

I tried to spoof the content-length, but apache corrected the wrong
value so that all the content the php script provided was sent as the
body of the 101 response.

Also my attempts to send a null character resulted in 501 Method Not
Implemented responses and a closed connection.

>  We should just use that instead of crossing our fingers and hoping for the best.

Your attitude that you are the only one here that cares about security
is getter rather tiresome.

---

From: Scott Ferguson <[email-masked]>
Date: Sat, 09 Oct 2010 08:59:22 -0700

> web site can trigger for an unrelated site.

Your attacker's PHP script is perfectly capable of launching a 
non-browser attack against the target server. It's not true at all that 
a HTTP request is one of the "things they currently cannot do". Can you 
explain why the attacker doesn't just launch a trivial non-browser 
attack from the PHP script?

To clarify, the target has the following vulnerabilities:

  1. It has a DELETE method available to any non-browser client on the 
internet.
  2. It has no authentication for that DELETE.

This authentication issue, by the way, is why I want a place for 
authentication in the WebSocket handshake. Since servers do need to 
protect themselves against non-browser clients, and will provide 
non-browser services, they need the ability to defend themselves against 
any attacker on the web who opens a TCP socket.

-- Scott

---

From: Scott Ferguson <[email-masked]>
Date: Sat, 09 Oct 2010 09:00:31 -0700

> WS and HTTP servers based on the second request.

+1

-- Scott

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Sat, 09 Oct 2010 18:21:13 +0200

>attack from the PHP script?

Because the target may refuse requests from the script but accept them
if they come from a certain user's browser. The server-side script can-
not, for instance, spoof the user's IP address, but the client-side one
can.
-- 
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: Eric Rescorla <[email-masked]>
Date: Sat, 9 Oct 2010 09:39:57 -0700

> But that's why we have defence in depth.

Defense in depth is an important security concept, but in general when I
design security systems, my objective is to have each layer of the defense
in depth be something I have a lot of confidence in. Certainly, I'd rather
have a single security layer that I had a very high level of confidence in
than several layers that I only sort-of-trusted.

> Implemented responses and a closed connection.

I'm generally not very persuaded by this kind of experiment. There is a huge
diversity
of Web server behaviors and so just because one server doesn't let you do X
doesn't
mean that another server doesn't. It's not really practical to have a
complete survey
of Web server behavior for the vast majority of questions.

Accordingly, I'd like to have a design that makes as minimal
assumptions about the behavior of the target server as possible and I'd like
those
assumptions to be rooted to the extent possible in behaviors which either
(1) are required by standards or (2) are required for the server to function
interoperably at all, if not both. Do you disagree?

-Ekr

---

From: Eric Rescorla <[email-masked]>
Date: Sat, 9 Oct 2010 09:43:21 -0700

> the web server or any intermediary consider additional data as a second

As I understand this suggestion, for it to provide security it relies on
servers always
treating any message with Connection: close as the final message. I don't
know if
servers always do this correctly, but since it's not really required for
interoperability,
I suspect that some do not.

All other things being equal, I would generally prefer to have a design
which failed
safely even if the server did not process Connection: close correctly. I
believe that the
design that Adam and I proposed in fact satisfies that desideratum

-Ekr

---

From: Scott Ferguson <[email-masked]>
Date: Sat, 09 Oct 2010 10:12:29 -0700

> not, for instance, spoof the user's IP address, but the client-side one

IP restrictions aren't practical because clients access sites from a 
variety of devices including mobile access points. A $2 a month server 
on a shared virtual host certainly isn't doing authentication using IP 
identification.

You're now claiming:

  1. DELETE public to the world
  2. No credential-based authentication
  3. Strong IP authentication which forbids the local host, but allows 
arbitrary browser IPs.

That's just plain nonsense. Reductio ad absurdum isn't supposed to be 
taken literally.

-- Scott

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Sat, 09 Oct 2010 22:33:05 +0200

>  3. Strong IP authentication which forbids the local host, but allows 

The scenario is: there is a web server 1.2.3.4 that supports a.example
and b.example. The attacker controls a.example, and b.example e.g. does
not allow requests coming from anywhere but a certain IP address range.
A small business for instance may be hosting a collaboration platform on
a shared server, but the platform can only be accessed from their office
network. The platform may require additional authentication, but trying
to overcome those can be part of an attack. The Websocket frames just
need to look like HTTP so the server does not close the connection. The
exchange could go like this:

(Websocket handshake)
  C: WEBSOCKET ... HTTP/1.1
  C: Host: a.example
  C: ...

(Websocket handshake)
  S: HTTP/1.1 101 Switching Protocols
  S: ...

(First Websocket frame(s) just happen to look like HTTP)
  C: DELETE / HTTP/1.1
  C: Host: a.example
  C: Content-Length: ...
  C: ...

(Whatever response the attacker feels like sending)
  S: ...

(Websocket traffic, starting from a point chosen by the attacker)
  C: WHATEVER /anywhere HTTP/1.1
  C: Host: b.example
  C: ...

By choosing the Content-Length in the HTTP-spoofing first Websocket
frame carefully, what goes to b.example can come from the free-form
Websocket payload. The attacker just needs to make sure the browser
keeps the "Websocket" connection open and the HTTP server keeps the
"HTTP" connection open, at least long enough to do something meaning-
ful; the attacker can then re-establish the connection as needed.

Right now, to take the example above, if an attacker tricks someone
in the office network to visit a.example, the options for attacks on
b.example are rather limited, for instance, only a few method verbs
are available, the browser will send a Referer header, he can't read
out the responses, and so on. If the above works, the attacker has
more options.

Obviously there are a number of ways to make this kind of attack hard
or even impossible, I just wanted it to be clear that an attacker is
not able to simply use XMLHttpRequest or something similar instead and
do all the same things.
-- 
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: Willy Tarreau <[email-masked]>
Date: Sat, 9 Oct 2010 22:40:09 +0200

> I suspect that some do not.

I really don't buy that. It's been the default mode for HTTP till 1.0 and
the default switched to keep-alive with 1.1. Supporting this header is a
huge requirement to support old browsers, crawlers and various monitoring
tools, otherwise you get back to the situation where both sides wait for
the other one to close. Saying that some servers won't support Upgrade
makes some sense, but saying that some won't support close clearly does
not.

> design that Adam and I proposed in fact satisfies that desideratum

But it causes other issues caused by its breakage of interoperability with
HTTP content-aware infrastructure components such as URL switchers and load
balancers which are already deployed in almost all shared hosting environments
(namely URLs, Host header and Cookies). So it maybe it satisfies the
requirement of protection against some types of not yet identified servers,
but it does not satisfy anymore the compatibility with existing
infrastructure.

Also, if we're talking about imaginary server implementations, why not
agree that some servers could systematically experience an exploitable
buffer overflow and fire /bin/sh everytime they receive a CONNECT request
with anything that does not look like an IP address ?

We can imagine many things, but at one point, when paranoia prevents one
from satisfying basic requirements, it must be reasonable. Especially
since the advertised goal is to protect from remotely controlled browsers
that will already be able to do much more things by exploiting plain HTTP
than what they can do with a reasonable WS handshake.

Regards,
Willy

---

From: Greg Wilkins <[email-masked]>
Date: Sun, 10 Oct 2010 08:46:49 +1100

> interoperably at all, if not both. Do you disagree?

I agree to some extent.

but note that the standards have several requirements on 1xx responses
(eg no bodies, in response to an upgrade) that the PHP script in the
supposed attack violates.  So according  to your criteria above we
would not need to consider this, even though the evidence is that a
commonly deployed server allows it.

As upgrade is an underutilized mechanism, it may be that there are
many implementations out there that do not enforce this aspect of the
specification.    This is unfortunate as it does peel back a layer of
defence that we would otherwise have.    But so long as this is a not
a necessary layer for defending initial deployments, then I think it
would be sufficient for us to raise issues on the commonly deployed
servers indicating they are breaking the specification and creating
security concerns by allowing applications to generate 101 responses.

With regards to my null trial - I agree that such "surveys" (specially
with a sample size of 1) are not really indicative, only somewhat
informative.      However, I do think we need to analyse our framing
from the perspective of could WS frames be mistaken for HTTP requests.

regards

---

From: Scott Ferguson <[email-masked]>
Date: Sat, 09 Oct 2010 17:53:01 -0700

Bjoern Hoehrmann wrote:
> network.

Then only browsers inside the target's office network are potential 
hijacked browsers.

To sum up, the following are required for the attack to work:

 1. the attacker has an account on the same physical/virtual machine as 
the target server
 2. the attacker has hijacked a browser inside the target's office IP 
2.2.2.*
 3. the target restricts access to the office IP 2.2.2.*
 4. the target is too cheap to pay $11/month for a virtual instance for 
security
 5. the ISP is too lazy to add <Limit WEBSOCKET>
 6. the target has an open DELETE method with no authentication
 
-- Scott

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Sun, 10 Oct 2010 03:22:44 +0200

> 6. the target has an open DELETE method with no authentication

Well, points 1, 5, and 6 are not quite correct. For 1, both hosts must
be behind the same IP address, how they achieve that is irrelevant. It's
perfectly possible to run them on mutually disconnected machines. For 5,
if the ISP blocks WEBSOCKET requests, that means none of the sites it is
hosting can do Websocket over port 80. If it allows it for some then the
protection is meaningless, as the WEBSOCKET request goes to the attacker
(and similarily on point 6, the DELETE request goes to the attacker). I
do not quite understand point 4, but I agree you need 2 and 3, where to
hijack a browser it is sufficient to trick someone on the office network
to open a specific web page.
-- 
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: Maciej Stachowiak <[email-masked]>
Date: Sat, 09 Oct 2010 20:41:37 -0700

> from the perspective of could WS frames be mistaken for HTTP requests.

If we encrypt the connection, as in Adam and Eric's proposal, or as suggested earlier by me, then such an analysis is not required. From the attacker's perspective, every frame they send would look like random bytes. It would not be possible to control the bytes to look like an HTTP message. Conversely it would also be impossible to make a chosen HTTP message body look like WebSocket frames.

If the attacker is unable to send specific chosen bytes as a message frame, that is a much stronger defense against cross-protocol attacks than relying on a coincidence of valid message frames not looking like an HTTP request. Or at least, it is easier to have a high degree of confidence in the analysis.

I note in passing that this defense is somewhat independent of whether to use a CONNECT-based or Upgrade-based handshake.

Regards,
Maciej

---

From: Eric Rescorla <[email-masked]>
Date: Sun, 10 Oct 2010 21:17:21 -0700

On Sat, Oct 9, 2010 at 1:40 PM, Willy Tarreau <[email-masked]> wrote:

> the other one to close.

As far as I know, it's not correct that failing to support this header
creates
deadlock.

(1) RFC 2616 does NOT require clients to send Connection: close if they
do not want to create a persistent connection. (The requirement in 8.1.2.1
is only SHOULD level.

(2) Servers are permitted (and at least the servers I am familiar with do)
to simply close the connection regardless of whether it is persistent
(i.e., regardless of whether either side sent a Connection: close).
(S 8.1.4.)

Thus, it's quite possible to implement an HTTP server which does not
deadlock
without looking at the Connection header at all, simply by having a short
timeout.

Moreover, even treating the *presence* of a Connection: close as an
indication
of there being no more requests is merely a SHOULD level requirement
(S 14.10):

  HTTP/1.1 defines the "close" connection option for the sender to
   signal that the connection will be closed after completion of the
   response. For example,

       Connection: close

   in either the request or the response header fields indicates that
   the connection SHOULD NOT be considered `persistent' (section 8.1)
   after the current request/response is complete.

Accordingly, it's not at all clear to me that it's safe to rely on
Connection: close

> Saying that some servers won't support Upgrade

It may be clear to you but it's not clear to me.

> but it does not satisfy anymore the compatibility with existing

I'm not convinced that that's true: Adam has already explained how to make
a
content aware load balancer that speaks Websockets, simply by having the
Host header appear in the encrypted portion.

> with anything that does not look like an IP address ?

I think there's a fairly obvious distinction between the assumption that
servers do not have trivially exploitable remote vulnerabilities (something
that no protocol design feature in this WG can ameliorate) and the
assumption that you appear to want to make, namely that servers will do
things
that (1) are not required for interoperate and (2) are not even MUST-level
requirements in the relevant specification.

-Ekr

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 11 Oct 2010 07:33:54 +0200

On Sun, Oct 10, 2010 at 09:17:21PM -0700, Eric Rescorla wrote:
(...)
> without looking at the Connection header at all, simply by having a short

That's what I meant with the "deadlock", we can only end the transfer on
a timeout if the client expects a close and the server does not close.
Even if the timeout is short, it makes the situation very uncomfortable
for the user.

>    after the current request/response is complete.

Indeed, however two lines below the requirement is a MUST for the client :

   An HTTP/1.1 client that does not support persistent connections MUST
   include the "close" connection option in every request message.

> Accordingly, it's not at all clear to me that it's safe to rely on

Well, the best way to wipe any doubt would be to test it on a variety of
servers.

BTW, I believe that Adam's example was that he could write a program on
a shared server that could return a valid handshake to the CONNECT request.
But since the valid response is a 200, by definition it's an establishment
of a tunnel between both sides, which ends only by the close. So once again
there is no other request on the wire after the handshake (rfc2817, #5.3).

(...)
> Host header appear in the encrypted portion.

I don't agree with that point at all. We're doing the same mistake again
that we did with -76 handshake : the intermediaries should not wait for
the connection to be completely established to take a routing decision.
Look at this very common example :

                       <--- hosting provider's infrastructure --->

                                   /---- server farm A
  client --- internet --- content <----- server farm B
                          switch   \---- server farm C

Some server farms are shared and other ones are dedicated to some
customers, which is the typical scenario we find at almost every
hosting provider's, because some customers with very poor code,
high traffic or nasty reputations can cause negative side effects
on other sites if shared on the same farms. Here, an HTTP content
switch (reverse proxy and/or load balancer) will simply look at
the host header and forward the request accordingly to the proper
server.

With Adam's proposed handshake, this is not possible anymore with
currently deployed components. We would have to implement WebSocket in
all front components just so that they can decrypt the host header and
see what farm is supposed to process it, if any at all. Not only this
is not compatible with existing HTTP infrastructure, but doing so makes
the frontend component sensible to new DoS attacks because it has to
maintain a context before even knowing if it has to handle the request.

Regards,
Willy

---

From: James Graham <[email-masked]>
Date: Mon, 11 Oct 2010 11:24:13 +0200

> maintain a context before even knowing if it has to handle the request.

I'm not sure I follow this objection. Unless I am misunderstanding 
Adam's proposal, all the information needed to access the Host header is 
in the initial client request; the only additional effort needed is to 
use the client-sent key to decrypt the headers. According to this 
understanding, one doesn't have to maintain state across requests just 
to determine if one will handle the request and, if so, with which back 
end server. Is it just the decryption that you believe represents an 
unmanagable burden?

---

From: Maciej Stachowiak <[email-masked]>
Date: Mon, 11 Oct 2010 02:34:36 -0700

On Oct 11, 2010, at 2:24 AM, James Graham wrote:

> I'm not sure I follow this objection. Unless I am misunderstanding Adam's proposal, all the information needed to access the Host header is in the initial client request; the only additional effort needed is to use the client-sent key to decrypt the headers. According to this understanding, one doesn't have to maintain state across requests just to determine if one will handle the request and, if so, with which back end server.

I agree with this understanding. With Adam's elaborations (not fully detailed in the original proposal), all the routing information is available in the initial client handshake request.

> Is it just the decryption that you believe represents an unmanagable burden?

In the unlikely case that the encryption is an unreasonable burden, I think it's possible to use a trivial form of encryption (XOR with one-time pad) instead of AES-128-CTR. But I think it's probably both safer and typically easier to use a well-known cipher.

Regards,
Maciej

---

From: Greg Wilkins <[email-masked]>
Date: Mon, 11 Oct 2010 23:28:02 +1100

On 11 October 2010 20:34, Maciej Stachowiak <[email-masked]> wrote:

> > I'm not sure I follow this objection. Unless I am misunderstanding Adam's
> proposal, all the information needed to access the Host header is in the
> initial client request; the only additional effort needed is to use the
> client-sent key to decrypt the headers. According to this understanding, one
> doesn't have to maintain state across requests just to determine if one will
> handle the request and, if so, with which back end server.
>
> I agree with this understanding. With Adam's elaborations (not fully
> detailed in the original proposal), all the routing information is available
> in the initial client handshake request.
>
> In the unlikely case that the encryption is an unreasonable burden, I think
> it's possible to use a trivial form of encryption (XOR with one-time pad)
> instead of AES-128-CTR. But I think it's probably both safer and typically
> easier to use a well-known cipher.
>

I think there are things that we can do to restrict "attacker" content in
the handshake short of encryption.

Firstly I don't think we can encrypt the host header, at least not for an
Upgrade handshake. It is part of RFC2616 that a host header should be
included and we have agreed that we must be HTTP compliant before a 101.
While the host value it is "attacker" supplied content, it has been at least
been partially validated by performing a DNS lookup, which I believe will
restrict the content to A-Za-z and a restricted set of punctuation. I think
this significantly limits the usefulness of the host name to an attacker.

Similarly, the subprotocol string is not necessarily free content for an
attacker.  We can impose a very strict token definition for subprotocol
names that will also substantially deny that as a field that can inject
anything useful to an attacker.

That leaves the URI in the handshake.   The requirement to be HTTP compliant
does not mean that we need to allow all legal URIs.  We could also restrict
the URLs to deny usage of many characters that would be needed to make a
meaningful attack.

regards

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 11 Oct 2010 07:07:18 -0700

> Even if the timeout is short, it makes the situation very uncomfortable

I don't understand what you mean here. There are two issues:

(1) when the response is finished
(2) when the connection can be closed.

Only the first affects the user experience, but they don't really interact.
Even
if the client is using persistent connections, the server still needs to
either
incorporate a length indication or terminate the response after sending the
response. In neither case does the user experience a stall.

>   include the "close" connection option in every request message.

I don't see how this is relevant. The question is whether servers
universally
treat the field's presence as an indication of no future requests.

> Well, the best way to wipe any doubt would be to test it on a variety of

No, I don't agree on this. Once you're reduced to this kind of survey you
no longer have any reasonable assurance of security. Surveys are sometimes
OK for resolving interoperability questions, but in this case you are
relying
on this property for a security purpose.

> there is no other request on the wire after the handshake (rfc2817, #5.3).

Yes, that's why using CONNECT is a desirable feature, since for
interoperability
reasons servers/proxies cannot treat data that appears in the tunnel as if
it
were HTTP traffic.

> see what farm is supposed to process it, if any at all.

Yes, I agree that this would be required. I don't agree that it's a
dealbreaker.

> Not only this
I don't see how this creates any meaningful increase in the state that must
be maintained by the infrastructure element, which must already maintain
TCP buffers, which are far larger.

-Ekr

---

From: James Graham <[email-masked]>
Date: Mon, 11 Oct 2010 18:11:40 +0200

On 10/11/2010 02:28 PM, Greg Wilkins wrote:
>
>
> On 11 October 2010 20:34, Maciej Stachowiak <[email-masked]
> <mailto:[email-masked]>> wrote:
>
>      > I'm not sure I follow this objection. Unless I am
>     misunderstanding Adam's proposal, all the information needed to
>     access the Host header is in the initial client request; the only
>     additional effort needed is to use the client-sent key to decrypt
>     the headers. According to this understanding, one doesn't have to
>     maintain state across requests just to determine if one will handle
>     the request and, if so, with which back end server.
>
>     detailed in the original proposal), all the routing information is
>     available in the initial client handshake request.
>
>     In the unlikely case that the encryption is an unreasonable burden,
>     I think it's possible to use a trivial form of encryption (XOR with
>     one-time pad) instead of AES-128-CTR. But I think it's probably both
>     safer and typically easier to use a well-known cipher.
>
>
>
> I think there are things that we can do to restrict "attacker" content
> in the handshake short of encryption.

So there is an underlying issue here that I don't understand. It seems 
clear to me that Adam and Eric's proposed handshake has a better 
security story with regard to cross-protocol attacks than -75, -76, or 
any other proposal other than using NPN with TLS. However there seem to 
be a number of people who have problems with this proposed handshake to 
the extent that they are prepared to forgo the security properties in 
order to get something different. In general people seem to be aware 
that they are making the security weaker since the arguments are mostly 
about how different approaches will probably be good enough in practice 
even though they are theoretically inferior.

What I haven't followed is what the problems with the proposal actually 
are. I understand that I have likely missed these in other messages, but 
it would be helpful if people who believe that the proposed approach, or 
aspects of it, are unworkable could summarise the outstanding issues 
they see.

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Mon, 11 Oct 2010 18:49:45 +0200

>aspects of it, are unworkable could summarise the outstanding issues 

The conceptional difference between the CONNECT proposal and the Upgrade
proposal is that the former does not re-use the normal HTTP routing in-
formation (path, host, port) meaning you may have to implement Websocket
at a higher level than you might want to. There seems to be a lack of
data if using CONNECT is problematic and/or beneficial. The only other
part of the proposal is essentially "all traffic should be randomized",
and that has been proposed for either approach.
-- 
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: Scott Ferguson <[email-masked]>
Date: Mon, 11 Oct 2010 09:56:44 -0700

>> 6. the target has an open DELETE method with no authentication

I've reordered the responses.

> I agree you need 2 and 3, where to

Necessary, not sufficient. They're not the same at all.

Your attack assumes a needle in a haystack on the part of the attacker. 
Not only must the attacker add a site to the target's own web server, he 
must hijack one of the target's own browsers while they're in the office 
which is a tiny universe of browsers.

> perfectly possible to run them on mutually disconnected machines.

Eric specifically insisted the shared machine configuration was the one 
he was worried about. If everyone agrees to drop that shared-machine 
scenario as implausible, we can move on to analyzing a proxied 
configuration. Until then, it's important to stick to one attack vector.

>  For 5, if the ISP blocks WEBSOCKET requests, that means none of the sites it is
> hosting can do Websocket over port 80. 

Adam insisted on a non-upgraded HTTP server. Until he drops that 
requirement, you can't change the attack to an upgraded WebSocket-aware 
server.

> If it allows it for some then the
> (and similarily on point 6, the DELETE request goes to the attacker).
You didn't address point #6, the open DELETE.

The target is pre-compromised because it has an open DELETE (point #6) 
and the target is pre-compromised because it's on the same machine as 
the attacker (point #1).

You're requiring a pre-compromised target to make this attack work.

> I do not quite understand point 4, but 
>   

The point of #4 is that the universe of potential targets is restricted 
to those who don't care about security. Any site can have its own web 
server for $11/month, eliminating this attack entirely. No site 
seriously concerned with security would use a shared machine 
configuration because it's basically pre-compromised.

In particular this restricts #3, the universe of browsers the target 
could hijack, because a small site with no security considerations is a 
tiny office with few target browsers.

-- Scott

---

From: Adam Barth <[email-masked]>
Date: Mon, 11 Oct 2010 09:59:17 -0700

> and that has been proposed for either approach.

The use of encryption and the use of CONNECT are indeed separable.

Adam

---

From: Adam Barth <[email-masked]>
Date: Mon, 11 Oct 2010 10:10:57 -0700

On Mon, Oct 11, 2010 at 9:56 AM, Scott Ferguson <[email-masked]> wrote:
> Your attack assumes a needle in a haystack on the part of the attacker. Not
> only must the attacker add a site to the target's own web server,

This is not as hard as you might think:

http://people.csail.mit.edu/tromer/papers/cloudsec.pdf (see Section 7).

> he must
> hijack one of the target's own browsers while they're in the office which is
> a tiny universe of browsers.

This is also not that hard.  When thinking about browser security, we
usually give this to the attacker for free.

> requirement, you can't change the attack to an upgraded WebSocket-aware

This requirement isn't going anywhere.  I was surprised that it's not
in the requirements document.  It should be.

> The target is pre-compromised because it has an open DELETE (point #6) and
> the target is pre-compromised because it's on the same machine as the
> attacker (point #1).
>

I'm not sure what pre-compromised means.  I'm not sure that I'd run my
servers in this configuration, but that doesn't mean lots of other
people don't.

> The point of #4 is that the universe of potential targets is restricted to
> those who don't care about security. Any site can have its own web server
> for $11/month, eliminating this attack entirely. No site seriously concerned
> with security would use a shared machine configuration because it's
> basically pre-compromised.

Well, we're interested in protecting the little guy too.

> In particular this restricts #3, the universe of browsers the target could
> hijack, because a small site with no security considerations is a tiny
> office with few target browsers.

Getting targeted folks to visit your web site isn't really that hard.
In fact, there's an entire industry devoted to exactly that:
advertising.  Failing that, targeted spam campaigns can also be very
effect.

By in any case, these are just the usual threat environment we work
with.  It's like asking how the attacker got a ciphertext/plaintext
pair to analyze when thinking about the security of a block cipher.

Adam

---

From: Bjoern Hoehrmann <[email-masked]>
Date: Mon, 11 Oct 2010 19:20:02 +0200

>and the target is pre-compromised because it's on the same machine as 

You are misunderstanding the example trace I gave. The DELETE is sent to
the attacker, not the target. The server 1.2.3.4 needs to think that the
client is still talking HTTP, and if the first thing it sees is "Ä§<" or
something like that, it might respond with an error message and close
the connection. "DELETE..." in US-ASCII looks like a Websocket text
frame and like HTTP, so I am using that as an example. If the attacker
manages to create the initial frames such that the web server keeps the
connection open, then he can send pretty much arbitrary HTTP requests to
the target server.
-- 
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: Scott Ferguson <[email-masked]>
Date: Mon, 11 Oct 2010 10:53:33 -0700

> connection open, then he can send pretty much arbitrary HTTP requests to

The "DELETE" represents the HTTP request that a normal browser cannot 
produce but the WebSocket request supposedly can.

The point is, a server cannot rely on browser restrictions to protect 
their HTTP site. It must defend itself against arbitrary clients which 
are perfectly capable of sending arbitrary, perfectly valid requests.

The attempt to avoid that server-side responsibility by using an IP 
restriction to a foreign site (the office) is not any kind of real defense.

-- Scott

---

From: Adam Barth <[email-masked]>
Date: Mon, 11 Oct 2010 11:02:16 -0700

On Mon, Oct 11, 2010 at 10:53 AM, Scott Ferguson <[email-masked]> wrote:
>>> and the target is pre-compromised because it's on the same machine as the
>>> attacker (point #1).
>>
> The point is, a server cannot rely on browser restrictions to protect their
> HTTP site. It must defend itself against arbitrary clients which are
> perfectly capable of sending arbitrary, perfectly valid requests.
>

I encourage you to read the archives of the W3C webapps working group.
 These issues were discussed in great depth when we were working on
CORS and UMP.  The consensus was that these things were worth worrying
about and the resultant protocols, both as specced and as implemented,
defend against these threats.  In that case, defending against these
threats was actually somewhat costly, unlike here where's it's quite
cheap.

Adam

---

From: Ian Fette (イアンフェッティ) <[email-masked]>
Date: Mon, 11 Oct 2010 13:34:10 -0700

I would really like to be able to just use NPN and call it a day. FWIW.

On Sat, Oct 9, 2010 at 8:41 PM, Maciej Stachowiak <[email-masked]> wrote:

> If we encrypt the connection, as in Adam and Eric's proposal, or as
> suggested earlier by me, then such an analysis is not required. From the
> attacker's perspective, every frame they send would look like random bytes.
> It would not be possible to control the bytes to look like an HTTP message.
> Conversely it would also be impossible to make a chosen HTTP message body
> look like WebSocket frames.
>
> If the attacker is unable to send specific chosen bytes as a message frame,
> that is a much stronger defense against cross-protocol attacks than relying
> on a coincidence of valid message frames not looking like an HTTP request.
> Or at least, it is easier to have a high degree of confidence in the
> analysis.
>
> I note in passing that this defense is somewhat independent of whether to
> use a CONNECT-based or Upgrade-based handshake.
>
> Regards,
> Maciej
>
> _______________________________________________
> hybi mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/hybi
>

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 11 Oct 2010 22:42:28 +0200

> Only the first affects the user experience, but they don't really interact.

Yes they do for components which rely on the close only and don't require
any content-length (eg: most monitoring tools). If the server did not care
about the close in the request and waited for a second request instead of
closing, the client would wait for the server to close to determine the
end of the response, which is after the keep-alive timeout of the server.

> response. In neither case does the user experience a stall.

This is mandatory for persistent connections only. While it's recommended for
other connections, we still see some servers that don't advertise a content
length for HTTP/1.0 request (even Tomcat until very recently).

> relying on this property for a security purpose.

I still think that since the complexity of the hanshake only relies on a fear
of massive attacks making use of browsers and shared hosting environments, if
we fail to find a deployed vulnerable servers, the massive attack risk
vanishes. It's not to say that no braindead server could not be attacked,
but that such a vector is basically useless.

> it were HTTP traffic.

And that's also why there cannot be a second request after the 200.

> Yes, I agree that this would be required. I don't agree that it's a

Well, first it's not compatible with any existing infrastructure, which is
a bit limited outside of the lab. Second, it means that the front server
would first have to acknowledge a WS handshake on behalf of any possible
server behind it and finally have to return in WS frames a "Sorry man, I
thought I could hand that connection to someone but there's nobody where
you want to go".

> TCP buffers, which are far larger.

Exactly, it *has* to maintain TCP buffers as well as contexts, it cannot
filter based on anything advertised in the handshake.

Right now in HTTP, it's easy to put very short timeout for the accept to
request steps because both are not subject to the RTT, so the request must
appear very quickly after the accept. Then the component just has to proceed
with the request and possibly reject it ASAP.

Here with the proposed handshake, you have to do the same thing, but then
send a WS handshake with a ping and wait for the pong for quite a longer
time (RTT) *just to know* if you have to handle this connection. In my
opinion, it makes DoSes much more easy to perform on such components than
what is currently possible.

All that is just based on the fact that we fear that some components will
accept to process an HTTP request after both a "Connection: close" and a
CONNECT that returns a 200.

I'd be tempted to suggest that such broken implementations simply deserve
to be taken down...

That said, even if we want to cover that, we could also make it mandatory
to prefix the first frame in each direction with a pattern made of impossible
HTTP bytes such as "0x00 0xFF".

Regards,
Willy

---

From: Ian Hickson <[email-masked]>
Date: Mon, 11 Oct 2010 21:04:08 +0000 (UTC)

> aspects of it, are unworkable could summarise the outstanding issues 

I would like to ask a similar question, but to the people proposing Adam 
and Eric's latest proposed handshake. What real problem does it solve that 
NPN with TLS doesn't solve? As you say, it is weaker than NPN with TLS, so 
why not just go all the way?

This would have multiple advantages beyond just being more secure, for 
example we could halve the number of schemes we're introducing, halve the 
number of handshake implementations on both clients and servers, greatly 
reduce the testing burden, etc.

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 11 Oct 2010 23:12:28 +0200

Hi Ian,

> reduce the testing burden, etc.

And unfortunately prevent content analysis in schools, and be blocked by
default in many enterprises, and probably make virtual hosting impossible,
unless the target resource can be announced in the TLS setup, which I'm
not sure is possible with NPN.

In fact, I think that if the WS work was started, it was to get rid of the
mechanisms relying on long polling. And those mechanisms were invented
because only HTTP passes everywhere. If we propose something which is
not compatible with currently deployed HTTP infrastructures, we'll then
still keep the current mechanisms and have WS proposed as an Nth alternative
for some situations, which will definitely make the situation worse for the
user and for the developer.

That need of compatibility with already deployed HTTP infrastructure seems
to be dismissed too much in this WG in my opinion, and I don't think I'm
wrong to predict a success directly dependant on this compatibility.

Regards,
Willy

---

From: Adam Barth <[email-masked]>
Date: Mon, 11 Oct 2010 14:12:56 -0700

> why not just go all the way?

I'd prefer to use TLS+NPN, but we put forward the newer proposal as a
compromise.  Technically, the cost of using NPN+TLS is one additional
network RT and the need to involve/update your TLS library to set up a
WebSocket server.

> reduce the testing burden, etc.

Indeed.

Adam

---

From: Ian Fette (イアンフェッティ) <[email-masked]>
Date: Mon, 11 Oct 2010 14:18:25 -0700

Willy,

People are welcome to use the null cipher suite with TLS.

---

From: Adam Barth <[email-masked]>
Date: Mon, 11 Oct 2010 14:20:13 -0700

Or just use the ws version that doesn't check certificates (as opposed
to the wss version that does).

Adam

---

From: Patrick McManus <[email-masked]>
Date: Mon, 11 Oct 2010 17:29:35 -0400

On Mon, 2010-10-11 at 21:04 +0000, Ian Hickson wrote:

> NPN with TLS doesn't solve? 

Alternatives to NPN do not require a totally independent spec, which has
not passed through a standards process, to be widely deployed before the
websockets implementation can be used at all. TLS is often terminated
separately from HTTP and under very different administrative policies. A
number of those NPN capable deployments would need to replace embedded
TLS implementations and other
paperwork-heavy-because-it-is-a-security-device servers which are going
to have long half lives.

I really think an NPN dependency is a non starter for that reason. We've
made compatibility with 443/80 a goal because it passes through existing
infrastructure and non-NPN aware devices are part of that
infrastructure.

A world with NPN we could depend on would be great, but I don't want to
tie websockets down to wait for it - but I am really pleased to see the
nuts and bolts of connect and upgrade being sorted through.

-Patrick

---

From: Ian Fette (イアンフェッティ) <[email-masked]>
Date: Mon, 11 Oct 2010 14:29:56 -0700

Sorry for the over-brief response. I was assuming in the world of an NPN
handshake that wss:// would use a strong cipher suite and check that the
certificate is valid, and that in the world of ws:// the NULL cipher suite
would be used, and the certificate would not be checked for validity (e.g.
self-signed cert would be fine.)

-Ian

2010/10/11 Adam Barth <[email-masked]>

> >> > > it would be helpful if people who believe that the proposed
> approach,
> >> > > or
> >> > NPN with TLS doesn't solve? As you say, it is weaker than NPN with
> TLS,
> >> > so

---

From: Willy Tarreau <[email-masked]>
Date: Mon, 11 Oct 2010 23:41:25 +0200

> People are welcome to use the null cipher suite with TLS.

OK, but that would void the initial point that made Adam want it : the
unpredictability of the bytes in the outgoing stream in order to avoid
cross-protocol attacks.

Willy

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 11 Oct 2010 15:22:38 -0700

> end of the response, which is after the keep-alive timeout of the server.

I don't see how this makes sense. Regardless of the setting of Connection:
close
if the server is not going to either put a length field or chunked encoding,
it
needs to close the connection at the end of the response. Timeouts don't
enter into it. I don't know what you mean by "monitoring tools" here...

> This is mandatory for persistent connections only.

It's not an issue of mandatory or not. It's an issue of minimal
functionality.

> While it's recommended for

I don't understand what point you're making here. It's entirely possible for
a
server to be interoperable while ignoring Connection: close simply by always
using a length field/chunked encoding and using a timeout. This leads to
neither
deadlock nor interop problems. If you think there is an interop problem
here,
please describe the sequence of events that causes it. If not, then I don't
see
how you can rely on proper Connection: close behavior as a security feature.

> but that such a vector is basically useless.

Who said anything about "massive attacks"? That's not my concern. My concern
is deploying a new feature which makes otherwise secure systems insecure.

> And that's also why there cannot be a second request after the 200.

Yes, that's my point. That you can't really have an interoperable CONNECT
implementation at all without ignoring everything after the 200. By
contrast,
you can have an interoperable implementation while ignoring Connection:
close.
This is why I feel more comfortable relying on the CONNECT behavior than
on Connection: close.

> a bit limited outside of the lab.

Yes, I agree it requires an infrastructure change. I don't agree that it's a
dealbreaker.

> Second, it means that the front server

No, this is not correct. The server can process the entire handshake,
including
the encrypted destination portion, and then only after that respond to the
request.
This requires, as Adam suggested, having the initial "Host" block encrypted
with a key supplied only by the client.

> filter based on anything advertised in the handshake.

Again, this is incorrect. All the relevant material appears immediately
after
the TCP handshake.

> CONNECT that returns a 200.

I really don't understand what aspect of Adam or my proposal you're arguing
against
here.

> to be taken down...

Given that those implementations are compliant with 2616, I don't know on
what
basis you claim that they are broken.

-Ekr

---

From: Scott Ferguson <[email-masked]>
Date: Mon, 11 Oct 2010 17:00:02 -0700

James Graham wrote:
> any other proposal other than using NPN with TLS. However there seem 
> to be a number of people who have problems with this proposed 
> handshake to the extent that they are prepared to forgo the security 
> properties in order to get something different. In general people seem 
> to be aware that they are making the security weaker since the 
> arguments are mostly about how different approaches will probably be 
> good enough in practice even though they are theoretically inferior.
>
> What I haven't followed is what the problems with the proposal 
> actually are. I understand that I have likely missed these in other 
> messages, but it would be helpful if people who believe that the 
> proposed approach, or aspects of it, are unworkable could summarise 
> the outstanding issues they see.

Some of the problems with the proposal:

1. auditing - the proposal takes away the capability to audit requests 
after an attack. Remember, cross-protocol is not the only kind of 
attack. Server admins will want to track down access logs to find the 
problem, but the proposal makes these request log opaque to the server 
admins.

2. authorization - since the proposal no longer uses URL/method and 
specifically doesn't use a unique WEBSOCKET method, existing security 
systems in existing servers cannot be used. (<Limit>, .htaccess, etc.)

3. incompatibility with existing host/application dispatch models. In 
existing servers, the URL/host are used to dispatch to the server before 
processing. This proposal upends that model, requiring WebSocket to be 
dispatched before knowing the target resource.

4. performance - the proposal requires encryption of the entire data 
stream. That's not cheap on the server side.

To justify these security, performance, and management penalties, the 
proposal proposes an attack which requires the target machine to run an 
attacker program, assumes the target web server is under the control of 
the attacker, and assumes the target application has an additional open 
security hole to non-browser clients.

-- Scott

---

From: Scott Ferguson <[email-masked]>
Date: Mon, 11 Oct 2010 17:05:06 -0700

> servers in this configuration, but that doesn't mean lots of other

1. Your target has an open vulnerability ("DELETE") to non-browser clients
2. Your attacker is running an arbitrary program on the same machine as 
the target.
3. Your attacker has control over the target's web server.

That target server is already under the control of the attacker. Adding 
a browser attack to that scenario is superfluous.

-- Scott

---

From: Adam Barth <[email-masked]>
Date: Mon, 11 Oct 2010 17:10:22 -0700

On Mon, Oct 11, 2010 at 5:05 PM, Scott Ferguson <[email-masked]> wrote:
>>> and
> 2. Your attacker is running an arbitrary program on the same machine as the
> target.
> That target server is already under the control of the attacker. Adding a
> browser attack to that scenario is superfluous.

We'll just have to agree to disagree on that point.  This scenario is
one that browser vendors are interested in defending against.

Adam

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 11 Oct 2010 17:11:08 -0700

> 2. Your attacker is running an arbitrary program on the same machine as the

I'm not going to argue about the rest of these, but as I've said before,
this is absolutely
a standard case. It's how shared hosting works, and I (and near  everyone
else) expects the
relevant machines to be configured in a way that it's not simple for
customers to attack
each other directly via this mechanism. cf. jails, etc.

-Ekr

---

From: Maciej Stachowiak <[email-masked]>
Date: Mon, 11 Oct 2010 19:14:13 -0700

On Oct 11, 2010, at 5:00 PM, Scott Ferguson wrote:

>> So there is an underlying issue here that I don't understand. It seems clear to me that Adam and Eric's proposed handshake has a better security story with regard to cross-protocol attacks than -75, -76, or any other proposal other than using NPN with TLS. However there seem to be a number of people who have problems with this proposed handshake to the extent that they are prepared to forgo the security properties in order to get something different. In general people seem to be aware that they are making the security weaker since the arguments are mostly about how different approaches will probably be good enough in practice even though they are theoretically inferior.
>> 
>> What I haven't followed is what the problems with the proposal actually are. I understand that I have likely missed these in other messages, but it would be helpful if people who believe that the proposed approach, or aspects of it, are unworkable could summarise the outstanding issues they see.
> 
> 1. auditing - the proposal takes away the capability to audit requests after an attack. Remember, cross-protocol is not the only kind of attack. Server admins will want to track down access logs to find the problem, but the proposal makes these request log opaque to the server admins.

It doesn't take away that capability - just means a WebSocket aware server needs some additional logging code.

> 2. authorization - since the proposal no longer uses URL/method and specifically doesn't use a unique WEBSOCKET method, existing security systems in existing servers cannot be used. (<Limit>, .htaccess, etc.)

For servers that are not modified to be aware of WebSocket, this is true, but probably not very relevant since WebSocket connection attempts will fail. For servers that are updated to support WebSocket, that doesn't have to be true.

> 
> 3. incompatibility with existing host/application dispatch models. In existing servers, the URL/host are used to dispatch to the server before processing. This proposal upends that model, requiring WebSocket to be dispatched before knowing the target resource.

Adam's revised design allows for this, but it would require servers to be updated to decrypt the extra URL and host fields, after which they could be passed through the ordinary dispatch logic.

> 
> 4. performance - the proposal requires encryption of the entire data stream. That's not cheap on the server side.

If AES-128-CR is too computationally expensive (and I really doubt it is), the proposal works fine with simpler ciphers. However, I believe modern server-class hardware can do streaming AES-128 at a rate that would significantly outpace even the fastest network hardware, so I would be skeptical that this is going to be the bottleneck absent some data.

I'm pretty convinced that encrypting the message payload, even if not the handshake header, is pretty much essential, even if it is only dumb encryption like XOR with the key. There is almost no downside and it greatly reduces the attack surface.

> 
> To justify these security, performance, and management penalties, the proposal proposes an attack which requires the target machine to run an attacker program, assumes the target web server is under the control of the attacker, and assumes the target application has an additional open security hole to non-browser clients.

I would put it another way. It replaces security-by-coincidence with a provable invariant. Instead of having to bet that no WebSocket stream will ever happen to look like an understandable part of another protocol, you make sure an attacker using WebSocket can only send a fixed prelude plus what will seem to be random bytes, and a WebSocket service being attacked with HTTP will only see random bytes after decrypting.

Also, the Adam+Eric proposal actually has a significant performance advantage over Greg's proposed handshake, namely fewer round trips. Even if this effect does not dominate today (and I suspect it does), cpu speed grows much faster than network latency shrinks.

Regards,
Maciej

---

From: Willy Tarreau <[email-masked]>
Date: Tue, 12 Oct 2010 07:11:57 +0200

On Mon, Oct 11, 2010 at 03:22:38PM -0700, Eric Rescorla wrote:
> enter into it.

I'm not saying that the server is not going to put a length, but that the
client is not going to make use of it because it's either an old one or a
simple one. All clients that rely on "Connection: close" are free to ignore
content-length, and that's sometimes for this exact reason that they add
this header.

In short you would have this if the server ignored "Connection: close" :

Req> GET /server-status HTTP/1.1
Req> Host: localhost
Req> Connection: close

Res> HTTP/1.1 200 OK
Res> Content-length: 3
Res>
Res> OK

And now the server waits for the client to send a new request, while the
client waits for the server to close.

> I don't know what you mean by "monitoring tools" here...

All simple tools that you find everywhere in prod environments to ensure
the service is OK. Scripts can either make use of the very common netcat
utility, of any home-made TCP client or even make use of the shell like
this :

#!/bin/bash
ip=$1; port=$2
exec 3</dev/tcp/$ip/$port
printf "GET /server-status HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n" >&3
read -t 3 -u 3 ; set -- $REPLY; status=$2
(date;echo "$1:$2: $status";echo;
 while read -t 3 -u 3; do
    echo $REPLY
 done
) >> log.$ip.$port

(...)
> please describe the sequence of events that causes it.

Precisely as explained above, the client generally sets "Connection: close"
to indicate that it can only rely on the close and will probably not care
about the Content-length header. Emitting/parsing content-length is not a
requirement if you don't intend to use a persistent connection. Most
versions of tomcat (even recent ones) made use of that asumption to avoid
sending the content-length and transfer encoding when they saw "Connection:
close".

> If not, then I don't

It's not a matter of a security feature, it's that "Connection: close" has a
strong enough semantics which means "terminate this request with a close as
you did in the old days, I won't parse your length headers anyway". So if the
connection is closed after processing the first request, you won't be using
the connection to send a second request.

(...)
> is deploying a new feature which makes otherwise secure systems insecure.

OK, so basically we're looking for a shared hosting environment that offers
low-cost accounts to various people with PHP scripting, who does not know
about "Connection: close", who does not know that CONNECT+200 is a tunnel,
and if we find such a hosting provider, we should make sure that the handshake
cannot be abused by one of their customer to send a request to another of
their customers... Do you seriously think that such a broken provider's
security only relies on a complex WS handshake ? I'd guess that given that
we manage to find *one*, it would have other serious issues such as HTTP
request smuggling and things like this.

> implementation at all without ignoring everything after the 200.

I agree with that, and that's one of the reasons I proposed CONNECT too
some months ago.

> By contrast,

I understand your point given the wording in the spec even if from
experience I don't agree.

> Yes, I agree it requires an infrastructure change. I don't agree that it's a

Here I don't agree. WS was supposed to make use of existing infrastructure.

> with a key supplied only by the client.

Then there's something I did not understand, because from what I understood
of his proposal, the Host was supposed to be sent after the handshake so
that the handshake contains nothing that can be controlled by the user.
BTW, I don't even agree with that goal, because if we want to be compatible
with HTTP, we can make use of the regular HTTP headers without any worries.
Whether the browser fills a Host header in a WS request or in an HTTP request
makes no difference. It will just fill it correctly. Even cookies work fine.
There's no need for encryption there. Let's just respect standard HTTP.

I agree about having an invalid host name in the CONNECT request though, in
order to avoid possible forwarding on real proxies. But let's have the Host
header hold the real information in clear text.

Regards,
Willy

---

From: Patrick McManus <[email-masked]>
Date: Tue, 12 Oct 2010 14:55:25 -0400

> IP restrictions aren't practical because clients access sites from a 

IP ACLs have limited value, but I see them all the time. A friend asked
me for a little apache administration help just the other day and it
turned out he had an Apache server running a bunch of content that could
be accessed either via http-basic auth or IP ACL. The 'office' network
was in the IP ACL whitelist, other users had to login.

In his case it wasn't a shared host, but that was a coincidence.

Its real.

---

From: Patrick McManus <[email-masked]>
Date: Tue, 12 Oct 2010 14:55:30 -0400

On Sat, 2010-10-09 at 22:40 +0200, Willy Tarreau wrote:

> I really don't buy that.

Unfortunately, Willy, I do buy it. I think I may have even implemented
such a server :(

As you know the side that issues the active TCP close goes into
TIME-WAIT.. My server was actually a very busy intermediary and I was
trying to avoid building up a gigantic pile of close-waits on it... so
the server side would not close the connection immediately after
completing the response unless it needed to do so to delimit the
response. instead it would presume that if the client didn't want a
persistent connection it would close the socket pretty soon itself so I
tossed it in the persistent reuse pool with a very short timeout -
anticipating that the active FIN would arrive from the client before the
timeout expired -  Which turned out to be true - I never saw a case of a
client depending on the server closing the connection other than in
cases without (at least) a Content-Length in the response. If the client
went ahead and sent another request I presume the code would have
dispatched it normally even though the previous one said "close", I
don't have access to the code to check it right now.

> tools, otherwise you get back to the situation where both sides wait for

Either side is free to close at any time, right?

> makes some sense, but saying that some won't support close clearly does

I would agree with this regarding the "connection: close" response
header, but not the request header. It is largely meaningless.

---

From: Willy Tarreau <[email-masked]>
Date: Tue, 12 Oct 2010 21:27:00 +0200

Hi Patrick,

> Unfortunately, Willy, I do buy it. I think I may have even implemented

Interesting. Thanks for publicly admitting it. However, I hope that
your server did not return a 200 in response to a CONNECT request ?

> trying to avoid building up a gigantic pile of close-waits on it...

time-waits and close-waits are very different. Time-waits are harmless
and expected. Close-waits denote a lack of close from the application
in response to a received close, on the side where they're observed.
This happens close to the end of some transfers during a short time.
Generally if they last long, it indicates an application bug, unless
the protocol supports that state (eg: a unidirectionnal FTP data
connection, or even a file transfer over HTTP when the client has
shut the send side down). Hmmm we're getting out of topic, if you're
interested, we can discuss that off-list.

> cases without (at least) a Content-Length in the response.

In practice, connections from browsers are always HTTP/1.1 and generally
result in the servers returning a valid content-length, which the browser
always correctly interpretes. Amusingly I've seen some WAP gateways send
1.0 requests, which on some servers don't result in a content-length, thus
make the client rely on the close.

> If the client

OK.

> Either side is free to close at any time, right?

Yes, perfectly. Even intermediaries are free to do so. What I indicated above
was in the context of timeouts (wait for other side to close or timeout to
strike).

> header, but not the request header. It is largely meaningless. 

Not from my observations to be honnest. It is even sometimes wrongly assumed
to be equivalent of HTTP/1.0, resulting in the server refraining from using
chunked encoding.

But thanks, at least now we have one case where Connection: close would not
have worked.

Regards,
Willy

---

From: Patrick McManus <[email-masked]>
Date: Tue, 12 Oct 2010 15:58:55 -0400

> your server did not return a 200 in response to a CONNECT request ?

It did not, because it was not that kind of proxy (it was a transforming
proxy of sorts in the SOAP and XML Web Services space) - it probably
returned 501 but I don't really recall for sure. There are lots of them
still in use, but none on the public Internet that I am aware of. (I'm
no longer with that employer.)

But it was a proxy (I know I said server - but I didn't say origin
server :)) and certainly it would have been reasonable to setup a valid
tunnel with a 200 in response to a well formed and configured-policy
valid CONNECT request if that functionality would have been useful.