Re: Feedback on WebSocket API, Editor's Draft 13 November 2009.

On Sat, Jan 30, 2010 at 10:31, Ian Hickson <ian@hixie.ch> wrote:
> Right now, today, if I were to expose a WebSocket service on my Dreamhost
> shared server, I could do so without any trouble. If we used a scheme such
> as the one described above using a policy file, anyone else also hosting
> their site on the same server could grant access to my server to their
> scripts on their page. Whether this is a technical or administrative
> issue, it's an issue we have to handle today.

If you only allow the policy file from being read from a single port
and that port is controlled by the service provider, then it is
possible to administrate this (together with other measures). With
both flash and Silverlight you have that ability, serve the policy
file from port 843 for flash and 943 for Silverlight and for flash say
in the file that it may not be overridden. For flash, if the service
provider doesn't administrate it, any other user of their site can
serve their own policy file on any port and grant flash access to your
Web Socket service. It is of course quite possible for flash to
connect to your service and provide any origin it wants. In your
shared host scenario another user can also try to grab "your" port
before your program starts; shared resources require administration.
A java applet can at least connect back to the same IP number as it
was downloaded from, so another user on the shared host can publish
such an applet.

[snip]
> IMHO, yes. I understand that security is a tradeoff between risk and
> reward, but fundamentally, it seems to me that it is far off the
> "risk/reward" scale to design a system in such a way that a security
> problem cannot be fixed when it is discovered. Having the user agent cache
> the security policy and act on that cached version even after a security
> problem has been found prevents security problems from being fixed in a
> timely manner.

Sure, it would cause a downtime, just like a misconfigured DNS entry
can, so good administrators develop routines around it. But to talk
about risk, one would have to talk about the chance of it happening,
the cost of it when it happens and compare that to what the benefit is
when it doesn't happen. I think it would have to happen quite often,
or the service would have to cost quite a lot when it is down for it
to make up for the extra cost of rewriting existing services.

>> The general solution is to have an opt-in system like flash's policy
>> files.
>
> This is not a possible solution if, as you suggest above, we send both
> requests simultaneously.

It would be a slightly more complex solution, but as soon as the
policy file is read, close the second port and don't allow another
"fast connect" until the policy file has been read again if it didn't
allow the access.

> It's also not possible in general, since as HTTP
> is also able to be used for this attack, one can simply tell the UA that
> the policy file is on the victim port, and have _that_ stage DOS the
> server instead of the actual Web Socket connection.

Unless one specifies a specific port and only allows them to be
downloaded from there (or uses a master file that says if is allowed
to serve a policy file from another port). A good implementation can
also avoid connecting to the policy port more than once at a time, but
a good Web Socket implementation can't prevent the javascript from
trying to connect to the same port many times since it can be legit
for the higher level protocol.

[snipped section about connecting to existing services]

> This is also not what Web Socket is designed to address, so it's not
> surprising that it can't handle this case. It also isn't a good protocol
> for implementing a generic document retrieval system, or peer-to-peer data
> transfer, or doing video multicast. These are not failings, per se,
> they just weren't use cases that Web Sockets was designed for.
>
>> I expect the same two scenarios would come up in most cases where you
>> want to use a web client against an existing tcp service.
>
> Absolutely. Web Sockets was specifically designed to make it impossible to
> connect to an existing TCP service, in fact, specifically to avoid
> situations such as poor policy file configurations allowing an SMTP
> server to be hijacked for sending spam.

Yes, I understand that and I think you are throwing out the baby with
the bathwater here, considering that this is how Silverlight and Flash
works and html5 competes in many ways with them.

>> The WebSocket protocol services would also be vulnerable to malicious
>> code and instead of just having one implementation in each web browser
>> that matches the origin with the port to see if a connection is allowed,
>> that code would have to be added to each WebSocket protocol service and
>> perhaps by less skilled programmers than the browser developers.
>
> I don't understand the attack scenario here. Can you elaborate?

I'm just saying that instead of the (four?) big browser implementors
adding support for some policy file and plain old TCP sockets, each
TCP service that one wants to have accessible via Web Socket will have
to be updated. In some of those cases there will be bugs that will
lead to security errors. I do believe the browser implementations
would both be of higher quality and audited more than the average
server implementation.

>> The WebSocket protocol has a higher cost and it seems to me that the
>> risks are equal, but different. Given that flash already uses TCP and
>> policy files, the risk of reusing it would not increase since I don't
>> think flash is going away soon.
>
> Flash is one of the main reasons I avoided policy files. While the
> vulnerabilities may not have been widely advertised, Flash policy files
> have in fact been the subject of _numerous_ attack scenarios.
>
> Two widely-reported cases are:
>   http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-6243
>   http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-4822

The first case is from the time before the current policy files were
developed (with respect to sockets), so it can hardly be a case
against it.

The second case is about Adobe's implementation not making use of the
policy files, an implementation error, right? All it would take is to
forget to call a single function (I've done it myself in a server's
authorization routine). What has that got to do with the concept? It
seems more like a problem with Adobe's development and QA processes
and says nothing about how complicated it would be. Considering that
the current implementation also seems correct (and has been copied by
Silverlight) does however prove that it can be implemented correctly.

> It's probably possible to make a secure implementation of this strategy.
> It's just not as simple or as easy as the direct approach Web Sockets
> uses, IMHO.

