Approach for CSRF Protection

75 views
Skip to first unread message

Matthew de Detrich

unread,
Oct 11, 2012, 1:04:23 AM10/11/12
to socket...@googlegroups.com
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?

Matthew de Detrich

unread,
Oct 11, 2012, 3:51:35 AM10/11/12
to socket...@googlegroups.com
Also a couple of other things I wanted to mention. Since this method will be replacing session management (in general), there will not be a 'cached' version available for the initial HTML page as mentioned in this thread (https://groups.google.com/forum/?fromgroups=#!topic/socketstream/1wclA8Fhldc). If we are going to be referring to different sessions by uniqueID's (which are actually embedded into the html), this needs to be universal. For performance reasons, this means that instead of using gzip on the html (as is planned in SS 4.0), we can instead minify the initial html. Yes the compression won't be as good as gzip, but unlike gzip you can at least cache one block of the minified html (which is basically everything that is not the token) and then combine that with the unique token for every request. As far as I am aware, there isn't any way to combine and cache different pieces of texts that are gzipped

In any case, if your initial block of html is ridiculously massive and you want certain parts of the html cached (for performance reasons), there is nothing stopping a SS website from loading parts of the html after the initial block (which would be completely static). We can obviously provide an API to make this incredibly easy :)

Owen B

unread,
Oct 11, 2012, 10:09:25 AM10/11/12
to socket...@googlegroups.com
Hi Matthew

We can't remove the cookie altogether, at least not in 0.3 as this will break everyone's app who is taking advantage of session sharing with Express - that's a lot of people.

The connect.sid cookie needs to continue to exist and provide the main Session ID. What we can do is create a separate token which is injected into the outgoing view which acts as a confirmation when CSFR checking is enabled. 

As for how we do things in 0.4, I am still thinking a lot about this and are open to making bigger changes, but any further changes to 0.3 must not break anything.

Owen

Matthew de Detrich

unread,
Oct 11, 2012, 12:57:03 PM10/11/12
to socket...@googlegroups.com
You will still be able to share sessions without breaking the api. It will be completely transparent to the user, I am pretty sure you can set Request to do session storage however way you want (it just uses cookies by default). If it will break something, I will let you know.
Reply all
Reply to author
Forward
0 new messages