Skip to content

Commit

Permalink
[1.5.X] Fixed a security issue in get_host.
Browse files Browse the repository at this point in the history
Full disclosure and new release forthcoming.
  • Loading branch information
apollo13 committed Dec 10, 2012
1 parent fce1fa0 commit 77b06e4
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
3 changes: 2 additions & 1 deletion django/http/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

RAISE_ERROR = object()
absolute_http_url_re = re.compile(r"^https?://", re.I)
host_validation_re = re.compile(r"^([a-z0-9.-]+|\[[a-f0-9]*:[a-f0-9:]+\])(:\d+)?$")


class UnreadablePostError(IOError):
Expand Down Expand Up @@ -64,7 +65,7 @@ def get_host(self):
host = '%s:%s' % (host, server_port)

# Disallow potentially poisoned hostnames.
if set(';/?@&=+$,').intersection(host):
if not host_validation_re.match(host.lower()):
raise SuspiciousOperation('Invalid HTTP_HOST header: %s' % host)

return host
Expand Down
25 changes: 25 additions & 0 deletions docs/topics/security.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,31 @@ recommend you ensure your Web server is configured such that:
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


.. _additional-security-topics:

Additional security topics
Expand Down
10 changes: 7 additions & 3 deletions tests/regressiontests/requests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,15 @@ def test_http_get_host(self):
'12.34.56.78:443',
'[2001:19f0:feee::dead:beef:cafe]',
'[2001:19f0:feee::dead:beef:cafe]:8080',
'xn--4ca9at.com', # Punnycode for öäü.com
]

poisoned_hosts = [
'example.com@evil.tld',
'example.com:dr.frankenstein@evil.tld',
'example.com:someone@somestie.com:80',
'example.com:80/badpath'
'example.com:dr.frankenstein@evil.tld:80',
'example.com:80/badpath',
'example.com: recovermypassword.com',
]

for host in legit_hosts:
Expand Down Expand Up @@ -186,13 +188,15 @@ def test_http_get_host_with_x_forwarded_host(self):
'12.34.56.78:443',
'[2001:19f0:feee::dead:beef:cafe]',
'[2001:19f0:feee::dead:beef:cafe]:8080',
'xn--4ca9at.com', # Punnycode for öäü.com
]

poisoned_hosts = [
'example.com@evil.tld',
'example.com:dr.frankenstein@evil.tld',
'example.com:dr.frankenstein@evil.tld:80',
'example.com:80/badpath'
'example.com:80/badpath',
'example.com: recovermypassword.com',
]

for host in legit_hosts:
Expand Down

0 comments on commit 77b06e4

Please sign in to comment.