Hi Russel, Thanks for the reply.
On 14:42 +0800 / 6 Apr, Russell Keith-Magee wrote: > > Hi Rohan, > > Apologies for the lack of response. Anyone who has put effort into writing up > a proposal certainly deserves a response of some kind, so we've dropped the > ball here. > > In our defence, here's a couple of the reasons why your proposal probably > hasn't got a wild response: > > * You've picked a project on your own, rather than one that is on the list > of suggested projects. Part of the GSoC process is mentoring, and you need to > have a mentor that can spare the time, and has the technical skills to review > your work. Most of the projects on the suggested list already have champions > inside the community, so if you pick one of them, you're likely to get a > response. If you pick your own project, you also have to find someone to get > sufficiently enthused about it. I had picked the project from the list of suggested projects (https://code.djangoproject.com/wiki/SummerOfCode2012#SecurityEnhancements). In fact, I have tried to take on each of the issues mentioned there, point by point. I did talk to Paul over the IRC about this. > > * You've picked a very gnarly problem. Security issues are the very model of > an 'anti-bikeshed'. If you read the original discussion about Bikesheds [1], > it's all about how everyone gives their opinion on "simple" topics, but > everyone leaves hard problems alone. In Django's context -- *everyone* has an > opinion about contrib.auth.User because it seems like a simple problem. > However, security is all about subtle issues and expert knoweledge. > Therefore, your pool of experts is much smaller. > > [1] http://bikeshed.com/ I recently generated some interest in this field, so picked up what I would like to work on the best. For being in field of web development, I believe it is necessary to have a good understanding of security. > > Regarding your project proposal itself: I can't really address the technical > merits, because I don't have any expertise on CORS, or the subtleties of the > CSRF changes your proposing. What you've proposed certainly sounds > interesting on the surface, but I'd really want to see someone like Paul > McMillan comment on the technical specifics. Ideally, Paul would also mentor > the project, since he's Django's resident security expert, and he'd need to > sign off on anything that was bound for trunk. I had some discussions with Paul over this earlier, but since a week days I haven't been able to find him online. > > What I can do is point at the things that look like problems from a GSoC > perspective. In particular, of the three sections to your project plan, two > of them (unified tokenization and django-secure) involve merging existing > projects into trunk. This is problematic, because one of the conditions of > GSoC is that the student writes the bulk of the code. While integrating these > two code pools may well be very valuable contributions to Django, they're not > good from the perspective of a GSoC project. Yes, these two will be more calling out to my `git merge` skills. I was assuming the most of my time would have spanned over CSRF improvements, while using some functionality from centralized token generation. > > So - apologies for not responding sooner. Unfortunately, I suspect that while > your project probably has merit, the community isn't in a position to support > your ambition at the moment. If Paul wants to swoop in at the last minute and > prove me wrong, I'd be a very happy man -- I hate seeing someone enthusiastic > get turned away -- but absent of that, it's only fair that we be honest to > you about your chances. No worries. I am at a blame too for my own activity. I myself have learnt a lot of interesting stuff from this. I would anyway be glad to give something back to django. -- Rohan > > Yours, > Russ Magee %-) > > On 06/04/2012, at 2:09 PM, Rohan Jain wrote: > > > Hi again, > > > > I really couldn't understand the response this post has got. It > > deserved at least a little feedback, positive or negative. I guess I > > wont be submitting this over melange. > > > > Still, I have put some effort and research in the proposal. So if > > possible I would like to know if it had anything of value. Maybe some > > one could work over that, even me if I get the time. > > > > -- > > Rohan > > > > > > On 23:40 +0530 / 31 Mar, Rohan Jain wrote: > >> Hi, > >> > >> I am Rohan Jain, a 4th (final) year B.Tech undergraduate Student > >> from Indian Institute of Technology, Kharagpur. I have been using > >> django since over a year and generally look into the code base to find > >> about various implementations. I have made attempts to make some minor > >> contributions and if selected this would be my first major one. > >> > >> More about Me: <http://www.rohanjain.in/about/> > >> IRC, Github: crodjer > >> > >> I am interested in contributing some security enhancements to django > >> as my Summer of Code project. Below is the 1st draft of my proposal > >> regarding this. A pretty version of this is available at: > >> https://gist.github.com/2203174 > >> > >> > >> #Abstract > >> > >> Django is a reasonably secure framework. It provides an API and > >> development patterns which transparently take care of the common web > >> security issues. But still there are security features which need > >> attention. I propose to work on integration of existing work on > >> centralized token system and improved CSRF checking without any > >> compromises. If time permits I will also attempt on integration of > >> django-secure. > >> > >> #Description > >> ##Centralized tokenization > >> There are multiple places in django which use some or other kinds of > >> tokens: > >> > >> - contirb.auth (random password, password reset) > >> - formtools > >> - session (backends) > >> - cache > >> - csrf > >> - etags > >> > >> Token generation is pretty common around the framework. So, instead > >> of each application having its own token system, and hence needs to be > >> maintained separately. There should be centralized token system, which > >> provides an abstract API for everyone to loose. In fact, I have seen > >> that some apps use `User.objects.make_random_password` from > >> contrib.auth, which they can be sure of being maintained in the future > >> for random generation. To me this looks kind of weird. > >> In last djangocon, a lot of work regarding this was done over [Yarko's > >> Fork][yarko-fork]. > >> > >> I had a discussion with Yarko Tymciurak regarding this. The work is > >> nearly ready for a merge, only some tasks left. In the initial period > >> my SoC I can work over these to insure that the already done > >> significant work gets in django and is updated for 1.5. > >> > >> - Porting more stuff to the new system (README.sec in > >> [yarko's fork][yarko-fork]) > >> - Testing - See if the current coverage of the tests is enough, write > >> them if not. > >> - Compatibility issues > >> - API Documentation > >> > >> I will study the changes done at djangocon and then attempt the tasks > >> mentioned above. > >> > >> ##CSRF Improvements > >> > >> Cross-Origin Resource Sharing (CORS): > >> W3C has a working draft regarding [CORS][w3c-cors-draft], which opens > >> up the possibility for allowing client-side request cross-origin > >> requests. This directly triggers in mind the capability to develop > >> API which can be exposed directly to the web browser. This would let > >> us get rid of proxies and other hacks used to achieve this. > >> Currently all the major browsers support this: Chrome (all versions), > >> Firefox (> 3.0), IE (> 7.0), Safari (> 3.2), Opera (> 12.0). > >> Introduced it here as some further parts of the post refer to this. > >> > >> ###Origin checking > >> > >> With CORS around need for using CSRF token can be dropped, at least in > >> some browsers. [Ticket #16859][orig-check-ticket], is an attempt for > >> that. But this was rejected because of neglecting the case for > >> presence of `CSRF_COOKE_DOMAIN` (Refer to the closing comment on the > >> ticket for details). So to handle this we need to simulate checking of > >> CSRF cookie domain as web browsers do it. Maybe: > >> > >> ```python > >> reqest.META.get('HTTP_ORIGIN').endswith(settings.CSRF_COOKIE_DOMAIN) > >> ``` > >> > >> As the closing comment points it out, we can't do this with secure > >> requests. They need to be essentially checked against the referrer or > >> origin, at least for now. We can not be sure that some untrusted or > >> insecure subdomain has not already set the cookie or cookie domain. > >> d > >> To deal with this, we have to consider https separately as it is > >> being done now. So it will be something like: > >> > >> > >> ```python > >> def process_view(self, request, ....): > >> > >> # Same initial setup > >> > >> if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'): > >> > >> host = request.get_host() > >> origin = reqest.META.get('HTTP_ORIGIN', "") > >> cookie_domain = settings.CSRF_COOKIE_DOMAIN > >> > >> if request.is_secure(): > >> good_referer = 'https://%s/' % host > >> referer = origin or request.META.get('HTTP_REFERER') > >> # Do the same origin checks here > >> > >> # We are insecure, so care less > >> # A better way for this check can be used if needed > >> elif origin.endswith(cookie_domain): > >> # Safe, accept request > >> > >> # Some unsupported browser > >> # Do the conventional checks here > >> ``` > >> > >> If the above were to be implemented, the setting `CSRF_COOKIE_DOMAIN` > >> should be deprecated for something like `CSRF_ALLOWED_DOMAIN` which > >> makes more sense. > >> > >> I would also suggest making CSRF cookie as http only. There doesn't > >> seem a reason currently why the cookies would be needed to be accessed > >> in browser. > >> > >> ###Less restrictive secure requests > >> > >> The current CSRF system is pretty much secure as it is. But CSRF > >> protection poses too much restriction to https. It says no to all the > >> request, without honouring any tokens. It kind of has to, thanks to > >> the way browsers allow cookie access. A cookie accessible through > >> subdomains mean that any subdomain secure or insecure can set the CSRF > >> token, which could be really serious for the site security. To get > >> around this, currently one has to completely exempt views from CSRF > >> and may or may not handle CSRF attacks. This can be dangerous. Also if > >> a person has a set of sites, which talk to each other through clients > >> and decides to run it over https, it would need some modifications. > >> > >> Django should behave under https similarly as it does under http > >> without compromising any security. So, we need to make sure that the > >> CSRF token is always set by a trusted site. Signing the data with the > >> same key, probably `settings.SECRET_KEY`, across the sites looks apt > >> for this, using `django.core.signing`. We can have `get_token` and > >> `set_token` methods which abstract the signing process. > >> This can be done in two ways: > >> > >> - Store CSRF data in sessions data in case `contrib.sessions` is > >> installed. Then the data will automatically be signed with the > >> secret key or will not be stored in the client as cookies at all. > >> > >> - In case of it being absent from installed apps, revert to custom > >> signing > >> > >> ```python > >> from django.core.signing import TimestampSigner > >> > >> signer = TimestampSigner("csrf-token") > >> CSRF_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 * 52 > >> > >> > >> def get_unsigned_token(request): > >> # BadSignature exception needs to be handled somewhere > >> return signer.unsign(request.META.get("CSRF_COOKIE", None) > >> max_age = CSRF_COOKIE_MAX_AGE) > >> > >> def set_signed_token(response, token): > >> response.set_cookie(settings.CSRF_COOKIE_NAME, > >> signer.sign(request.META["CSRF_COOKIE"]), > >> max_age = CSRF_COOKIE_MAX_AGE, > >> domain=settings.CSRF_COOKIE_DOMAIN, > >> path=settings.CSRF_COOKIE_PATH, > >> secure=settings.CSRF_COOKIE_SECURE > >> ) > >> > >> > >> def get_token(request): > >> if 'django.contrib.sessions' in settings.INSTALLED_APPS: > >> return request.session.csrf_token > >> else: > >> return get_unsigned_token(request) > >> > >> def set_token(response, token) > >> if 'django.contrib.sessions' in settings.INSTALLED_APPS: > >> request.session.csrf_token = token > >> else: > >> set_signed_token(response, token) > >> > >> # Comparing to the token in the request > >> constant_time_compare(request_csrf_token, get_token(csrf_token)) > >> > >> ``` > >> > >> Now, doing this is not as simple as the above code block makes it > >> look. There is a lot which can and probably will go wrong with this > >> approach: > >> > >> - Even when the token is signed, other domains can completely replace > >> the CSRF token cookie, it won't grant them access through CSRF > >> check though. > >> > >> - This sort of couples CSRF with sessions, a contrib app. Currently > >> nothing except some of the other contrib apps are tied up with > >> sessions. It will break if sessions were to be removed in future or > >> the API changed. Also, this means that if one website is using > >> sessions CSRF, all of the other must be too. > >> > >> - If this were successfully implemented, is this exposing any > >> critical security flaws otherwise? Will it cause compatibility > >> issues? > >> > >> As Paul McMillan said "This is a hard problem", I'll delegate figuring > >> this to future me. I will look into [The Tangled Web][tangled-web] > >> and [Google's Browser Security Handbook][gobrowsersec] for ideas, > >> again suggested by Paul on the IRC. > >> > >> ###Better CORS Support > >> Since, already introducing Origin checking, we can go one step further > >> and try to provide better support for CORS for browsers supporting it. > >> A tuple/list setting, which specifies allowed domains will be > >> provided. Using this the various access control allowance response > >> headers will be set when the request origin is from amongst the > >> allowed domains. For CSRF check, just see if http origin is present in > >> allowed domains. > >> > >> ```python > >> > >> def set_cors_headers(response, origin): > >> response['Access-Control-Allow-Origin']: origin > >> > >> def process_response(self, request, response): > >> > >> origin = reqest.META.get('HTTP_ORIGIN', "") > >> > >> if origin in settings.CSRF_ALLOWED_DOMAINS: > >> set_cors_headers(response, origin) > >> > >> def process_request(self, request, response): > >> > >> # Use origin in settings.CSRF_ALLOWED_DOMAINS here instead of > >> # origin.endswith > >> > >> ``` > >> > >> Probably, something similar to the above will be needed to incorporate > >> the CORS support. > >> > >> ##Integrating django-secure > >> A really useful app for catching security configuration related > >> mistakes is [carljm's django-secure][djang-secure]. It is specially > >> useful to find out issues that might have been introduced while quick > >> changes to settings for development. This project is popular and > >> useful enough that it can be shipped with django. I haven't been able > >> give this enough time yet. I can think of two ways of integrating > >> this: > >> > >> - Dropping it as a contrib app > >> This seems pretty straight forward would require minimal amount of > >> changes. > >> > >> - Distribute around the framework: > >> Like CSRF, this can also be distributed framework wide and hence it > >> won't be optional to have. Apps can still define custom checks in > >> the same way when `django-secure` was installed as a pluggable > >> application. > >> > >> The app might also need some changes whilst being integrated: > >> > >> - More security checks, if required > >> - Adjust according to the changes introduced above. > >> > >> #Plan > >> I think that the tasks centralized tokenization and CSRF enhancements > >> will be enough to span through the SoC period. If after a thorough > >> implementation and testing of these, I still have time, django-secure > >> integration can be looked into. > >> > >> ##Timeline > >> I have listed the tasks above in a chronological order. I'll add a > >> more granular timeline in one of the next drafts. > >> > >> > >> [yarko-fork]: https://github.com/yarko/django > >> [w3c-cors-draft]: http://www.w3.org/TR/access-control/ > >> [orig-check-ticket]: https://code.djangoproject.com/ticket/16859 > >> [tangled-web]: > >> http://www.amazon.com/The-Tangled-Web-Securing-Applications/dp/1593273886/ > >> [gobrowsersec]: http://code.google.com/p/browsersec/wiki/Main > >> [django-secure]: https://github.com/carljm/django-secure > >> > >> > >> -- > >> Thanks > >> Rohan Jain > > > > -- > > 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. > > > > -- > 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. > -- 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.