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
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ Development mailing list [email protected] http://lists.qt-project.org/mailman/listinfo/development
