[Development] websockets (was RE: Qt 5.3 Feature freeze is coming quite soon...)

Konrad Rosenbaum konrad at silmor.de
Wed Jan 29 09:45:55 CET 2014


Hi,

[Warning: this mail is kind of lengthy]

I read the RFC for WebSockets and some of the material describing the attacks 
that masking is supposed to mitigate.

Now that I'm through I'm quite disappointed: it was less funny than I thought. 
The RFC is just not very good at explaining the security background of 
seemingly strange specs.

I now also understand why masking needs strong random. Sadly.

One piece of strangeness remains: I can't for the life of me figure out why 
the handshake has to use a cryptographic hash algorithm, when a simple header 
value would have sufficed. On the part of the paper (link below) I guess it is 
typical of cryptographers to use cryptographic tools to the exclusion of 
simpler tools, on the part of the RFC authors ... I don't know...?

On Monday, Monday 27 January 2014 at 11:12, Konrad Rosenbaum wrote:
> On Sunday, Sunday 26 January 2014 at 23:46, Richard Moore wrote:
> > The aim of the masking is to prevent request splitting and smuggling
> > attacks when going through proxies. It prevents an application from
> > being to trick proxies into beginning a new request that does
> > something different to the one intended.
> > 
> > https://www.owasp.org/index.php/HTTP_Request_Smuggling
> 
> Thanks for the link, this is an interesting attack on faulty proxies.

The original paper on how these attacks relate to websockets:
http://w2spconf.com/2011/papers/websocket.pdf

Let's formulate a more understandable threat model than was done in the RFC:

The masking is supposed to protect explicitly configured and transparent 
proxies (some of which are badly broken and vulnerable, ie. the normal 
deployment for many large corporations) from malicious active web content. 
Specifically against various attempts of cache poisoning (in which the proxy 
is made to cache the wrong content for a URL) and IP hijacking (in which the 
proxy briefly redirects a request to the wrong server).

In laymans terms: The conclusion of the paper was that if the script or 
flash/java applet running in the browser is able to control any part of the 
content that is sent over the wire enough to inject something that looks like 
an HTTP header (even if it is technically at the wrong position in the stream) 
then some proxies are idiotic enough to actually interpret these as part of an 
HTTP exchange, sometimes redirecting the traffic, sometimes just accepting 
anything at face value. The rest of the company now will get an attack kit 
delivered instead of their morning news or the browser may be tricked into 
allowing an attack applet that it should not have allowed (one which comes 
from the wrong server, but still gets access to the open tab and its content).

To be explicit about it: the masking does not (as we assumed) try to protect 
the data that is being transmitted from eavesdroppers. Instead it tries to 
protect badly maintained infrastructure (and different users on the same badly 
maintained network) from malicious scripts run in an usually trusted program. 
In other words: the WebSocket spec tries to clean up after lazy and idiotic 
proxy programmers and admins (sorry, I don't have a better term for them).

The masking does explicitly not defend against stand-alone applications that 
the user starts outside the browser. This kind of magic is beyond the mere use 
of bits...

Consequently it does also not defend against malicious browsers. Which are a 
kind of application after all...

Let's translate this into scenarios which are relevant for Websockets in Qt:

Someone creates a browser with Qt (it has been rumored to have happened) and 
uses this Websocket implementation to give scripts access to their servers. 
Earlier or later some weird script (embedded in some flaky advertisement for 
unsavory products) decides to poison the local proxie's cache.

This can be generalized to: any Qt based application that uses Websockets and 
allows content from outside the app to control such a socket can be used to 
mount this attack against a vulnerable proxy. A local user scripting his app 
may be less likely to screw up his own environment...

On second thought: consider local users as good a conductor for malware as 
copper is for electricity. So: any app that allows networked and/or user 
generated content to control the websocket can be used as an attack tool 
against (explicit or transparent) web proxies.

Masking is one way of defending against this: it makes it very hard for the 
malicious script to control what actually goes over the wire.

The paper already showed a few mitigation strategies, only one made it into 
the RFC in a very washed down way (the paper proposed a stream cipher as 
masking).

There are several additional strategies, which should be employed in my not so 
humble opinion:

1) create a fresh TCP connection for each Websocket, this way it is not 
possible to combine a previous HTTP request and a socket in an attack; 
consequently: if the handshake fails: terminate the TCP connection!

2) when faced with an explicitly configured proxy: ALWAYS use the CONNECT 
method before sending the actual socket request - proxies do not care about 
the socket content after a CONNECT is through - additionally there are 
probably close to zero deployed proxies that even understand the semantics of 
Upgrade: websocket.

Unfortunately 2) does not help with broken transparent proxies, since by their 
nature you cannot detect them easily and it is not a good strategy to send a 
CONNECT just in case...

3) implement masking properly.

The latter can be done in stages, I'd propose this plan:

First: implement websockets, get them into Qt. For the mask generation create 
a virtual protected method "QByteArray getNextMaskValue(int numbytes)const" 
and implement it using qrand()&0xff for each byte - please note that you have 
to initialize with qsrand in each thread. Document the shortcoming with 
something like this:

"This implementation of WebSockets uses cryptographically weak random numbers 
during communication. If you allow user generated or downloaded scripts to 
access WebSockets, then malicious scripts could abuse this implementation to 
attack some vulnerable web proxy servers (e.g. for cache poisoning). In this 
case it is recommended that you reimplement getNextMaskValue to use 
cryptographically strong random numbers."
(maybe add a link to the paper)

Using qrand provides only a very small obstacle to scripts, I'd guess 
something in the order of sending 2^10 frames (done in minutes) could be 
enough to confuse some particularly bad proxies. If the script has access to 
qrand it may even be a lot quicker. No amount of hashing, seeding, shifting or 
otherwise manipulating the numbers would change this (I've fallen into this 
trap years ago, the result was not pretty). Using a deterministic approach 
(like shifting the number by a fixed amount or shuffling it a bit 
mathematically) reduces the attack difficulty to the order of 10-50 frames 
(Done in fractions of seconds) - the number is this high because you still 
have to guess the kind of proxy that is being used (a clever script would need 
2 frames to guess the "random" number sequence).

Later on: when a plan has been found to expose the low-level OpenSSL API to Qt 
this implementation could be changed to use OpenSSL and fall back to qrand if 
it is not available. The documentation would change to something like:

"If you allow user generated or downloaded scripts to access WebSockets, then 
this implementation needs OpenSSL to protect some vulnerable proxy servers 
against cache poisoning or similar attacks. OpenSSL will be detected 
automatically, if OpenSSL is not available this class will fall back to a less 
secure implementation."

A fair warning to proxy admins though: 32 bits of good random is still an 
awfully small amount of bits that stands between a determined attacker and 
your proxy. If untargeted attacks on proxies were as common as spam I would 
expect about one cache poisoning incident per year for an organisation with 
several hundred to a few thousand employees and perfect browsers. If someone 
targets your organisation or one of the browsers uses bad random this can be 
done in days and the poisoned cache is just the beginning of the trouble... So 
keep your proxies up to date!



	Konrad
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20140129/1018f84e/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.qt-project.org/pipermail/development/attachments/20140129/1018f84e/attachment.sig>


More information about the Development mailing list