#30285: The domain in broken link emails can be spoofed ----------------------------------------+---------------------------- Reporter: orlnub123 | Owner: nobody Type: Bug | Status: new Component: Core (Other) | Version: master Severity: Normal | Keywords: middleware Triage Stage: Unreviewed | Has patch: 1 Needs documentation: 0 | Needs tests: 0 Patch needs improvement: 0 | Easy pickings: 0 UI/UX: 0 | ----------------------------------------+---------------------------- When using BrokenLinkEmailsMiddleware, if an incoming request with a spoofed HTTP Host header 404s it'll use the spoofed header in the email subject. This isn't a big issue because the HTTP Host header gets validated against settings.ALLOWED_HOSTS, so it's only applicable on sites with multiple domains or with multiple settings.ALLOWED_HOSTS values.
Here's a demo on a site with multiple settings.ALLOWED_HOSTS values: ''We start the server.'' {{{ [orlnub123@orlnub123 mysite]$ ./manage.py runserver Performing system checks... System check identified no issues (0 silenced). March 24, 2019 - 05:38:46 Django version 2.1.7, using settings 'mysite.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C. }}} ''Then send a normal request. The referer header here is important; without it the email won't get sent.'' {{{ [orlnub123@orlnub123 mysite]$ curl -H 'Referer: http://example.com/referrer' -w '\n' localhost:8000 <h1>Not Found</h1><p>The requested resource was not found on this server.</p> }}} ''We get the email; everything looks good.'' {{{ Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Django] Broken link on localhost:8000 From: root@localhost To: j...@example.com Date: Sun, 24 Mar 2019 05:38:49 -0000 Message-ID: <155340592942.14004.17031704219271235623@orlnub123.localdomain> Referrer: http://example.com/referrer Requested URL: / User agent: curl/7.64.0 IP address: 127.0.0.1 ------------------------------------------------------------------------------- [24/Mar/2019 05:38:49] "GET / HTTP/1.1" 404 77 }}} ''We send another request; this time with a spoofed host header.'' {{{ [orlnub123@orlnub123 mysite]$ curl -H 'Referer: http://example.com/referrer' -H 'Host: example.com' -w '\n' localhost:8000 <h1>Not Found</h1><p>The requested resource was not found on this server.</p> }}} ''Oh no! The subject contains our spoofed header and presents the link as an internal one.'' {{{ Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [Django] Broken INTERNAL link on example.com From: root@localhost To: j...@example.com Date: Sun, 24 Mar 2019 05:38:59 -0000 Message-ID: <155340593990.14004.12227248404736375101@orlnub123.localdomain> Referrer: http://example.com/referrer Requested URL: / User agent: curl/7.64.0 IP address: 127.0.0.1 ------------------------------------------------------------------------------- [24/Mar/2019 05:38:59] "GET / HTTP/1.1" 404 77 }}} I've fixed it by replacing the `request.get_host()` call with `get_current_site(request).domain`. This approach falls back to using `request.get_host()` internally on sites that don't use the sites framework. It isn't perfect, but it replicates what many other components do. -- Ticket URL: <https://code.djangoproject.com/ticket/30285> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/052.f89411e5085bd05ea6a66ad1483628c6%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.