Due to the lack of CSRF protection, I have started creating my own pull request (3.0.2) for CSRF protection in SS. The way this is going to work is that when visit a SS website and it serves you the initial HTML, that initial HTML will contain a unique token (which is a uuid.v1). This same token will be registered in your session store (such as Redis). This unique token will be placed in the head under a meta tag (with the meta name as ss_uuid). As far as I am aware, this shouldn't cause any issues
The question just remains regarding session management. My current thoughts is to just completely remove cookies from any type of session management at all (for an explanation why, read this
http://faye.jcoglan.com/security.html). There are also numerous advantages to not using cookies for management (apart from security reasons).
- You can use a client that is not a browser. As long as the client application can initiate a HTTP request, it can use the websocket protocol to communicate with a SS server, and sessions will still work.
- Cookies have some issues with long lived process's (which are completely negated by using this method)
- Gives developer full control over sessions. Every web page (or web tab) will have its own UUID. You can refer to each client by UUID using this method, and it can allow things like sending messages to a client (defined by UUID) instead of using a bucket. This can be handy if you want to log someone out after X amount of time
The way SS will work is that every request that is sent (and received) will contain this token, and if the tokens do not match then obviously there is a CSRF attack. This means that when you do a
ss.rpc('some.request',someData)
That request will automatically contain the token inside the HTML. When the server receives the token, it will proceed from there.
The only question, is that there will be some api changes. The question is not so simple about breaking API or not, because we are actually changing the way sessions work, and some people may have made an assumption about how the old sessions work.
One thing to take into account, is that sometimes you want people to access your server from another domain. If you are making a public websocket api that can be accessed from anywhere, then you do not need to validate sessions. Putting the token in each message also creates some overhead for every request (but again, its the only secure way to prevent CSRF). Most people will want to put the token into every message, just to make sure that CSRF is prevented.
So what I can do, is to replace the current ss.rpc with the sescure ss.rpc. It will work the exact same way as SS 3.0.2's RPC, however it will (automatically) place the token into each request (and the server will automatically read each request and pop the token off the request, deal with the token, and then send the rest of the data to the standard exports.actions that we already use. For insecure messages. we will have another action on the client (lets call it ss.rpc.insecure) which will send the data without any token. The server will have an exports.insecureActions section (just like we have exports.actions section) which is where you will place your functions for dealing with insecure. There will be a similar separation for push events from the server (what is called ss.event on the client). This means the default will be secure (and it still gives you option to make insecure messages that have less overhead).
If people still want to use cookies, (such as for remember me functionality when you login), they can, its not just part of the core session handling. There are plenty of client side cookie javascript libraries (and non web browser clients can use their own storage mechanism). You can combine this with storing sessions as objects in the database (this is how major websites like facebook do it with their access tokens)
What are peoples thoughts around this?