#27379: Django violates RFC7230 when handling requests.
-------------------------------------+-------------------------------------
     Reporter:  Stavros              |                    Owner:  nobody
  Korokithakis                       |
         Type:  Bug                  |                   Status:  new
    Component:  Uncategorized        |                  Version:  1.10
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Changes (by Florian Apolloner):

 * cc: Florian Apolloner (added)


Comment:

 I think this depends on how you configured Nginx. If Nginx works as a
 proxy for your application, this applies (
 https://tools.ietf.org/html/rfc7230#section-5.4 ):
 {{{
    When a proxy receives a request with an absolute-form of
    request-target, the proxy MUST ignore the received Host header field
    (if any) and instead replace it with the host information of the
    request-target.  A proxy that forwards such a request MUST generate a
    new Host field-value based on the received request-target rather than
    forward the received Host field-value.
 }}}
 If Nginx does not work as a proxy, it should reject requests which are not
 compliant to the RFC ( https://tools.ietf.org/html/rfc7230#section-5.3 ):
 {{{
    When making a request directly to an origin server, other than a
    CONNECT or server-wide OPTIONS request (as detailed below), a client
    MUST send only the absolute path and query components of the target
    URI as the request-target.  If the target URI's path component is
    empty, the client MUST send "/" as the path within the origin-form of
    request-target.  A Host header field is also sent, as defined in
    Section 5.4.
 }}}
 In this case it is imo questionable if Nginx should pass an invalid
 request on at all, or answer with 400 already as per (
 https://tools.ietf.org/html/rfc7230#section-5.4 ):
 {{{
    A server MUST respond with a 400 (Bad Request) status code to any
    HTTP/1.1 request message that lacks a Host header field and to any
    request message that contains more than one Host header field or a
    Host header field with an invalid field-value.
 }}}
 It is questionable on whether an invalid request makes the Host header in
 this case invalid, but well.

 Either way, I cannot see any reason for Django to consider such a request
 not as an attack, and therefore the last paragraph of (
 https://tools.ietf.org/html/rfc7230#section-5.5 ) applies:
 {{{
    Once the effective request URI has been constructed, an origin server
    needs to decide whether or not to provide service for that URI via
    the connection in which the request was received.  For example, the
    request might have been misdirected, deliberately or accidentally,
    such that the information within a received request-target or Host
    header field differs from the host or port upon which the connection
    has been made.  If the connection is from a trusted gateway, that
    inconsistency might be expected; otherwise, it might indicate an
    attempt to bypass security filters, trick the server into delivering
    non-public content, or poison a cache.  See Section 9 for security
    considerations regarding message routing.
 }}}

 Django chooses not to honour this request cause the host-header is not
 configured as it expects it too. This is a valid reason to reject the
 request, cause after all a valid client MUST send a valid host-header and
 technically is not allowed to send a full request URI. So unless there is
 any evidence that this has legitimate use cases, I suggest we leave it as
 is to keep the code simple. Another interesting sidenote: How is the
 server supposed to know if `http://example.com` is a full URI or actually
 a path named `http://example.com`?

--
Ticket URL: <https://code.djangoproject.com/ticket/27379#comment:2>
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/071.dd5f2d521970c94503e35b4567b3fc59%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to