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

Reply via email to