#23295: ALLOWED_HOSTS setting is done in the wrong place, should be in a custom
middleware
-------------------------------+--------------------
     Reporter:  mark0978       |      Owner:  nobody
         Type:  Bug            |     Status:  new
    Component:  Uncategorized  |    Version:  1.5
     Severity:  Normal         |   Keywords:
 Triage Stage:  Unreviewed     |  Has patch:  0
Easy pickings:  0              |      UI/UX:  0
-------------------------------+--------------------
 Right now ALLOWED_HOST checking is done in Request.get_host() which is
 called by CommonMiddleware. And then called again in
 fix_location_header(request, response) which means it is impossible to
 redirect an attacker to fbi.gov and at the same time record their attack
 because on a redirect get_host is called twice!

 Raising a suspicious operation just does not belong in Request.get_host(),
 it really isn't part of the function that gives you the host back, it is
 something you do after you get the host information.

 This is what I've had to write to work around this problem:

 {{{#!python
 class CommonMiddleware(DjangoCommonMiddleware):
     """ In an effort to stop the deluge of ALLOWED_HOSTS emails sent at
 our software
     by very stupid pentesters, I have decided to record what they are
 doing, and then
     send them to the fbi.gov site (out of spite).  It shall be interesting
 to see
     if they actually figure it out or not. (But right now I can't do that
 because of
     limitations within Django"""

     def process_request(self, request):

         def get_client_ip(request):
             x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
             if x_forwarded_for:
                 ip = x_forwarded_for.split(',')[0]
             else:
                 ip = request.META.get('REMOTE_ADDR')
             return ip

         try:
             return super(CommonMiddleware, self).process_request(request)
         except SuspiciousOperation as xcpt:
             if 'ALLOWED_HOSTS' in str(xcpt):
                 # We try three options, in order of decreasing preference.
                 if settings.USE_X_FORWARDED_HOST and (
                     'HTTP_X_FORWARDED_HOST' in request.META):
                     host = request.META['HTTP_X_FORWARDED_HOST']
                 elif 'HTTP_HOST' in request.META:
                     host = request.META['HTTP_HOST']
                 else:
                     # Reconstruct the host using the algorithm from PEP
 333.
                     host = request.META['SERVER_NAME']
                     server_port = str(request.META['SERVER_PORT'])
                     if server_port != ('443' if request.is_secure() else
 '80'):
                         host = '%s:%s' % (host, server_port)

                 obj = AllowedHostViolation.objects.create(
                     host_attacked=host,
                     url_attacked=request.get_full_path(),
                     attacker=get_client_ip(request)
                 )
                 response = HttpResponse("You were hoping to have breached
 security!"
                                         " Not today though!"
                                         " Now smile for the camera,
 because you've been busted!\n",
                                         content_type='application/text',
 status=418)
                 response.allowed_host_violation = True
                 return response
             raise

     def process_response(self, request, response):
         """ Have to also do this to keep it from throwing another
 Suspicious Operation """
         if response.allowed_host_violation:
             return response

         return super(CommonMiddleware, self).process_response(request,
 response)

 }}}

 This bug is also present in 1.6 but in that case you get a differentiated
 Exception thrown.  You still can't return a HttpResponseRedirect to send
 them all to fbi.gov though because the logic is in the wrong place.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/23295>
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/051.157cc83ec30a83a1ce4d469a2e07a718%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to