#30017 closed Bug (wontfix)
Django should assume port 443 for https in django.utils.http.is_same_domain()
Reported by: | Ruslan Dautkhanov | Owned by: | nobody |
---|---|---|---|
Component: | HTTP handling | Version: | 2.1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
More complete explanation posted here - https://stackoverflow.com/questions/53658795/django-how-to-disable-referer-check
the issue is probably in Django code here: https://github.com/django/django/blob/22e8ab02863819093832de9f771bf40a62a6bd4a/django/middleware/csrf.py#L280
referer variable there is a urlparse object (see https://docs.python.org/3/library/urllib.parse.html ) which contains "netloc" property with a port.
Notice the error again - netlocs don't match because one has a port (443) and another doesn't have it (443 port is default for https):
Referer checking failed -
https://hue-dev.discover.abc.com/hue/accounts/login/?next=/
does not match
https://hue-dev.discover.abc.com:443/.
so I guess it should be some sort of Referer field transformation made in nginx config to cut out 443 port explicitly (or add it).
Referer check is failing because django.utils.http.is_same_domain() takes into account port
(in referer.netloc ).
Django should assume that port 443 is default for httpS, and not fail Referer check in this case.
Change History (6)
comment:4 by , 6 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
As per the Stack Overflow question linked, the issue here is a wrong Nginx configuration.
proxy_set_header X-Forwarded-Host $host:$server_port;
You just want to be using $host
, and drop the $server_port
bit.
comment:5 by , 6 years ago
Resolution: | invalid |
---|---|
Status: | closed → new |
Hi Carlton,
If Django assume that port 443 is default for httpS, then it'll not fail Referer check in this case.
https://web.site.com/
and
https://web.site.com:443/
are the same thing, but not for Django referer check.
What we did in nginx is a workaround.
Real problem is on Django side.
Thank you!
Ruslan
comment:6 by , 6 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
Neither the Host
nor the X-Forwarded-Host
include the scheme right? As such it's just not right to say that web.site.com
and web.site.com:443
are the same. The latter includes more information. (Yes, if we also lookup the scheme we might infer the 443
but we're making assumptions in doing so.)
The suggested fix on Stack Overflow seems right to me. (If you must send the port, beyond correcting the Nginx config, you can already adjust ALLOWED_HOSTS
and/or CSRF_TRUSTED_ORIGINS
here.)
comment:7 by , 6 years ago
Resolution: | wontfix |
---|---|
Status: | closed → new |
As I mentioned on SO, we use Django as part of Cloudera Hue product https://github.com/cloudera/hue
and there is no way to inject Django configs like ALLOWED_HOSTS
and/or CSRF_TRUSTED_ORIGINS
there.
Anyway, this would be a workaround for this problem, not a solution.
infer the 443 but we're making assumptions in doing so
Port 443 is not an assumption, but part of Internet Standard RFC-2818
https://tools.ietf.org/html/rfc2818
the default port is 443
All browsers for example, when you type in https://abc.com "assume" same thing unless port is given,
and they "assume" port 80 when you specify http://
- because it's part of Internet Standard.
Neither the Host nor the
X-Forwarded-Host
include the scheme right?
As such it's just not right to say thatweb.site.com
andweb.site.com:443
are the same.
Not quite right. Django has X-Forwarded-Proto
header and it knows that it's https
and not http
.
That's my last attempt to reopen this ticket. Thanks for the feedback, but I believe this
is a real problem in Django.
Moreover, not sure why Django is making a big deal from Referer
check?
It's not a real security as Referer
header can be easily spoofed
https://security.stackexchange.com/questions/66165/does-referrer-header-checking-offer-any-real-world-security-improvement
I wish there would be a way to disable referer check altogether.
Thanks again.
comment:8 by , 6 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
Please TicketClosingReasons/DontReopenTickets.
I see three options here:
- Correct the Nginx config. This seems the obvious answer, the one on the Stack Overflow thread, and presumably you have no problem with it, since you think
web.site.com
andweb.site.com:443
are equivalent, so there's no harm dropping the$server_port
bit. - Add
web.site.com:443
toCSRF_TRUSTED_ORIGINS
(as others have done here). - Add logic examining the environment to infer the
443
port.
I'm sure we could get 3 roughly right with some effort. But I'm equally sure that it would turn out to be wrong for someone's setup. Then we'd have to add edge-case handling and opt-outs and all the rest of it.
In my view such things are simply not worth the effort when options 1 and 2 are available. I suggest you take one of those.
I wish there would be a way to disable referer check altogether.
You could always subclass the CSRF middleware. I wouldn't do that. (I'd go with option 1.)
Related to https://code.djangoproject.com/ticket/26037