diff options
| author | Carl Meyer <carl@oddbird.net> | 2013-02-09 11:32:51 -0700 |
|---|---|---|
| committer | Carl Meyer <carl@oddbird.net> | 2013-02-19 10:37:54 -0700 |
| commit | 9936fdb11d0bbf0bd242f259bfb97bbf849d16f8 (patch) | |
| tree | 43770281aab2cce7da09de070c347235d7d31ebe /docs | |
| parent | 57b62a74cb44ac3cf8b1a9d4cf75bfe953208814 (diff) | |
[1.4.x] Added ALLOWED_HOSTS setting for HTTP host header validation.
This is a security fix; disclosure and advisory coming shortly.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/ref/settings.txt | 36 | ||||
| -rw-r--r-- | docs/releases/1.4.4.txt | 39 | ||||
| -rw-r--r-- | docs/releases/index.txt | 1 | ||||
| -rw-r--r-- | docs/topics/security.txt | 62 |
4 files changed, 103 insertions, 35 deletions
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index d7b100f0b9..f992eef3e7 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -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: ``['*']`` + +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 diff --git a/docs/releases/1.4.4.txt b/docs/releases/1.4.4.txt new file mode 100644 index 0000000000..3c5513bb8f --- /dev/null +++ b/docs/releases/1.4.4.txt @@ -0,0 +1,39 @@ +========================== +Django 1.4.4 release notes +========================== + +*February 19, 2013* + +This is the fourth bugfix/security release in the Django 1.4 series. + +Host header poisoning +--------------------- + +Some parts of Django -- independent of end-user-written applications -- make +use of full URLs, including domain name, which are generated from the HTTP Host +header. Django's documentation has for some time contained notes advising users +on how to configure webservers to ensure that only valid Host headers can reach +the Django application. However, it has been reported to us that even with the +recommended webserver configurations there are still techniques available for +tricking many common webservers into supplying the application with an +incorrect and possibly malicious Host header. + +For this reason, Django 1.4.4 adds a new setting, ``ALLOWED_HOSTS``, containing +an explicit list of valid host/domain names for this site. A request with a +Host header not matching an entry in this list will raise +``SuspiciousOperation`` if ``request.get_host()`` is called. For full details +see the documentation for the :setting:`ALLOWED_HOSTS` setting. + +The default value for this setting in Django 1.4.4 is `['*']` (matching any +host), for backwards-compatibility, but we strongly encourage all sites to set +a more restrictive value. + +This host validation is disabled when ``DEBUG`` is ``True`` or when running tests. + + +Other bugfixes and changes +========================== + +* Changed a SQL command syntax to be MySQL 4 compatible (#19702). +* Added backwards-compatibility with old unsalted MD5 passwords (#18144). +* Numerous documentation improvements and fixes. diff --git a/docs/releases/index.txt b/docs/releases/index.txt index 0b465a6d80..3571e03126 100644 --- a/docs/releases/index.txt +++ b/docs/releases/index.txt @@ -20,6 +20,7 @@ Final releases .. toctree:: :maxdepth: 1 + 1.4.4 1.4.2 1.4.1 1.4 diff --git a/docs/topics/security.txt b/docs/topics/security.txt index 0b5112803c..2a784bce85 100644 --- a/docs/topics/security.txt +++ b/docs/topics/security.txt @@ -149,48 +149,40 @@ server, there are some additional steps you may need: .. _additional-security-topics: -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. -Additionally, as of 1.3.1, Django requires you to explicitly enable support for -the ``X-Forwarded-Host`` header if your configuration requires it. +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. -Configuration for Apache ------------------------- +For more details see the full :setting:`ALLOWED_HOSTS` documentation. -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. +.. warning:: -.. _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 + 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 (via the :setting:`USE_X_FORWARDED_HOST` +setting) if your configuration requires it. |
