mirror of
https://github.com/django/django.git
synced 2025-08-03 18:38:50 +00:00
[1.5.x] Added a new required ALLOWED_HOSTS setting for HTTP host header validation.
This is a security fix; disclosure and advisory coming shortly.
This commit is contained in:
parent
5d853db90e
commit
a7e33c5bf3
12 changed files with 169 additions and 44 deletions
|
@ -68,6 +68,42 @@ of (Full name, email address). Example::
|
|||
Note that Django will email *all* of these people whenever an error happens.
|
||||
See :doc:`/howto/error-reporting` for more information.
|
||||
|
||||
.. setting:: ALLOWED_HOSTS
|
||||
|
||||
ALLOWED_HOSTS
|
||||
-------------
|
||||
|
||||
Default: ``[]`` (Empty list)
|
||||
|
||||
A list of strings representing the host/domain names that this Django site can
|
||||
serve. This is a security measure to prevent an attacker from poisoning caches
|
||||
and password reset emails with links to malicious hosts by submitting requests
|
||||
with a fake HTTP ``Host`` header, which is possible even under many
|
||||
seemingly-safe webserver configurations.
|
||||
|
||||
Values in this list can be fully qualified names (e.g. ``'www.example.com'``),
|
||||
in which case they will be matched against the request's ``Host`` header
|
||||
exactly (case-insensitive, not including port). A value beginning with a period
|
||||
can be used as a subdomain wildcard: ``'.example.com'`` will match
|
||||
``example.com``, ``www.example.com``, and any other subdomain of
|
||||
``example.com``. A value of ``'*'`` will match anything; in this case you are
|
||||
responsible to provide your own validation of the ``Host`` header (perhaps in a
|
||||
middleware; if so this middleware must be listed first in
|
||||
:setting:`MIDDLEWARE_CLASSES`).
|
||||
|
||||
If the ``Host`` header (or ``X-Forwarded-Host`` if
|
||||
:setting:`USE_X_FORWARDED_HOST` is enabled) does not match any value in this
|
||||
list, the :meth:`django.http.HttpRequest.get_host()` method will raise
|
||||
:exc:`~django.core.exceptions.SuspiciousOperation`.
|
||||
|
||||
When :setting:`DEBUG` is ``True`` or when running tests, host validation is
|
||||
disabled; any host will be accepted. Thus it's usually only necessary to set it
|
||||
in production.
|
||||
|
||||
This validation only applies via :meth:`~django.http.HttpRequest.get_host()`;
|
||||
if your code accesses the ``Host`` header directly from ``request.META`` you
|
||||
are bypassing this security protection.
|
||||
|
||||
.. setting:: ALLOWED_INCLUDE_ROOTS
|
||||
|
||||
ALLOWED_INCLUDE_ROOTS
|
||||
|
|
|
@ -354,6 +354,16 @@ Backwards incompatible changes in 1.5
|
|||
deprecation timeline for a given feature, its removal may appear as a
|
||||
backwards incompatible change.
|
||||
|
||||
``ALLOWED_HOSTS`` required in production
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The new :setting:`ALLOWED_HOSTS` setting validates the request's ``Host``
|
||||
header and protects against host-poisoning attacks. This setting is now
|
||||
required whenever :setting:`DEBUG` is ``False``, or else
|
||||
:meth:`django.http.HttpRequest.get_host()` will raise
|
||||
:exc:`~django.core.exceptions.SuspiciousOperation`. For more details see the
|
||||
:setting:`full documentation<ALLOWED_HOSTS>` for the new setting.
|
||||
|
||||
Managers on abstract models
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -167,47 +167,40 @@ server, there are some additional steps you may need:
|
|||
|
||||
.. _host-headers-virtual-hosting:
|
||||
|
||||
Host headers and virtual hosting
|
||||
================================
|
||||
Host header validation
|
||||
======================
|
||||
|
||||
Django uses the ``Host`` header provided by the client to construct URLs
|
||||
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
|
||||
recommend you ensure your Web server is configured such that:
|
||||
Django uses the ``Host`` header provided by the client to construct URLs in
|
||||
certain cases. While these values are sanitized to prevent Cross Site Scripting
|
||||
attacks, a fake ``Host`` value can be used for Cross-Site Request Forgery,
|
||||
cache poisoning attacks, and poisoning links in emails.
|
||||
|
||||
* 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.
|
||||
Because even seemingly-secure webserver configurations are susceptible to fake
|
||||
``Host`` headers, Django validates ``Host`` headers against the
|
||||
:setting:`ALLOWED_HOSTS` setting in the
|
||||
:meth:`django.http.HttpRequest.get_host()` method.
|
||||
|
||||
This validation only applies via :meth:`~django.http.HttpRequest.get_host()`;
|
||||
if your code accesses the ``Host`` header directly from ``request.META`` you
|
||||
are bypassing this security protection.
|
||||
|
||||
For more details see the full :setting:`ALLOWED_HOSTS` documentation.
|
||||
|
||||
.. warning::
|
||||
|
||||
Previous versions of this document recommended configuring your webserver to
|
||||
ensure it validates incoming HTTP ``Host`` headers. While this is still
|
||||
recommended, in many common webservers a configuration that seems to
|
||||
validate the ``Host`` header may not in fact do so. For instance, even if
|
||||
Apache is configured such that your Django site is served from a non-default
|
||||
virtual host with the ``ServerName`` set, it is still possible for an HTTP
|
||||
request to match this virtual host and supply a fake ``Host`` header. Thus,
|
||||
Django now requires that you set :setting:`ALLOWED_HOSTS` explicitly rather
|
||||
than relying on webserver configuration.
|
||||
|
||||
Additionally, as of 1.3.1, Django requires you to explicitly enable support for
|
||||
the ``X-Forwarded-Host`` header if your configuration requires it.
|
||||
|
||||
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
|
||||
the ``X-Forwarded-Host`` header (via the :setting:`USE_X_FORWARDED_HOST`
|
||||
setting) if your configuration requires it.
|
||||
|
||||
|
||||
.. _additional-security-topics:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue