#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: [email protected]
Date: Sun, 24 Mar 2019 05:38:49 -0000
Message-ID:
<[email protected]>
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: [email protected]
Date: Sun, 24 Mar 2019 05:38:59 -0000
Message-ID:
<[email protected]>
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 [email protected].
To post to this group, send email to [email protected].
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.