Ticket 14261 - add basic clickjacking protection to Django

56 views
Skip to first unread message

Ryan N

unread,
Mar 13, 2011, 1:51:13 AM3/13/11
to Django developers
See approved ticket: http://code.djangoproject.com/ticket/14261

There, Luke Plant said:

"""
+1, I was going to suggest it myself. The patch looks pretty good.
After Django 1.3 is out, we should have some discussion on django-devs
about:

- what the default value should be (I think SAMEORIGIN would make it
better for general use, with very little decrease in security).
- whether we can avoid a new setting
- whether the middleware should be on by default or in the project
template.
"""

I already changed the patch to default to SAMEORIGIN instead of DENY,
so that should be cool. So it seems the other two points are what's up
for some discussion. Anything else?

Rohit Sethi

unread,
Mar 13, 2011, 12:03:45 PM3/13/11
to Django developers
This is awesome - very progressive and I hope other frameworks follow
suite.

Have you done a poll of users to see how many would be affected by a
"SAMEORIGIN" setting? Maybe that would be a good place to start. Is
there some other way to test the overall impact of this prior to
committing to it being on by default?

Ryan N

unread,
Mar 13, 2011, 12:30:09 PM3/13/11
to Django developers
I personally do not believe XFrameOptionsMiddleware should be on by
default. There are plenty of folks using Django for simple static
sites or RESTful APIs where clickjacking doesn't apply.

I'd prefer it's something that requires you to intentionally turn it
on by adding the middleware to your settings and/or using the
decorators on views you want to clickjack protect.

With that said, I could change the patch if the core devs say
otherwise.

Rohit Sethi

unread,
Mar 13, 2011, 1:00:32 PM3/13/11
to Django developers
I personally like the idea of a decorator

Paul McMillan

unread,
Mar 14, 2011, 4:38:47 PM3/14/11
to django-d...@googlegroups.com
I agree that Django should include this functionality in core. The
header is a very useful way to discourage click-jacking in modern
browsers.

However, I also agree with Ryan N that this should be off by default.
If it must be on, it should use SAMEORIGIN (as the patch currently
provides) to avoid breaking existing sites.

For better or worse, frames are an integral part of the web today.
Taking a stance as an entire framework that by default, content should
not be framed, is a _very bad_ choice. Many sites use Django to build
open data platforms, and many of the interesting sites on the web
today function as mashups of other site content (often by framing it,
often without an explicit "go-ahead" by the framed site). If we force
every site creator to explicitly enable the ability to be framed, we
are directly creating a closed, less dynamic, less interesting
internet.

I would prefer an approach that was more selective. In particular,
this header (usually) only makes sense in the context of a page which
contains a form. If we must enable it by default, we should limit it
to those pages.

-Paul

Luke Plant

unread,
Mar 14, 2011, 7:34:28 PM3/14/11
to django-d...@googlegroups.com
On 14/03/11 20:38, Paul McMillan wrote:

> However, I also agree with Ryan N that this should be off by default.
> If it must be on, it should use SAMEORIGIN (as the patch currently
> provides) to avoid breaking existing sites.

I would suggest putting the middleware in the project template, but
leaving it commented out with an explanation, like the admin is done.
This will help people become aware of it, and make it very easy for
people who need it to turn it on.

> I would prefer an approach that was more selective. In particular,
> this header (usually) only makes sense in the context of a page which
> contains a form. If we must enable it by default, we should limit it
> to those pages.

I don't think this is a practical requirement. We would have to inspect
the HTML before adding the header, which adds lots of complications for
things like for streaming responses, and we really don't want to be
making that harder. It also doesn't work in the context of pages that
build forms via javascript in some way, and neither does it cater for
the very common case of pages that allow actions to be taken without any
forms at all e.g. AJAX. It is impossible to examine a page and see
whether it is potentially dangerous or not.

However, to make it more selective, I would suggest something like the
CSRF approach - a middleware that can be turned on globally to allow for
quick, blanket protection, then decorators that:
- turn off the global protection (something like 'clickjack_exempt')
- add the protection, whether or not the middleware is present
(something like 'clickjack_protect').

If anyone has better ideas for how to implement this pattern which has
now come up a few times (i.e. the need for easy global protection, with
more fine grained options available), I'd be really interested to hear.

Regards,

Luke

--
Evolution (n): A hypothetical process whereby infinitely improbable
events occur with alarming frequency, order arises from chaos, and
no one is given credit.

Luke Plant || http://lukeplant.me.uk/

Ryan N

unread,
Mar 14, 2011, 11:27:59 PM3/14/11
to Django developers
Luke - I suggest taking a look at the patch, as it works exactly as
you describe (i.e. CSRF-like).

Only thing that's not in there is having the middleware in the project
template but commented out. I can add that in too.
Reply all
Reply to author
Forward
0 new messages