Opened 16 years ago

Closed 16 years ago

Last modified 12 years ago

#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)

7472.patch (1.2 KB ) - added by Fraser Nevett 16 years ago.
7472-2.patch (3.5 KB ) - added by Fraser Nevett 16 years ago.

Download all attachments as: .zip

Change History (12)

by Fraser Nevett, 16 years ago

Attachment: 7472.patch added

comment:1 by Simon Greenhill, 16 years ago

Triage Stage: UnreviewedAccepted

comment:2 by durdinator, 16 years ago

Cc: me@… added

comment:3 by Marc Fargas, 16 years ago

Patch needs improvement: set

That should also patch the relevant documentation alerting users that mails from HTTPS connections won't have request info.

by Fraser Nevett, 16 years ago

Attachment: 7472-2.patch added

comment:4 by Fraser Nevett, 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:5 by James Bennett, 16 years ago

Erm. Isn't this what secure email is for?

comment:6 by Malcolm Tredinnick, 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 James Bennett, 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 Fraser Nevett, 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' and EMAIL_USE_TLS = True).
  • ADMINS is set to (('John Doe', 'john.doe@examle.net'),).
  • The MX record of example.net is mail.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 Jacob, 16 years ago

Resolution: wontfix
Status: newclosed

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).

comment:10 by Jacob, 12 years ago

milestone: 1.0 beta

Milestone 1.0 beta deleted

Note: See TracTickets for help on using tickets.
Back to Top