2011-05-31 06:27:47 +08:00
|
|
|
========================
|
|
|
|
Clickjacking Protection
|
|
|
|
========================
|
|
|
|
|
|
|
|
.. module:: django.middleware.clickjacking
|
|
|
|
:synopsis: Protects against Clickjacking
|
|
|
|
|
|
|
|
The clickjacking middleware and decorators provide easy-to-use protection
|
|
|
|
against `clickjacking`_. This type of attack occurs when a malicious site
|
|
|
|
tricks a user into clicking on a concealed element of another site which they
|
|
|
|
have loaded in a hidden frame or iframe.
|
|
|
|
|
|
|
|
.. versionadded:: 1.4
|
|
|
|
The clickjacking middleware and decorators were added.
|
|
|
|
|
|
|
|
.. _clickjacking: http://en.wikipedia.org/wiki/Clickjacking
|
|
|
|
|
|
|
|
An example of clickjacking
|
|
|
|
==========================
|
|
|
|
|
|
|
|
Suppose an online store has a page where a logged in user can click "Buy Now" to
|
|
|
|
purchase an item. A user has chosen to stay logged into the store all the time
|
|
|
|
for convenience. An attacker site might create an "I Like Ponies" button on one
|
|
|
|
of their own pages, and load the store's page in a transparent iframe such that
|
|
|
|
the "Buy Now" button is invisibly overlaid on the "I Like Ponies" button. If the
|
|
|
|
user visits the attacker site and clicks "I Like Ponies" he will inadvertently
|
2011-05-31 06:50:11 +08:00
|
|
|
click on the online store's "Buy Now" button and unknowingly purchase the item.
|
2011-05-31 06:27:47 +08:00
|
|
|
|
2011-06-10 23:14:36 +08:00
|
|
|
.. _clickjacking-prevention:
|
|
|
|
|
2011-05-31 06:27:47 +08:00
|
|
|
Preventing clickjacking
|
|
|
|
=======================
|
|
|
|
|
|
|
|
Modern browsers honor the `X-Frame-Options`_ HTTP header that indicates whether
|
|
|
|
or not a resource is allowed to load within a frame or iframe. If the response
|
|
|
|
contains the header with a value of SAMEORIGIN then the browser will only load
|
|
|
|
the resource in a frame if the request originated from the same site. If the
|
|
|
|
header is set to DENY then the browser will block the resource from loading in a
|
|
|
|
frame no matter which site made the request.
|
|
|
|
|
|
|
|
.. _X-Frame-Options: https://developer.mozilla.org/en/The_X-FRAME-OPTIONS_response_header
|
|
|
|
|
|
|
|
Django provides a few simple ways to include this header in responses from your
|
|
|
|
site:
|
|
|
|
|
|
|
|
1. A simple middleware that sets the header in all responses.
|
|
|
|
|
|
|
|
2. A set of view decorators that can be used to override the middleware or to
|
|
|
|
only set the header for certain views.
|
|
|
|
|
|
|
|
How to use it
|
|
|
|
=============
|
|
|
|
|
|
|
|
Setting X-Frame-Options for all responses
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
To set the same X-Frame-Options value for all responses in your site, add
|
|
|
|
``'django.middleware.clickjacking.XFrameOptionsMiddleware'`` to
|
|
|
|
:setting:`MIDDLEWARE_CLASSES`::
|
|
|
|
|
|
|
|
MIDDLEWARE_CLASSES = (
|
|
|
|
...
|
|
|
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
|
|
...
|
|
|
|
)
|
|
|
|
|
|
|
|
By default, the middleware will set the X-Frame-Options header to SAMEORIGIN for
|
|
|
|
every outgoing ``HttpResponse``. If you want DENY instead, set the
|
|
|
|
:setting:`X_FRAME_OPTIONS` setting::
|
|
|
|
|
|
|
|
X_FRAME_OPTIONS = 'DENY'
|
|
|
|
|
|
|
|
When using the middleware there may be some views where you do **not** want the
|
|
|
|
X-Frame-Options header set. For those cases, you can use a view decorator that
|
2011-05-31 06:50:11 +08:00
|
|
|
tells the middleware not to set the header::
|
2011-05-31 06:27:47 +08:00
|
|
|
|
|
|
|
from django.http import HttpResponse
|
|
|
|
from django.views.decorators.clickjacking import xframe_options_exempt
|
|
|
|
|
|
|
|
@xframe_options_exempt
|
|
|
|
def ok_to_load_in_a_frame(request):
|
|
|
|
return HttpResponse("This page is safe to load in a frame on any site.")
|
|
|
|
|
|
|
|
|
|
|
|
Setting X-Frame-Options per view
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
To set the X-Frame-Options header on a per view basis, Django provides these
|
|
|
|
decorators::
|
|
|
|
|
|
|
|
from django.http import HttpResponse
|
|
|
|
from django.views.decorators.clickjacking import xframe_options_deny
|
|
|
|
from django.views.decorators.clickjacking import xframe_options_sameorigin
|
|
|
|
|
|
|
|
@xframe_options_deny
|
|
|
|
def view_one(request):
|
|
|
|
return HttpResponse("I won't display in any frame!")
|
|
|
|
|
|
|
|
@xframe_options_sameorigin
|
|
|
|
def view_two(request):
|
|
|
|
return HttpResponse("Display in a frame if it's from the same origin as me.")
|
|
|
|
|
|
|
|
Note that you can use the decorators in conjunction with the middleware. Use of
|
|
|
|
a decorator overrides the middleware.
|
|
|
|
|
|
|
|
Limitations
|
|
|
|
===========
|
|
|
|
|
|
|
|
The `X-Frame-Options` header will only protect against clickjacking in a modern
|
|
|
|
browser. Older browsers will quietly ignore the header and need `other
|
|
|
|
clickjacking prevention techniques`_.
|
|
|
|
|
|
|
|
Browsers that support X-Frame-Options
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
* Internet Explorer 8+
|
2013-01-01 21:12:42 +08:00
|
|
|
* Firefox 3.6.9+
|
|
|
|
* Opera 10.5+
|
|
|
|
* Safari 4+
|
|
|
|
* Chrome 4.1+
|
2011-05-31 06:27:47 +08:00
|
|
|
|
|
|
|
See also
|
|
|
|
~~~~~~~~
|
|
|
|
|
|
|
|
A `complete list`_ of browsers supporting X-Frame-Options.
|
|
|
|
|
|
|
|
.. _complete list: https://developer.mozilla.org/en/The_X-FRAME-OPTIONS_response_header#Browser_compatibility
|
|
|
|
.. _other clickjacking prevention techniques: http://en.wikipedia.org/wiki/Clickjacking#Prevention
|