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

Konrad Rosenbaum konrad at silmor.de
Sun Jan 26 19:12:11 CET 2014


Hi,

[wow, I had a good laugh!]


On Sunday 26 January 2014, Kurt Pattyn wrote:
> On 26 Jan 2014, at 11:31, Konrad Rosenbaum <konrad at silmor.de> wrote:
> > Depends. What is it used for? Is it just obfuscation or is it supposed
> > to be real security?
> 
> Well, there are 2 places where random numbers are used:
> 1. During the handshake phase
> Client sends a handshake request containing a 128-bit random number
> converted to a string hex representation (Sec-WebSocket-Key). The server
> appends a well-known UUID (published in the RFC) to that number and
> calculates a SHA-1 hash. This hash in sent to the client, which in its
> turn appends the same UUID to the random number it sent before, and
> calculates a SHA-1 hash. If both the server-sent hash and the client
> calculated hash match, the handshake succeeds.

And this is sent in the open? On an unsecured connection?

This is the most elaborate scheme of a not-so-secret handshake that I've 
read so far! The only thing that is more hilarious is the Big Bang Theory 
scene in which Sheldon lectures his friends on the "secret knock" before 
Leonard's birthday party...

My personal opinion on unencrypted connections: don't sweat it. Use whatever 
is available. qrand is as secure as the rest of the connection (i.e. not 
secure at all). Using secure random does not change a thing in this case 
(only CPU cycles wasted on the client).

On encrypted (SSL) connections: if this covers several HTTP(S) requests and 
not a simple non-interrupted socket then this should better be some secure 
128 bits. Although it is beyond me why you would hash them again and again - 
they could be used as a cookie...

[See bottom of my response for some more elaborate argument on this.]

> 2. When sending data from client to server (not the other way)
> The client generates a 32-bit random number.
> This random number is stored in plain text in the header of each frame.
> The data is XOR-ed with that 32-bit random number.
> 
> The server takes the 32-bit random number from the header and XORs it
> with the payload to get to the original data.
> 
> I really fail to see what the intention is of this mechanism. I really
> fail to see what could make this communication ‘secure’.

I seem to remember that a certain Julius Caesar had a similarly clever idea 
for securing his correspondence. Of course Julius had the excuse that 
advanced math-based cryptography was not available in his time...

(https://en.wikipedia.org/wiki/Caesar_cipher)


> "The masking key needs to
>  be unpredictable; thus, the masking key MUST be derived from a strong
>  source of entropy, and the masking key for a given frame MUST NOT
>  make it simple for a server/proxy to predict the masking key for a
>  subsequent frame.  The unpredictability of the masking key is
>  essential to prevent authors of malicious applications from selecting
>  the bytes that appear on the wire.”

My above statement about the handshake was wrong. Enormously so.
This statement tops all the comedy in in my sizable DVD collection!

> Why should the masking key be unpredictable if it is send unencrypted
> along with the masked data? Why would a server/proxy predict the masking
> key if it can just fetch it from the header? To me it looks like having
> a locked door with the key in the keyhole. Why would a burglar use a
> crowbar if he has the key?

Exactly. This toy-cipher and its description is equivalent to triple-ROT13 
(triple for more "security"...) 

#-(

> > If the latter: is it the only way to generate security? (If so: in all
> > likelyhood you are affixed by an inclined plane wrapped helicly around
> > an axis. In laymans terms: screwed.)
> > 
> > If the former: unless it is absolutely necessary for understanding the
> > other side of the communication channel - don't bother implementing
> > it. Obscurity is no security.
> 
> Well, the standard requires the frames that go from client to server to
> be masked. So yes, it is absolutely necessary, but in my opinion
> complete overkill.

I agree with you. The only thing this defends against is absolutely clueless 
IT people (pointy haired boss types) who have read access to network logs, 
but whose 8 year old kids refuse to help with a simple script.

Use any source of (weak) random (e.g. qrand) and ignore this bullshit about 
"strong source of entropy".

If anyone asks you why you are using insecure random:

a) on unsecured connections it is pointless to get secure random and then 
transmit it in the open together with the data. Revealing secure random to 
the open makes it magically insecure. You might as well not try to conceal 
the data at all.

b) on secured (SSL) connections it is pointless to implement a toy 
encryption when SSL is already doing an adequate job of doing real 
encryption designed by real cryptographers. 

c) Or the social argument: anyone clever enough to crack an SSL secured 
connection might fall off their chair laughing hard when after spending days 
or decades cracking the SSL-shell-of-encryption and they see secure random 
being transmitted in the open along with data to make the data "more secure" 
- I would not want to be responsible for the kind of injury they might 
sustain falling head first onto an open computer case... ;-)

> > I would not recommend trying to implement your own PRNG either -
> > getting it right is horribly difficult. Getting the entropy gathering
> > right in a cross- platform way is much worse effort…
> 
> I wouldn’t even dare :-) This is a research field on its own.

Very wise decision. :-)

> > I wonder whether it would be possible to expose the low-level APIs of
> > OpenSSL to Qt, it has quite a good random number generator and it is
> > used for QSslSocket already.
> 
> Indeed, I planned to use the OpenSSL RNGs (the library has FIPS approved
> RNGs), but that library is not available on all platforms I think.
> Besides that, I am afraid this is a very expensive operation, certainly
> because another masking key has to be calculated for every frame.

Don't bother for the masking key.

If you do use OpenSSL RNGs: don't specifically pick FIPS approved ones or 
some other specific models for whatever reason (one of the FIPS RNGs may 
have been made intentionally insecure by the NSA: Dual-EC-DRBG) - just pick 
the default secure RNG and let the experts from OpenSSL decide which one is 
best ("best" may even change between releases because of new discoveries in 
crypto).

> Konrad, reading the cases where random numbers are used, do you think it
> is worth the effort? I am even considering to calculate the masking key
> just once and use it for every frame (would speed up the communication).

Don't do any elaborate calculation on the "masking key". Just generate it 
with qrand every time you need one. Using the same "key" every time might 
piss off some paranoid implementations (I've seen some truly idiotic 
implementations in the SOAP arena, I don't expect those vendors to do better 
with Websockets).

There is one specific case in which it would make sense to use secure random 
and in which the OpenSSL library can be assumed to exist. If all of those 
criteria are met then the handshake key needs to be secure:

1) the handshake happens on a connection that uses SSL
2) there is a chance that the websocket spans several actual TCP connections
  (e.g. by being split over several HTTP requests, the splitting could be
   done by a proxy in this case)
3) the key data (or something derived from it) is actually used to identify
   the connection between separate TCP connections

If criterion 1) fails (unsecured connection) then there is no need to 
bother. The protocol can be executed by any attacker. Using good random 
slows the legitimate user down, not the attacker.

As far as I could get from Wikipedia item 2 is not applicable, since one TCP 
connection is upgraded from HTTP to Websocket and stays active in Websocket 
mode (i.e. if the TCP connection closes, then the Websocket is lost as 
well). So the whole argument fails and the key does not need to be secure.

I couldn't find much information about criterion 3 yet, but it seem to be 
used for the initial handshake only - never after that - right? 

However, if all 3 of them are correct then the handshake key is the only 
thing that chains separate TCP/SSL connections together. In order to be 
secure it has to be at least as strong as the connections it is supposed to 
chain together.


Maybe I should read the RFC later on - I might need a good laugh after work 
tomorrow... :-)




	Konrad
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20140126/69baa498/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/20140126/69baa498/attachment.sig>


More information about the Development mailing list