#7472 closed (wontfix)
Potentially sensitive information leaked if an error occurs when a page is served over HTTPS
Reported by: | Fraser Nevett | Owned by: | nobody |
---|---|---|---|
Component: | HTTP handling | Version: | dev |
Severity: | Keywords: | ||
Cc: | me@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
If an error occurs while processing a request, Django sends an email to those defined in settings.ADMIN
. This email contains a repr
of the request object, which includes GET and POST data amongst other things. If the request came in over HTTPS then potentially very sensitive information could be leaked as plain text in the email.
HTTPS is designed to secure the transmission of the data between the browser and the server. The issue here is that the contents of Django's error email is not encrypted, so that as it travels from the web server to the admins' email servers it is in plain text form which any "man in the middle" could read.
The attached patch simply omits the request details if HTTPS was used.
I've discussed this with Jacob on the security mailing list and he's asked me to raise a ticket with this patch and assign it as 1.0 item.
Attachments (2)
Change History (12)
by , 16 years ago
Attachment: | 7472.patch added |
---|
comment:1 by , 16 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 16 years ago
Cc: | added |
---|
comment:3 by , 16 years ago
Patch needs improvement: | set |
---|
by , 16 years ago
Attachment: | 7472-2.patch added |
---|
comment:4 by , 16 years ago
Patch needs improvement: | unset |
---|
I've attached an updated patch which provides some documentation of the new behaviour.
I also noticed that the 404 notification emails have the same issue of potentially leaking sensitive data, so this patch also provides a fix in that part of the code too.
comment:6 by , 16 years ago
I'm -1 on this. It's a faux solution in a way, since it doesn't cover sensible setups like Apache accepting an HTTPS connection forwarding to another web server on the same machine that runs the Django stuff (using HTTP, since it's intra-machine).
Secondly, it's solving a sysadmin problem at the wrong level (and everybody has to pay the price of not seeing that information). The right solution is to use TLS email connections in this case. Django supports that already. If it's considered useful to send the request information, it should always be sent. Otherwise, never sent. As noted, HTTPS protects the browser to server path. It's not an indication or predictor of internal sysadmin or network requirements.
comment:7 by , 16 years ago
Malcolm said it better. And for the record, I already do this, it's ludicrously easy and, in fact, I can't do anything else: my hosting service doesn't permit me to use non-TLS connections to send mail, and doesn't permit me to use non-TLS connections to retrieve my mail. This is very much a configuration issue with an easy solution for anyone paranoid enough to worry about it.
comment:8 by , 16 years ago
My understanding is that the EMAIL_USE_TLS
setting is only used to provide a secure connection between Django and the EMAIL_HOST
. The EMAIL_HOST
will probably then relay the message onwards to the destination mailserver of each of the ADMINS
over connections which are not required to be secure.
Imagine the following scenario:
- The Django web server is at
www.example.com
.
- The web server uses
mail-relay.example.com
to send outbound messages securely (i.e.EMAIL_HOST = 'mail-relay.example.com'
andEMAIL_USE_TLS = True
).
ADMINS
is set to(('John Doe', 'john.doe@examle.net'),)
.
- The MX record of
example.net
ismail.example.net.
So, when an error occurs, the error notification email would be relayed as follows:
+-----------------+ TLS +------------------------+ plain +------------------+ | www.example.com | --------> | mail-relay.example.com | --------> | mail.example.net | +-----------------+ +------------------------+ text +------------------+
Even if TLS is used between www.example.com
and mail-relay.example.com
, there is absolutely no guarantee that the communication between mail-relay.example.com
and mail.example.net
will be secure; RFC3207 states:
A publicly-referenced SMTP server MUST NOT require use of the STARTTLS extension in order to deliver mail locally. This rule prevents the STARTTLS extension from damaging the interoperability of the Internet's SMTP infrastructure. A publicly-referenced SMTP server is an SMTP server which runs on port 25 of an Internet host listed in the MX record (or A record if an MX record is not present) for the domain name on the right hand side of an Internet mail address.
Also, TLS does not provided end-to-end encryption like HTTPS does, but rather only provides security between two directly communicating servers. In the example above, mail-relay.example.com
could be be run by an untrusted party such as your hosting ISP, so cannot really be considered secure. Again, from RFC3207:
It should be noted that SMTP is not an end-to-end mechanism. Thus, if an SMTP client/server pair decide to add TLS privacy, they are not securing the transport from the originating mail user agent to the recipient. Further, because delivery of a single piece of mail may go between more than two SMTP servers, adding TLS privacy to one pair of servers does not mean that the entire SMTP chain has been made private.
With regard to having a public-facing HTTPS server delegating to a secondary internal web server over HTTP, I would have thought the secondary server would want to know the request originated over HTTPS otherwise you may have trouble with other things such as the common request.is_secure() and 'https' or 'http'
construct for building absolute URLs.
I appreciate that completely omitting the details of the request may not ideal; however it would appear that currently the only way to prevent request information being from sent when an error occurs would be to set ADMINS
to ()
. This has the significant downside that you wouldn't receive notification of the error at all.
It may be preferable to have some facility to allow the standard error email construction to be overridden. This would allow you to decide yourself what should go in the error notification email and even allow you to encrypt it using something like S/MIME.
I guess you can already achieve something like this by connecting to the got_request_exception
signal. However, I really think in its default configuration Django should be sensible enough to know that if HTTPS was used then the request information should not be forwarded on over an insecure email channel.
comment:9 by , 16 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
While I appreciate the problem, this isn't something that we need to do for Django. Besides what Malcolm and James said, there's another, even simpler fix: if you're this security-concious, just don't send error emails (use some other notification logging system).
That should also patch the relevant documentation alerting users that mails from HTTPS connections won't have request info.