Django security releases issued
djangoproject.com
djangoproject.com
Or is the mention of password resets an indicator that an attacker, in their own separate connection, can contaminate an email sent to other users with bad URLs? (If so, detecting suspicious Host values would seem to leave a risk that legal-looking but wrong Host values are still trusted by the email mechanism.)
1. Links are rendered via some function that takes into account the user's current request (ie: to determine the proper host)
2. The "reset your password by clicking this link" URL is generated using that function.
3. I am a malicious attacker and I submit a password reset request for your account.
Thus, I can control the URL that is sent to you in an email.
[So please upgrade!]
It seems to me that the deeper risk is composing emails based on a passed Host value, rather than any sort of canonical name the site has for itself. Does the warning about avoiding domain-wildcard setups mean this is still a risk, even after the latest fix?
No, it's not. As the release notes say, "Some attacks against this are beyond Django's ability to control, and require the web server to be properly configured"; see https://docs.djangoproject.com/en/1.4/topics/security/#host-... for details.
The note about "beyond Django's ability to control" seems hand-wavey to me. Avoiding the use of the Host header to construct URLs -- not necessarily as a quick fix, but as a long-term better-practices goal -- would put safety against such attacks completely under Django's control, and provide a bit more defense-in-depth.
My estimation of what would be most safe/robust would be for a deployment to know its own canonical hostname/base-URL, and use that trusted value in construction of emailed URLs.
Perhaps this would be one of the explicit parameters that vary in dev-vs-production configurations. Maybe it's looked up from a key that's the local hostname. Perhaps, even, it's looked up based on the 'Host' header, but if the key is absent it's a failure. (Then, the available mappings are a sort of whitelist.)
The official Django recommendation essentially equates to, "be sure to enforce a whitelist on passed 'Host' values at the HTTP server". So it's leaving responsibility to the many alternate web server configurations Django devs might be using... while it could be solved definitively with a slightly different practice inside Django itself.
On the other hand, you're completely right that the "you gotta get your upstream server configured correctly" advice is handwavy at best.
Seems like this is always the case, this tension between security and usability...
If you've got bright ideas, I'd love to hear 'em. Maybe join us on django-dev (http://groups.google.com/group/django-developers) if you do?
However, my idea is just what's already outlined above: avoid using 'Host', except (perhaps) as a key.
Declaring one or more approved hostnames for accessing an install isn't an onerous requirement (especially if you're assuming that when they're not doing it in Django, they must do it elsewhere to be safe).
Maybe some people (such as in multi-tenancy situations or to make dev/staging/production transitions easier) will choose to use 'Host' directly anyway, or some sort of wildcard for acceptable hostnames. That's fine, but then they'll be accepting the risk by conscious action, deviating from the safer default. That seems better than facing the risk by the inaction of overlooking this more-subtle webserver-configuration issue.
Yes, this is a good idea in theory (it's an offshoot of the idea of avoiding using any data that's provided by the browser.) But in practice, it breaks down any time you need to generate a full URL into the site, i.e.:
* Callback URLs for schemes like OAuth, webhooks, IPN, etc. * Transaction emails with links back to the site ("this week on example.com", "joe just mentioned you..." password resets, etc.) * Links in Atom, RSS feeds, etc.
In each case, Django could require that hosts be hardcoded (perhaps in settings) instead of consulting requests, but that would make each of those things harder to use.
... I'm not really trying to have an argument here; I see your point completely and I think I probably agree, personally. But I am trying to point out that security and usability are often at odds, and that there isn't as much a "right answer" as there is a calibration between those two needs. Drawing the line in the right place is hard.
And even if it's easy enough to do it elsewhere, if in practice it gets overlooked and the costs of overlooking it are high, that would be a good reason to make the lazy/common path the safest path.
Even if it's easy enough to do it elsewhere, if in practice it gets overlooked, and the risks of overlooking it are high, that would be a reason to make the lazy/common path the safest path.
django-announce+subscribe@googlegroups.com