On Thu, Sep 17, 2009 at 3:11 PM, Simon Willison <si...@simonwillison.net> wrote:
>
> On Sep 15, 2:57 pm, Luke Plant <l.plant...@cantab.net> wrote:
>> OK, I'll wait and see.
>
> Here's the code: http://github.com/simonw/django-safeform
>
>>  * it requires using Django's form system.  I've got plenty of views that
>> don't (e.g. anything with a dynamic number of controls).  People not using
>> django.Forms are left out in the cold, or having to learn another way to do
>> things.
>
> I've covered this in django-safeform by exposing a low level interface
> to the CSRF token creation and validation routines (in csrf_utils) -
> see the readme for documentation on this.
>
>>  * it's off by default.  Turning it on by default will require making
>> django.forms.Form subclass SafeForm, which will almost certainly require a
>> huge and immediate upgrade effort, because SafeForm cannot have the same API
>> as Form.  If it's off by default, I see no point at all in this entire
>> exercise.  If we don't arrive at a point where the POST form created in the
>> tutorial is safe from CSRF, I think we've failed.
>
> My priority for this is a little different: while I would dearly love
> to see all Django applications secure against CSRF by default, I can't
> see a way of doing it that doesn't break existing apps. More important
> for me though is that the Django admin (and other reusable apps, such
> as Pinax stuff) MUST be secure against CSRF out of the box, no matter
> what the user puts in their settings.py file. If developers fail to
> protect themselves (especially when the solution is well documented)
> then at least it isn't our fault.
>
> I think this is subtly different from the XSS escaping issue simply
> because the solution to CSRF is much more intrusive.
>
>> And it will still require changes to templates, just like the template tag,
>> and it will also require changes to views, only significantly more complex
>> than simply using RequestContext.  It's got at least as many and at least as
>> intrusive 'moving parts' AFAICS.
>
> The SafeForm API actually simplifies views - you go from this:
>
> def change_password(request):
>    form = ChangePasswordForm()
>    if request.method == 'POST':
>        form = ChangePasswordForm(request.POST)
>        if form.is_valid():
>            return HttpResponse('Thank you')
>    return render_to_response('change_password.html', {
>        'form': form,
>    })
>
> To this:
>
> @csrf_protect
> def change_password(request):
>    form = ChangePasswordForm(request)
>    if form.is_valid():
>        return HttpResponse('Thank you')
>    return render_to_response('change_password.html', {
>        'form': form,
>    })
>
> The SafeForm deals with the request.method == 'POST' bit, meaning one
> less conditional branch within the view function itself.

Did we discuss this bit at the sprint? I'm completely on board with
everything else, but this bit makes me nervous:

 * It calls is_valid() on the form during a GET (which isn't currently
done as part of normal practice).

 * It isn't possible to have any special view handling based on the
request method.

 * It implies that the method of construction the form will always be
the same, regardless of whether we are GETting or POSTing. This isn't
always true - in particular, I'm thinking of the construction of
FormSets, which can use a queryset to populate the forms on GET, but
don't require the queryset on POST.

> I'm pretty happy with the SafeForm interface now that I've fleshed it
> out - it's a lot less clunky than I was originally expecting.

Another advantage that Simon hasn't mentioned - it requires no
modifications to the tutorial. We can present the basic ideas of form
handling in tutorial 4 without mentioning CSRF. We then have scope to
introduce a new tutorial on security issues, that can both educate on
the nature of XSS and CSRF attacks, plus what you have to do in order
to protect against them.

Yours,
Russ Magee %-)

--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to