17

I'm supposed to set ALLOWED_HOSTS in my Django project's configuration to the hostnames that belong to me 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.

What does this actually mean? Why wouldn't the attacker simply use the "correct" Host header and do the same thing to spam password resets? 'Poisoning caches' also sounds like something that would be between Eve and Bob which I don't have control over anyways...

15

It took me a bit of digging to find it, but I found this which seems to answer the question:

https://www.djangoproject.com/weblog/2013/feb/19/security/#s-issue-host-header-poisoning

Issue: Host header poisoning

Several previous Django security releases have attempted to address persistent issues with the HTTP Host header. Django contains code -- and some functionality shipped with Django itself makes use of that code -- for constructing a fully-qualified URL based on the incoming HTTP request. Depending on configuration, this makes use of the Host header, and so an attacker who can cause a Django application to respond to arbitrary Host headers can cause Django to generate, and display to end users, URLs on arbitrary domains.

Previous iterations of this issue (see CVE-2011-4139 and CVE-2012-4520) have focused on tightening Django's parsing of Host headers, to eliminate various means by which attackers -- using techniques such as username/password pairs in their submitted Host header -- could exploit this.

Ultimately, however, Django alone cannot ensure that an attacker is unable to submit, and cause Django to accept, arbitrary Host headers. Properly securing this in a deployed Django instance additionally requires configuration of the web server, and both the configuration and the achievable level of security vary with the server being used.

In light of this, the get_host() method of django.http.HttpRequest will now validate the Host header against a new setting, ALLOWED_HOSTS. This setting is a list of strings (by default, an empty list) corresponding to acceptable values for the header, with some support for wildcards.

Code which does not use get_host(), or Django configurations which can determine the current hostname without recourse to HTTP headers (i.e., when Django's sites framework is enabled) will not be affected by this change.

Since this is hardening/tightening of a previous issue, it does not have a new CVE number.

9

James Kettle provides a good write up on Practical HTTP Host Header Attacks. They are summarized here with a description of the Django ALLOWED_HOSTS strategy.

Vulnerabilities

Password Reset Vector

The password reset email vulnerability that the documentation alludes to is a result of Django and/or its applications using and trusting the HTTP Host value, which is provided by the client (sound like a bad idea?). The Host value is copied directly into password reset emails, providing a handy injection vector.

Cache Poisoning

The cache poisoning variation relies on this behavior, and also on differences in the way the HOST header is handled by servers and caching solutions.

HTTP_SERVER vs HTTP['HOST']

As Kettle describes, due to RFC2616, it is possible with compliant servers to use a discrepancy between HTTP_SERVER and HTTP['HOST'] to deliver arbitrary Host strings.

Host Parsing

By exploiting different formats and using special characters, an attacker can cause an 'allowed' Host to be interpreted maliciously in different contexts. This is again an error in the application that trusted the Host string.

Django Solution

As the release notes provided by Catskul summarize, the Django solution is to have the user put the allowed hosts directly into the project code. By forbidding any other hosts that don't match ALLOWED_HOSTS, the injection vector is eliminated (a "white listing" approach).

This is something of a clunky solution, as James points out, but it's also pretty effective.

Keep in Mind

It's possible to use wildcards in a project's settings, in which case this feature doesn't help secure anything.

A secure application developer will avoid using the HTTP Host value in any meaningful way.

References

Carlos Bueno, Cache Poisoning (2008)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.