2011-05-30 22:27:47 +00: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.
|
|
|
|
|
2015-08-08 10:02:32 +00:00
|
|
|
.. _clickjacking: https://en.wikipedia.org/wiki/Clickjacking
|
2011-05-30 22:27:47 +00:00
|
|
|
|
|
|
|
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
|
2013-11-30 13:37:15 +00:00
|
|
|
user visits the attacker's site, clicking "I Like Ponies" will cause an
|
|
|
|
inadvertent click on the "Buy Now" button and an unknowing purchase of the item.
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2011-06-10 15:14:36 +00:00
|
|
|
.. _clickjacking-prevention:
|
|
|
|
|
2011-05-30 22:27:47 +00: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
|
2013-03-22 09:50:45 +00:00
|
|
|
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.
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2017-05-20 15:51:21 +00:00
|
|
|
.. _X-Frame-Options: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2019-06-17 14:54:55 +00:00
|
|
|
Django provides a few ways to include this header in responses from your site:
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2019-06-17 14:54:55 +00:00
|
|
|
#. A middleware that sets the header in all responses.
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2018-11-15 18:54:28 +00:00
|
|
|
#. A set of view decorators that can be used to override the middleware or to
|
2011-05-30 22:27:47 +00:00
|
|
|
only set the header for certain views.
|
|
|
|
|
2015-06-02 04:11:01 +00:00
|
|
|
The ``X-Frame-Options`` HTTP header will only be set by the middleware or view
|
|
|
|
decorators if it is not already present in the response.
|
|
|
|
|
2011-05-30 22:27:47 +00:00
|
|
|
How to use it
|
|
|
|
=============
|
|
|
|
|
2016-01-24 21:26:11 +00:00
|
|
|
Setting ``X-Frame-Options`` for all responses
|
|
|
|
---------------------------------------------
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2013-03-22 09:50:45 +00:00
|
|
|
To set the same ``X-Frame-Options`` value for all responses in your site, put
|
2011-05-30 22:27:47 +00:00
|
|
|
``'django.middleware.clickjacking.XFrameOptionsMiddleware'`` to
|
2015-11-07 15:12:37 +00:00
|
|
|
:setting:`MIDDLEWARE`::
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2015-11-07 15:12:37 +00:00
|
|
|
MIDDLEWARE = [
|
2011-05-30 22:27:47 +00:00
|
|
|
...,
|
|
|
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
|
|
...,
|
2015-01-21 16:55:57 +00:00
|
|
|
]
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2014-03-24 15:42:56 +00:00
|
|
|
This middleware is enabled in the settings file generated by
|
|
|
|
:djadmin:`startproject`.
|
Simplified default project template.
Squashed commit of:
commit 508ec9144b35c50794708225b496bde1eb5e60aa
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Tue Jan 29 22:50:55 2013 +0100
Tweaked default settings file.
* Explained why BASE_DIR exists.
* Added a link to the database configuration options, and put it in its
own section.
* Moved sensitive settings that must be changed for production at the
top.
commit 6515fd2f1aa73a86dc8dbd2ccf512ddb6b140d57
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Tue Jan 29 14:35:21 2013 +0100
Documented the simplified app & project templates in the changelog.
commit 2c5b576c2ea91d84273a019b3d0b3b8b4da72f23
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Tue Jan 29 13:59:27 2013 +0100
Minor fixes in tutorials 5 and 6.
commit 55a51531be8104f21b3cca3f6bf70b0a7139a041
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Tue Jan 29 13:51:11 2013 +0100
Updated tutorial 2 for the new project template.
commit 29ddae87bdaecff12dd31b16b000c01efbde9e20
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Tue Jan 29 11:58:54 2013 +0100
Updated tutorial 1 for the new project template.
commit 0ecb9f6e2514cfd26a678a280d471433375101a3
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Tue Jan 29 11:29:13 2013 +0100
Adjusted the default URLconf detection to account for the admin.
It's now enabled by default.
commit 5fb4da0d3d09dac28dd94e3fde92b9d4335c0565
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Tue Jan 29 10:36:55 2013 +0100
Added security warnings for the most sensitive settings.
commit 718d84bd8ac4a42fb4b28ec93965de32680f091e
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 23:24:06 2013 +0100
Used an absolute path for the SQLite database.
This ensures the settings file works regardless of which directory
django-admin.py / manage.py is invoked from.
BASE_DIR got a +1 from a BDFL and another core dev. It doesn't involve
the concept of a "Django project"; it's just a convenient way to express
relative paths within the source code repository for non-Python files.
Thanks Jacob Kaplan-Moss for the suggestion.
commit 1b559b4bcda622e10909b68fe5cab90db6727dd9
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 23:22:40 2013 +0100
Removed STATIC_ROOT from the default settings template.
It isn't necessary in development, and it confuses beginners to no end.
Thanks Carl Meyer for the suggestion.
commit a55f141a500bb7c9a1bc259bbe1954c13b199671
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 23:21:43 2013 +0100
Removed MEDIA_ROOT/URL from default settings template.
Many sites will never deal with user-uploaded files, and MEDIA_ROOT is
complicated to explain.
Thanks Carl Meyer for the suggestion.
commit 44bf2f2441420fd9429ee9fe1f7207f92dd87e70
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 22:22:09 2013 +0100
Removed logging config.
This configuration is applied regardless of the value of LOGGING;
duplicating it in LOGGING is confusing.
commit eac747e848eaed65fd5f6f254f0a7559d856f88f
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 22:05:31 2013 +0100
Enabled the locale middleware by default.
USE_I18N is True by default, and doesn't work well without
LocaleMiddleware.
commit d806c62b2d00826dc2688c84b092627b8d571cab
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 22:03:16 2013 +0100
Enabled clickjacking protection by default.
commit 99152c30e6a15003f0b6737dc78e87adf462aacb
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 22:01:48 2013 +0100
Reorganized settings in logical sections, and trimmed comments.
commit d37ffdfcb24b7e0ec7cc113d07190f65fb12fb8a
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 16:54:11 2013 +0100
Avoided misleading TEMPLATE_DEBUG = DEBUG.
According to the docs TEMPLATE_DEBUG works only when DEBUG = True.
commit 15d9478d3a9850e85841e7cf09cf83050371c6bf
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 16:46:25 2013 +0100
Removed STATICFILES_FINDERS/TEMPLATE_LOADERS from default settings file.
Only developers with special needs ever need to change these settings.
commit 574da0eb5bfb4570883756914b4dbd7e20e1f61e
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 16:45:01 2013 +0100
Removed STATICFILES/TEMPLATES_DIRS from default settings file.
The current best practice is to put static files and templates in
applications, for easier testing and deployment.
commit 8cb18dbe56629aa1be74718a07e7cc66b4f9c9f0
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 16:24:16 2013 +0100
Removed settings related to email reporting from default settings file.
While handy for small scale projects, it isn't exactly a best practice.
commit 8ecbfcb3638058f0c49922540f874a7d802d864f
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Tue Jan 29 18:54:43 2013 +0100
Documented how to enable the sites framework.
commit 23fc91a6fa67d91ddd9d71b1c3e0dc26bdad9841
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 16:28:59 2013 +0100
Disabled the sites framework by default.
RequestSite does the job for single-domain websites.
commit c4d82eb8afc0eb8568bf9c4d12644272415e3960
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Tue Jan 29 00:08:33 2013 +0100
Added a default admin.py to the application template.
Thanks Ryan D Hiebert for the suggestion.
commit 4071dc771e5c44b1c5ebb9beecefb164ae465e22
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 10:59:49 2013 +0100
Enabled the admin by default.
Everyone uses the admin.
commit c807a31f8d89e7e7fd97380e3023f7983a8b6fcb
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 10:57:05 2013 +0100
Removed admindocs from default project template.
commit 09e4ce0e652a97da1a9e285046a91c8ad7a9189c
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 16:32:52 2013 +0100
Added links to the settings documentation.
commit 5b8f5eaef364eb790fcde6f9e86f7d266074cca8
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 11:06:54 2013 +0100
Used a significant example for URLconf includes.
commit 908e91d6fcee2a3cb51ca26ecdf12a6a24e69ef8
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 16:22:31 2013 +0100
Moved code comments about WSGI to docs, and rewrote said docs.
commit 50417e51996146f891d08ca8b74dcc736a581932
Author: Aymeric Augustin <aymeric.augustin@m4x.org>
Date: Mon Jan 28 15:51:50 2013 +0100
Normalized the default application template.
Removed the default test that 1 + 1 = 2, because it's been committed
way too many times, in too many projects.
Added an import of `render` for views, because the first view will
often be:
def home(request):
return render(request, "mysite/home.html")
2013-01-28 14:51:50 +00:00
|
|
|
|
2013-03-22 09:50:45 +00:00
|
|
|
By default, the middleware will set the ``X-Frame-Options`` header to
|
2019-09-07 07:52:10 +00:00
|
|
|
``DENY`` for every outgoing ``HttpResponse``. If you want any other value for
|
|
|
|
this header instead, set the :setting:`X_FRAME_OPTIONS` setting::
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2019-09-07 07:52:10 +00:00
|
|
|
X_FRAME_OPTIONS = "SAMEORIGIN"
|
|
|
|
|
2011-05-30 22:27:47 +00:00
|
|
|
When using the middleware there may be some views where you do **not** want the
|
2013-03-22 09:50:45 +00:00
|
|
|
``X-Frame-Options`` header set. For those cases, you can use a view decorator
|
|
|
|
that tells the middleware not to set the header::
|
2011-05-30 22:27:47 +00:00
|
|
|
|
|
|
|
from django.http import HttpResponse
|
|
|
|
from django.views.decorators.clickjacking import xframe_options_exempt
|
|
|
|
|
2023-02-28 19:53:28 +00:00
|
|
|
|
2011-05-30 22:27:47 +00:00
|
|
|
@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.")
|
|
|
|
|
2019-09-16 10:13:06 +00:00
|
|
|
.. note::
|
|
|
|
|
|
|
|
If you want to submit a form or access a session cookie within a frame or
|
|
|
|
iframe, you may need to modify the :setting:`CSRF_COOKIE_SAMESITE` or
|
|
|
|
:setting:`SESSION_COOKIE_SAMESITE` settings.
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2016-01-24 21:26:11 +00:00
|
|
|
Setting ``X-Frame-Options`` per view
|
|
|
|
------------------------------------
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2013-03-22 09:50:45 +00:00
|
|
|
To set the ``X-Frame-Options`` header on a per view basis, Django provides these
|
2011-05-30 22:27:47 +00:00
|
|
|
decorators::
|
|
|
|
|
|
|
|
from django.http import HttpResponse
|
|
|
|
from django.views.decorators.clickjacking import xframe_options_deny
|
|
|
|
from django.views.decorators.clickjacking import xframe_options_sameorigin
|
|
|
|
|
2023-02-28 19:53:28 +00:00
|
|
|
|
2011-05-30 22:27:47 +00:00
|
|
|
@xframe_options_deny
|
|
|
|
def view_one(request):
|
|
|
|
return HttpResponse("I won't display in any frame!")
|
|
|
|
|
2023-02-28 19:53:28 +00:00
|
|
|
|
2011-05-30 22:27:47 +00:00
|
|
|
@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
|
|
|
|
===========
|
|
|
|
|
2024-07-04 21:08:19 +00:00
|
|
|
The ``X-Frame-Options`` header will only protect against clickjacking in
|
|
|
|
`modern browsers`_.
|
2011-05-30 22:27:47 +00:00
|
|
|
|
2024-07-04 21:08:19 +00:00
|
|
|
.. _modern browsers: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options#browser_compatibility
|