Hi, Centralized Tokenization: I have merged the work already done for centralized-tokenization in last djangocon at [yarko/django][0]. Since it there have been significant amount of changes since then, merging and resolving conflicts took a little more time then expected. As of now the tests are passing. I am yet to do some minor work to move remaining components to the token system. I'll post it up by tonight or tomorrow and then document how the system works.
CSRF: Clubbing the information regarding CSRF, I have started writing down an overview about it in one place, listing the pros and cons of the methods for CSRF checking. Its in my same soc proposal gist: <https://gist.github.com/2203174#file_csrf.mkd> Also added the content of the gist in the end of this mail. -- Thanks Rohan [0]: https://github.com/yarko/django [1]: https://github.com/crodjer/django/commits/centralized-tokenization ## Current state Django currently uses two methods for protection against CSRF: - In case of http non SSL requests, a conventional token system is used. - In case of https requests, we do referer checking. Both these system introduce a difference in behaviour. Using cookie-token system provides a side effect feature which lets you access the CSRF token across multiple subdomains. But the other, referer checking looks for the request to come from the same host and hence, doesn't allow for cookie like cross subdomain behaviour. The fact that there is a `CSRF_COOKIE_DOMAIN` setting shows that django supports the cross domain capabilities in the CSRF system. So users might utilize this while building multiple sites. When they change to https scheme, they will see a new surprising behaviour. ## The modified system The working tree is at [crodjer/django](https://github.com/crodjer/django/tree/csrf-enhancements) over github. ###Origin and Referer Checking, Permitted domains. - Origin header, a fairly new introduction, has CSRF as one of the target. Unlike the referer header, it sends back only the domain and the path information, so the people don't need to disable these through plugins like the referer header. - With origin header absent, referer header can be used as a fallback. - Strict referer checking is already there in https scheme which is used in all major deployments. We can bring it to the non secure scheme also. - With this method a permitted domains functionality is possible, which lets explicit specification of domains which are trusted and can bypass CSRF. A prototype implementation is there at crodjer/django, csrf-enhancements branch. - Cons: - Since origin checking is still a new concept, it is not implemented yet in major browsers. - Referer headers spoofing is also heard of in some old versions of flash. - Plugins which disable referer header are popular. A client which doesn't provide origin header and with one such plugin, will fail against this kind of checking. ###CSRF Cookies (Time signed): - A random token generated by the server stored in the browser cookies. For verification, every non get request will need to provide a signed version of the same token. This can then be verified on the browser side. - This can be implemented by adding signing to the existing csrf token system, using the signing framework. - A conventional method of CSRF checks, all the major frameworks have similar systems. - Signing takes care of the side effects due to cross domain behaviour of cookies. - Cons: - Relies on the browser cookies system, which introduces insecurities. - Can be broken easily by having a parallel legitimate session, which gives a valid token, signature pair. This generator can then be used in MITM attacks. Given these two methods, I am slightly inclined at Origin/Referer checking, which is already being completely relied upon in case of the secure requests. Or we could loose the possibility of permitted domains functionality and implement both kinds of checks. On 02:16 +0530 / 10 Jul, Rohan Jain wrote: > Hi, > > This check-in is a little delayed. Meanwhile, I continued working on > CSRF and started a on centralized tokenization. > > As I had posted, I implemented the permitted domains system, as > `CSRF_PERMITTED_DOMAINS`. I did some minor cleanups and tests, the > behaviour is mostly the same. Since with the origin header peresent, > referer checking can be neglected, now the system bypasses referer > checking when origin header is not none. > > The new permitted domains system is practically invalidated because of > the existing csrf cookie and token functionality. So for this, I > created a separate branch on my fork, which goes by > [purge-cookies][0]. In this I'll try to remove the CSRF cookie > functionality without affecting the interface which CSRF checking > system provides here. This interface could generate deprecation > warnings about CSRF cookie setting and csrf middleware token. Later we > can remove this interface completely too. > > I would also like to get some suggestions if completely shifting > towards header checking will be a good idea. From all I could find out > from other frameworks out there, tokens and cookies are used to save a > state for CSRF checks generally. Header checks are hardly used > anywhere. Is it because of some flaw with how the headers system work? > Given that referer checking is already being used for request which > use the https scheme, I am assuming this is okay to do and will only > decrease the vulnerabilites which exists from cookies system. > > If there are some reasons for using a cookie, we could at least start > siging them. Probably have the post form send a signed (and timed?) > hash apart from the csrf token for verification. Because otherwise it > is easy to break the system if the attacker has access to some other > subdomain, maybe on a shared hosting. > > Awaiting some feedback on CSRF, I have now started looking into > integrating a centeralized tokenization system with django. Work for > this already exists, done in djangocon 2011 and exists at > [yarko/django][1] on github. The commits were on django-old, so it > can't be merged directly. I cherry picked commits by commits and ran > the merge conflicts with my best guesses. The result of the merge > (broken) exists at [centralized-tokenization][2] branch of my fork. > I'll have to look into this one more and see if I get it to work, as > it does at yarko/django. > > Also, my first change sets regarding contrib.sessions are still > pending some feedback, at [pull-78].[3]. > > -- > Thanks > Rohan Jain > > [0]: https://github.com/crodjer/django/tree/purge-cookies > [1]: https://github.com/yarko/django > [2]: https://github.com/crodjer/django/commits/centralized-tokenization > [3]: https://github.com/django/django/pull/78 > > On Tue, Jun 12, 2012 at 1:32 PM, Rohan Jain <crod...@gmail.com> wrote: > > > > I have done some work on CSRF revolving around origin header checking. > > The origin header is fairly new and is not yet implemented in a > > uniform fashion in the major browsers, so it cannot be solely relied > > upon for CSRF checks. Instead we check if the header exists and use it > > only for rejection of requests. > > > > If an `HTTP_ORIGIN` header is sent by the browser, it checks if it > > matches to be from a valid origin. In case it is not the request is > > rejected right away. Otherwise it proceeds for further CSRF checks > > > > Because of the way browser cookies behave, I had to do some unpleasant > > tweaks to origin header checking such that `COOKIE_DOMAIN_SETTING` is > > followed. From the commit: > > > > if not ((good_origin.startswith('.') > > and good_origin.count('.') is origin.count('.') > > and origin.endswith(good_origin)) > > or origin[origin.find('://')+3:] == good_origin): > > > > All this is because using cookies open the possibility for allowing > > cross subdomain requests (a side effect?). I had a chat with Paul for > > breaking (fixing) this behaviour. The plan is to: > > > > - Make the strict referer checking, currently implemented only for > > HTTPS, default for http requests too. The http scheme which is more > > popular definitely deserves better checking. > > - Make the origin checking work similar to the way referer checking > > is done. Also, will it be safe to bypass referer checking in case > > of origin header being present? > > - Implement a PERMITTTED_DOMAINS setting which lets administrators > > explicitly mention the domains which are permitted to make the > > otherwise restricted requests. This gives more control to the > > administrators. > > - The PERMITTED_DOMAINS setting, a list, accepts patterns. Regex > > cannot be used here because characters like `.`, `-` will need > > escaping. So I decided to settle on the simpler unix style globs. > > The pattern matching is done through the `fnmatch` library > > function, documented [here][fnmatch-docs]. One can use this setting > > like this: > > > > PERMITTED_DOMAINS = [ > > 'www.example.com', # Exactly the domain > > `www.example.com` > > '*.supertrusteddomain.com', # All subdomains to > > `supertrusteddomain.com` > > '?.services.example.com', # Single letter subdomains to > > `.services.example.com` > > ] > > > > I have done an initial implementation of these, changes in [pull > > request #95][pull-95]. I'll now proceed to clean these up, writing > > better tests and documentation for these. Also with these, we can > > completely get rid of the cookie based CSRF check system. > > > > -- > > Thanks > > Rohan Jain > > > > [fnmatch-docs]: http://docs.python.org/library/fnmatch.html > > [pull-95]: https://github.com/django/django/pull/95 > > > > On 20:10 +0530 / 21 May, Rohan Jain wrote: > > > Hi, > > > > > > Since my last check in I worked on improvements to > > > contrib.sessions: > > > > > > - Introduction of signing framework > > > - Session expiry checks (for Ticket [#18194][0] > > > - And some other trivial patches. > > > > > > The tests (existing and the one which I added) are passing. > > > > > > These changes are in my [Pull Request #78][1] over github. > > > Paul, could you please review it to see if the patches are usable. > > > > > > Next, I'll make the changes which may be required in documentation > > > because of the above. > > > Today is official start date of the GSoC project, so I'll now start > > > concentrating more on the project now. > > > > > > Rohan Jain > > > > > > [0]: https://code.djangoproject.com/ticket/18194 > > > [1]: https://github.com/django/django/pull/78 > > > > > > On Mon, May 7, 2012 at 12:21 PM, Rohan Jain <crod...@gmail.com> wrote: > > > > Hi, > > > > > > > > Last week I looked into the Ticket [#18194][0]: > > > > > > > > - Trivial attempts to handle the issue. > > > > - Wrote a minor initial patch. > > > > - The test fails for Cache and Cookie backend. > > > > > > > > Also, I looked at the talks from Paul regarding advanced security > > > > topics at py/django cons. Realised that why I should not attempt > > > > anything related to encryption in my project. > > > > > > > > There is high academic pressure currently, so I am not able to give > > > > enough time to these. I think the situation will be better this > > > > weekend onwards. > > > > > > > > I'll try to work on: > > > > > > > > - Write tests which emulate the problem in #18194 well, and then work > > > > on the final fix. > > > > - Start looking into resources useful for my project, like [The > > > > Tangled Web][1]. > > > > > > > > Rohan Jain > > > > > > > > > > > > [0]: https://code.djangoproject.com/ticket/18194 > > > > [1]: > > > > http://www.amazon.com/The-Tangled-Web-Securing-Applications/dp/1593273886 -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.