2011-12-17 10:48:27 +08:00
|
|
|
==================
|
|
|
|
Security in Django
|
|
|
|
==================
|
2011-06-10 23:14:36 +08:00
|
|
|
|
2011-12-17 10:48:27 +08:00
|
|
|
This document is an overview of Django's security features. It includes advice
|
|
|
|
on securing a Django-powered site.
|
2011-06-10 23:14:36 +08:00
|
|
|
|
|
|
|
.. _cross-site-scripting:
|
|
|
|
|
|
|
|
Cross site scripting (XSS) protection
|
|
|
|
=====================================
|
|
|
|
|
|
|
|
.. highlightlang:: html+django
|
|
|
|
|
2011-07-17 22:17:26 +08:00
|
|
|
XSS attacks allow a user to inject client side scripts into the browsers of
|
|
|
|
other users. This is usually achieved by storing the malicious scripts in the
|
|
|
|
database where it will be retrieved and displayed to other users, or by getting
|
2011-12-17 10:48:27 +08:00
|
|
|
users to click a link which will cause the attacker's JavaScript to be executed
|
2011-07-17 22:17:26 +08:00
|
|
|
by the user's browser. However, XSS attacks can originate from any untrusted
|
2011-12-17 10:48:27 +08:00
|
|
|
source of data, such as cookies or Web services, whenever the data is not
|
2011-07-17 22:17:26 +08:00
|
|
|
sufficiently sanitized before including in a page.
|
2011-06-10 23:14:36 +08:00
|
|
|
|
|
|
|
Using Django templates protects you against the majority of XSS attacks.
|
|
|
|
However, it is important to understand what protections it provides
|
|
|
|
and its limitations.
|
|
|
|
|
|
|
|
Django templates :ref:`escape specific characters <automatic-html-escaping>`
|
|
|
|
which are particularly dangerous to HTML. While this protects users from most
|
2011-06-14 18:34:52 +08:00
|
|
|
malicious input, it is not entirely foolproof. For example, it will not
|
2011-06-10 23:14:36 +08:00
|
|
|
protect the following:
|
|
|
|
|
|
|
|
.. code-block:: html+django
|
|
|
|
|
|
|
|
<style class={{ var }}>...</style>
|
|
|
|
|
|
|
|
If ``var`` is set to ``'class1 onmouseover=javascript:func()'``, this can result
|
2011-12-17 10:48:27 +08:00
|
|
|
in unauthorized JavaScript execution, depending on how the browser renders
|
2011-06-10 23:14:36 +08:00
|
|
|
imperfect HTML.
|
|
|
|
|
|
|
|
It is also important to be particularly careful when using ``is_safe`` with
|
2012-12-25 22:56:22 +08:00
|
|
|
custom template tags, the :tfilter:`safe` template tag, :mod:`mark_safe
|
2011-06-10 23:14:36 +08:00
|
|
|
<django.utils.safestring>`, and when autoescape is turned off.
|
|
|
|
|
|
|
|
In addition, if you are using the template system to output something other
|
|
|
|
than HTML, there may be entirely separate characters and words which require
|
|
|
|
escaping.
|
|
|
|
|
2011-07-17 22:17:26 +08:00
|
|
|
You should also be very careful when storing HTML in the database, especially
|
|
|
|
when that HTML is retrieved and displayed.
|
2011-06-10 23:14:36 +08:00
|
|
|
|
2012-04-19 23:00:55 +08:00
|
|
|
|
2011-06-10 23:14:36 +08:00
|
|
|
Cross site request forgery (CSRF) protection
|
|
|
|
============================================
|
|
|
|
|
|
|
|
CSRF attacks allow a malicious user to execute actions using the credentials
|
|
|
|
of another user without that user's knowledge or consent.
|
|
|
|
|
|
|
|
Django has built-in protection against most types of CSRF attacks, providing you
|
|
|
|
have :ref:`enabled and used it <using-csrf>` where appropriate. However, as with
|
|
|
|
any mitigation technique, there are limitations. For example, it is possible to
|
|
|
|
disable the CSRF module globally or for particular views. You should only do
|
|
|
|
this if you know what you are doing. There are other :ref:`limitations
|
|
|
|
<csrf-limitations>` if your site has subdomains that are outside of your
|
|
|
|
control.
|
|
|
|
|
|
|
|
:ref:`CSRF protection works <how-csrf-works>` by checking for a nonce in each
|
|
|
|
POST request. This ensures that a malicious user cannot simply "replay" a form
|
2011-12-17 10:48:27 +08:00
|
|
|
POST to your Web site and have another logged in user unwittingly submit that
|
2011-06-10 23:14:36 +08:00
|
|
|
form. The malicious user would have to know the nonce, which is user specific
|
|
|
|
(using a cookie).
|
|
|
|
|
2012-12-25 22:56:22 +08:00
|
|
|
When deployed with :ref:`HTTPS <security-recommendation-ssl>`,
|
|
|
|
``CsrfViewMiddleware`` will check that the HTTP referer header is set to a
|
2012-09-07 04:08:14 +08:00
|
|
|
URL on the same origin (including subdomain and port). Because HTTPS
|
|
|
|
provides additional security, it is imperative to ensure connections use HTTPS
|
|
|
|
where it is available by forwarding insecure connection requests and using
|
|
|
|
HSTS for supported browsers.
|
|
|
|
|
2011-06-10 23:14:36 +08:00
|
|
|
Be very careful with marking views with the ``csrf_exempt`` decorator unless
|
|
|
|
it is absolutely necessary.
|
|
|
|
|
2012-09-07 04:08:14 +08:00
|
|
|
|
2011-06-10 23:14:36 +08:00
|
|
|
SQL injection protection
|
|
|
|
========================
|
|
|
|
|
|
|
|
SQL injection is a type of attack where a malicious user is able to execute
|
|
|
|
arbitrary SQL code on a database. This can result in records
|
|
|
|
being deleted or data leakage.
|
|
|
|
|
|
|
|
By using Django's querysets, the resulting SQL will be properly escaped by
|
|
|
|
the underlying database driver. However, Django also gives developers power to
|
|
|
|
write :ref:`raw queries <executing-raw-queries>` or execute
|
|
|
|
:ref:`custom sql <executing-custom-sql>`. These capabilities should be used
|
|
|
|
sparingly and you should always be careful to properly escape any parameters
|
|
|
|
that the user can control. In addition, you should exercise caution when using
|
|
|
|
:meth:`extra() <django.db.models.query.QuerySet.extra>`.
|
|
|
|
|
|
|
|
Clickjacking protection
|
|
|
|
=======================
|
|
|
|
|
|
|
|
Clickjacking is a type of attack where a malicious site wraps another site
|
|
|
|
in a frame. This attack can result in an unsuspecting user being tricked
|
|
|
|
into performing unintended actions on the target site.
|
|
|
|
|
|
|
|
Django contains :ref:`clickjacking protection <clickjacking-prevention>` in
|
|
|
|
the form of the
|
|
|
|
:mod:`X-Frame-Options middleware <django.middleware.clickjacking.XFrameOptionsMiddleware>`
|
|
|
|
which in a supporting browser can prevent a site from being rendered inside
|
2011-06-14 18:34:52 +08:00
|
|
|
a frame. It is possible to disable the protection on a per view basis
|
2011-06-10 23:14:36 +08:00
|
|
|
or to configure the exact header value sent.
|
|
|
|
|
|
|
|
The middleware is strongly recommended for any site that does not need to have
|
|
|
|
its pages wrapped in a frame by third party sites, or only needs to allow that
|
|
|
|
for a small section of the site.
|
|
|
|
|
2012-09-07 04:08:14 +08:00
|
|
|
.. _security-recommendation-ssl:
|
|
|
|
|
2011-06-10 23:14:36 +08:00
|
|
|
SSL/HTTPS
|
|
|
|
=========
|
|
|
|
|
|
|
|
It is always better for security, though not always practical in all cases, to
|
|
|
|
deploy your site behind HTTPS. Without this, it is possible for malicious
|
|
|
|
network users to sniff authentication credentials or any other information
|
2011-12-17 10:48:27 +08:00
|
|
|
transferred between client and server, and in some cases -- **active** network
|
|
|
|
attackers -- to alter data that is sent in either direction.
|
2011-06-10 23:14:36 +08:00
|
|
|
|
|
|
|
If you want the protection that HTTPS provides, and have enabled it on your
|
2012-06-05 03:31:23 +08:00
|
|
|
server, there are some additional steps you may need:
|
|
|
|
|
|
|
|
* If necessary, set :setting:`SECURE_PROXY_SSL_HEADER`, ensuring that you have
|
|
|
|
understood the warnings there thoroughly. Failure to do this can result
|
|
|
|
in CSRF vulnerabilities, and failure to do it correctly can also be
|
|
|
|
dangerous!
|
2011-06-10 23:14:36 +08:00
|
|
|
|
|
|
|
* Set up redirection so that requests over HTTP are redirected to HTTPS.
|
|
|
|
|
2012-06-05 03:31:23 +08:00
|
|
|
This could be done using a custom middleware. Please note the caveats under
|
|
|
|
:setting:`SECURE_PROXY_SSL_HEADER`. For the case of a reverse proxy, it may be
|
|
|
|
easier or more secure to configure the main Web server to do the redirect to
|
|
|
|
HTTPS.
|
2011-06-10 23:14:36 +08:00
|
|
|
|
|
|
|
* Use 'secure' cookies.
|
|
|
|
|
|
|
|
If a browser connects initially via HTTP, which is the default for most
|
|
|
|
browsers, it is possible for existing cookies to be leaked. For this reason,
|
|
|
|
you should set your :setting:`SESSION_COOKIE_SECURE` and
|
|
|
|
:setting:`CSRF_COOKIE_SECURE` settings to ``True``. This instructs the browser
|
|
|
|
to only send these cookies over HTTPS connections. Note that this will mean
|
|
|
|
that sessions will not work over HTTP, and the CSRF protection will prevent
|
2011-06-14 18:34:52 +08:00
|
|
|
any POST data being accepted over HTTP (which will be fine if you are
|
2011-06-10 23:14:36 +08:00
|
|
|
redirecting all HTTP traffic to HTTPS).
|
|
|
|
|
2012-09-07 03:13:31 +08:00
|
|
|
* Use HTTP Strict Transport Security (HSTS)
|
|
|
|
|
|
|
|
HSTS is an HTTP header that informs a browser that all future connections
|
|
|
|
to a particular site should always use HTTPS. Combined with redirecting
|
|
|
|
requests over HTTP to HTTPS, this will ensure that connections always enjoy
|
|
|
|
the added security of SSL provided one successful connection has occurred.
|
|
|
|
HSTS is usually configured on the web server.
|
|
|
|
|
2012-09-07 04:08:14 +08:00
|
|
|
.. _host-headers-virtual-hosting:
|
2011-06-10 23:14:36 +08:00
|
|
|
|
2011-12-17 10:48:27 +08:00
|
|
|
Host headers and virtual hosting
|
2011-09-10 08:46:38 +08:00
|
|
|
================================
|
|
|
|
|
2011-12-17 10:48:27 +08:00
|
|
|
Django uses the ``Host`` header provided by the client to construct URLs
|
2011-09-10 08:46:38 +08:00
|
|
|
in certain cases. While these values are sanitized to prevent Cross
|
|
|
|
Site Scripting attacks, they can be used for Cross-Site Request
|
|
|
|
Forgery and cache poisoning attacks in some circumstances. We
|
2011-12-17 10:48:27 +08:00
|
|
|
recommend you ensure your Web server is configured such that:
|
|
|
|
|
2012-09-07 04:10:08 +08:00
|
|
|
* It always validates incoming HTTP ``Host`` headers against the expected
|
|
|
|
host name.
|
|
|
|
* Disallows requests with no ``Host`` header.
|
|
|
|
* Is *not* configured with a catch-all virtual host that forwards requests
|
|
|
|
to a Django application.
|
2011-09-10 08:46:38 +08:00
|
|
|
|
2011-12-17 10:48:27 +08:00
|
|
|
Additionally, as of 1.3.1, Django requires you to explicitly enable support for
|
|
|
|
the ``X-Forwarded-Host`` header if your configuration requires it.
|
2011-09-10 08:46:38 +08:00
|
|
|
|
2012-11-28 05:19:37 +08:00
|
|
|
Configuration for Apache
|
|
|
|
------------------------
|
|
|
|
|
|
|
|
The easiest way to get the described behavior in Apache is as follows. Create
|
|
|
|
a `virtual host`_ using the ServerName_ and ServerAlias_ directives to restrict
|
|
|
|
the domains Apache reacts to. Please keep in mind that while the directives do
|
|
|
|
support ports the match is only performed against the hostname. This means that
|
|
|
|
the ``Host`` header could still contain a port pointing to another webserver on
|
|
|
|
the same machine. The next step is to make sure that your newly created virtual
|
|
|
|
host is not also the default virtual host. Apache uses the first virtual host
|
|
|
|
found in the configuration file as default virtual host. As such you have to
|
|
|
|
ensure that you have another virtual host which will act as catch-all virtual
|
|
|
|
host. Just add one if you do not have one already, there is nothing special
|
|
|
|
about it aside from ensuring it is the first virtual host in the configuration
|
|
|
|
file. Debian/Ubuntu users usually don't have to take any action, since Apache
|
|
|
|
ships with a default virtual host in ``sites-available`` which is linked into
|
|
|
|
``sites-enabled`` as ``000-default`` and included from ``apache2.conf``. Just
|
|
|
|
make sure not to name your site ``000-abc``, since files are included in
|
|
|
|
alphabetical order.
|
|
|
|
|
|
|
|
.. _virtual host: http://httpd.apache.org/docs/2.2/vhosts/
|
|
|
|
.. _ServerName: http://httpd.apache.org/docs/2.2/mod/core.html#servername
|
|
|
|
.. _ServerAlias: http://httpd.apache.org/docs/2.2/mod/core.html#serveralias
|
|
|
|
|
|
|
|
|
2012-09-07 04:08:14 +08:00
|
|
|
.. _additional-security-topics:
|
|
|
|
|
2011-06-10 23:14:36 +08:00
|
|
|
Additional security topics
|
|
|
|
==========================
|
|
|
|
|
|
|
|
While Django provides good security protection out of the box, it is still
|
|
|
|
important to properly deploy your application and take advantage of the
|
2011-12-17 10:48:27 +08:00
|
|
|
security protection of the Web server, operating system and other components.
|
2011-06-10 23:14:36 +08:00
|
|
|
|
2011-12-17 10:48:27 +08:00
|
|
|
* Make sure that your Python code is outside of the Web server's root. This
|
2011-07-07 07:44:54 +08:00
|
|
|
will ensure that your Python code is not accidentally served as plain text
|
|
|
|
(or accidentally executed).
|
|
|
|
* Take care with any :ref:`user uploaded files <file-upload-security>`.
|
2011-06-10 23:14:36 +08:00
|
|
|
* Django does not throttle requests to authenticate users. To protect against
|
|
|
|
brute-force attacks against the authentication system, you may consider
|
2011-12-17 10:48:27 +08:00
|
|
|
deploying a Django plugin or Web server module to throttle these requests.
|
2011-06-10 23:14:36 +08:00
|
|
|
* If your site accepts file uploads, it is strongly advised that you limit
|
2011-12-17 10:48:27 +08:00
|
|
|
these uploads in your Web server configuration to a reasonable
|
2011-06-10 23:14:36 +08:00
|
|
|
size in order to prevent denial of service (DOS) attacks. In Apache, this
|
|
|
|
can be easily set using the LimitRequestBody_ directive.
|
|
|
|
* Keep your :setting:`SECRET_KEY` a secret.
|
|
|
|
* It is a good idea to limit the accessibility of your caching system and
|
|
|
|
database using a firewall.
|
|
|
|
|
|
|
|
.. _LimitRequestBody: http://httpd.apache.org/docs/2.2/mod/core.html#limitrequestbody
|