The difference is of course that the policy file would only have to be
correctly implemented in each client that wants to make use of it, but
the Web Socket protocol would ALSO have to be implemented in each
server that wants to be accessible via it, thus there will be more
implementations and more risks of bugs. The "each client" set is also
larger for the Web Socket protocol compared to plain old TCP with a
policy file if one wants to make a native client against some new
service.


To summarize:

With the Web Socket protocol:
- Existing services would have to be changed if they should be
accessible (with the risk of bugs, duplication of existing access
control and logging).
-- This is a huge total cost and a huge potential for security problems.

- Requires all new services to implement the policy mechanism correctly.
-- Instead of just having a few correct implementations in the clients
(that already have code for origin handling and whose designers
hopefully are aware of the problems), each server will have to have it
with associated risks of errors. A huge potential for new security
problems. Will of course be cheaper and less risky when libraries are
available for most languages, but still many more implementations.

- Native clients against a new service would have to use the Web
Socket protocol too.
-- Adds a little extra cost and risks. Will of course be cheaper and
less risky when libraries are available for most languages, but still
way more implementations. What about someone adding support for Basic
authentication in their client, exposing the credentials?

- One can't prevent a client from connecting to a port that it should
not be allowed to connect to, but the client can't start
communications.
-- Yet another DoS vector, but as you've written, there are others so
then it is ok?

- Can be used for port mapping.
-- But as you've written, there are other ways, so then it is acceptable?

- Part of the security of the protocol relies on the fact that the
clients can't use "raw" TCP sockets. This is not always true if the
client has the flash, java or the Silverlight plugins. What about
future plugins or APIs?
-- During a transition phase to html5, I would think that people would
simulate the Web Socket API via scriptable flash clients since most
users already have it installed, so this would probably become rather
common. Someone might also do the same via Silverlight.

- Makes it simpler to implement authentication and SSO against Web
Socket services.


With plain TCP and a policy file mechanism:
- This is how flash and Silverlight works today.

- Most existing TCP services can be used, if the administrator wants it.
-- Doesn't cost anything extra on the server side to allow a service
(except another line in a policy file) to be used by web apps.

- The loading of the policy file introduces latency at connection time
unless caching and/or dual connections are used:
-- If dual connections are used, one can't prevent a client from
connecting to a port that does not want to be connected, but the
client can't communicate.
--- Yet another DoS vector, but can be limited to one connection per
client by careful implementation.
-- If caching is used, the administrator can't prevent clients to try
to connect until the timeout has happened.
-- This is really up to each implementation and they can start simple
and accept the latency.
-- Existing TCP services (with the exceptions of HTTP and FTP in some
cases) are rather long lived so it might not be such a big problem,
especially if one has it in mind when developing new protocols.

- Unless caching is used, there is a slight extra network overhead for
each additional connection.
-- With caching there is less overhead once the policy file is cached
(until it has timed out).

- All existing services on a host can also be accessed via javascript,
IFF the administrator makes a misstake.
-- Is mostly a problem with services that authenticate via the IP
number, like some SMTP implementations, but can also be a problem with
DoS attacks and password cracking malware.
-- Might lead to downtime of the affected service if caching is used
when correcting the misstake.
-- Common protocols can easily be secured by additional policies in
the browsers.

- Authentication/SSO is slightly harder to implement against new services.
-- A future extension to the API could help, especially against
existing services.
-- Many protocols would probably use secure session tokens instead
since they are easier to verify in a server.

- Only javascript clients would have to implement the policy loading mechanism.
-- Adds no extra cost for native clients accessing new services.

- A policy file would have to be shared on shared hosts.
-- Will cost slightly more in shared hosting environments, but this is
a problem that already exists for silverlight and flash.


To me, the total risk and cost of the Web Socket protocol is higher
than the total risk and cost of allowing TCP with policy files.

A good implementation of either should IMO also give the user the
ability to blacklist ports and IP ranges, for example SMTP and HTTP
might be black listed by default, no matter what the downloaded policy
file says, so risks of DoS attacks, port mapping, password cracking
etc against internal and common services could in both cases be
lowered by the default browser configurations. Or perhaps do as
Silverlight do and only allow a limited range of ports, then use NAPT
to remap them to other ports if needed.


Risks and costs aside; to me the Web Socket protocol competes against
silverlight and flash. It provides a few things better - the
integrated authentication credential transfer, the simplicity of
packet communication and the lower connection latency, but at the huge
cost of more complex servers, not being able to reuse services and
protocols that today speak with deployed flash, silverlight or native
clients. Adding a packet interface above a streaming protocol is
trivial and there would shortly be plenty of javascript libraries that
provides it if the need exists. So the only thing that sells the
protocol to me is the build in credential transfer method, but in
practice I would probably use a secure session token instead and
verify it at connection time since it would be much simpler than
having to duplicate the authentication and authorization code of the
http server in my service. A nice SASL/GSS-API implementation on the
other hand, that would add a lot of value.


And for interested parties:
The policy of silverlight:
http://msdn.microsoft.com/en-us/library/cc645032(VS.95).aspx
Flash: http://www.adobe.com/devnet/flashplayer/articles/flash_player_9_security.pdf

Regards,
/Sebastian
-- 
One laptop per child project: http://laptop.org/

Received on Sunday, 31 January 2010 14:36:59 UTC