-
Notifications
You must be signed in to change notification settings - Fork 10.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal to allow clients to specify a sessionid when connecting. (bug 497) #498
Conversation
That's a data leakage and/or DoS vulnerability in the making right there. I'd spend more time considering options before turning to this. |
Can you expand on that a little bit? My thoughts were the following...
Thoughts? |
All that said, I would also ask, do you even want this sort of "long lasting session id" to exist in socket.io? I think it could be useful in some/many cases, but one could also build this functionality on top of socket.io instead of in to socket.io. |
Sure, but the keyspace is large enough for that to be ok - so long as there are no overlaps, and "active but not currently connected" sessions are removed from storage regularly. This however brings me to another point: the current
In my opinion it's better to either
|
I like #2, but doesn't a sufficiently large/random session id provide the exact same protection? Either way the server sends the user something (in your idea sessionid+hashed/encrypted bit and in mine just a sessionid) and the user can later send that exact thing back to re-establish identity. No need for a second encrypted/hashed token/bit of data if the sessionid is so large that it is impossible to guess. To your first point, I totally agree. One strategy for creating session ids is UUID+(a few bytes of fairly strong random entropy) (in this case + meaning concatenation) -- UUIDs already provide a way of creating a globally unique identifier. However it is possible to guess UUIDs (super hard, practically impossible), so we add on some extra random to make them unguessable. Another strategy is to just use very large (256bit, for example) strong random numbers for sessionids and leave it at that. While there would be some chance of collision/guessing one, the probability is many, many orders of magnitude less than that of an asteroid destroying the earth in the next one second. Would you like me to create a patch to make the generateId function behave in this way? Also, does the sessionid need to be purely numeric? |
To be fair, no. Guids, within a scope, exist to provide a guaranteed unique identifier within said scope, for storage and referencing. Contrary to popular belief, they do not exist as a security measure. While we're talking guids, there's also length to consider. If you have a load-heavy application, passing a longer than necessary identifier isn't necessarily a wise choice. Anyhoo, all I'm really saying is that this isn't a decision to be made in a haste. |
As a first step in this, would you be open to pull request strengthening the session ids? I can do some research into best practices for secure session identifiers (while balancing the length) and put something together. |
Sounds good to me. |
What if a client specifies his own id, as for example I like the idea with persistent clients through reconnects though. But maybe there are better ways to do it? |
Really good thought... we would have to check to see if a sessionid is valid. That would mean storing all session ids in the store, expiring them, etc... So we aren't letting a client choose a sessionid, just reconnect using their previous sessionid. Something along the line of Handshake:
Heartbeat:
|
What if some malicious user tries to connect using someone else's session id? Client-side scripts can be reverse engineered and data can be tampered. |
What Tehek said. You can however provide a secret key upon connection, which is only known to this user. If the user wishes to restore the state after a reconnection, he must provide this key. After reconnection, the old key is replaced by a new one and the user is informed about the new key. |
@tommedema: but the new key still sits at client-side, right? |
@dvv, both server and client side, yes. The only way this can be exploited is when the user transfers his key to someone else, in which case there is no real issue. |
sorry, does "key is stolen" result in effect similar to "user transfers the key"? |
@dvv, ehh, yes, just like a stolen password. Theft will always cause problems. Though you can reduce the chances of theft by using SSL or disabling this In a way that's like saying, let us not produce cars, because cars can be stolen, and we don't want that to happen. |
(no need to make invalid examples). I mean if key is stored in browser, it is weak, because it is a shared environment and there are and always will be techniques to steal info in such environments. |
@dvv, the fact is that there is no safer way to accomplish this. Many people will agree that this is safe enough for most applications. The only way this can be exploited is by means of:
All these situations are extremely unlikely, and will not be a problem for most applications. Also, if any of these problems do appear, then this kind of session restore is the least of your worries. :) Another fact is that browsers will force a disconnection when you open a flash file browser or alert box on several operating systems. This is the only solution for these disconnection issues. Finally, in case someone does not need this functionality, it should be a toggle so that it can be turned on or off. |
thanks for a truly good summary. though i'd say they ways you enumerated are not so extremely unlikely in the wild world (think of free metasplot, and paid exploit combines, and malicious corporate sysad, and...), i tend to agree so far i see no safer way than proposed challenge-response pattern |
Why, oh why, is this problem attempted solved in 'new' ways? The only proper way of doing this is to use simple public-key crypto to send a client key joined with a server provided nonce (for replay protection) from the client to the server. Also, what's being discussed here is a serious problem with the polling transports we're using right now. It really is trivial to break into other sessions, ssl or no ssl, if the session id is at any point guessable or available to other clients. |
@einaros the key phrase is "if the session id is at any point guessable or available to other clients." -- the goal is to create a session id that is impossible/infeasible to guess (which will be possible to create one this lands https://github.com/bnoordhuis/node/compare/issue1330-2). |
I have a different take on this problem. See pull 858 for details. |
This is a proposal for new functionality.
The intended use case is to allow clients to reconnect using the same sessionid that they originally connected with. This, combined with the RedisStore would allow a socket server to fall out of a cluster, a client to reconnect to another server in the cluster, all while maintaining data associated with the socket.
My proposal would be to modify the Manager.handleHandshake method to pull a sessionid from the query if it exists.
In order to utilize this feature, clients would have to set the sessoinid in the socket.options.query (client).
Any thoughts?