]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
docs: Add warnings about DNS rebinding attacks 2297/head
authorBen Darnell <ben@bendarnell.com>
Sun, 4 Mar 2018 16:52:06 +0000 (11:52 -0500)
committerBen Darnell <ben@bendarnell.com>
Sun, 4 Mar 2018 16:55:00 +0000 (11:55 -0500)
Fixes #2256

docs/guide/security.rst
tornado/web.py

index 02c16f0ba16c18f9b784d3cc4c05fe24f5ad9989..f71f323aed1e86f6119d84c130d6762085f19731 100644 (file)
@@ -292,3 +292,46 @@ disable XSRF protection by making ``check_xsrf_cookie()`` do nothing.
 However, if you support both cookie and non-cookie-based authentication,
 it is important that XSRF protection be used whenever the current
 request is authenticated with a cookie.
+
+.. _dnsrebinding:
+
+DNS Rebinding
+~~~~~~~~~~~~~
+
+`DNS rebinding <https://en.wikipedia.org/wiki/DNS_rebinding>`_ is an
+attack that can bypass the same-origin policy and allow external sites
+to access resources on private networks. This attack involves a DNS
+name (with a short TTL) that alternates between returning an IP
+address controlled by the attacker and one controlled by the victim
+(often a guessable private IP address such as ``127.0.0.1`` or
+``192.168.1.1``).
+
+Applications that use TLS are *not* vulnerable to this attack (because
+the browser will display certificate mismatch warnings that block
+automated access to the target site).
+
+Applications that cannot use TLS and rely on network-level access
+controls (for example, assuming that a server on ``127.0.0.1`` can
+only be accessed by the local machine) should guard against DNS
+rebinding by validating the ``Host`` HTTP header. This means passing a
+restrictive hostname pattern to either a `.HostMatches` router or the
+first argument of `.Application.add_handlers`::
+
+    # BAD: uses a default host pattern of r'.*'
+    app = Application([('/foo', FooHandler)])
+
+    # GOOD: only matches localhost or its ip address.
+    app = Application()
+    app.add_handlers(r'(localhost|127\.0\.0\.1)',
+                     [('/foo', FooHandler)])
+
+    # GOOD: same as previous example using tornado.routing.
+    app = Application([
+        (HostMatches(r'(localhost|127\.0\.0\.1)'),
+            [('/foo', FooHandler)]),
+        ])
+
+In addition, the ``default_host`` argument to `.Application` and the
+`.DefaultHostMatches` router must not be used in applications that may
+be vulnerable to DNS rebinding, because it has a similar effect to a
+wildcard host pattern.
index 8abe4bc2a64d78364a71b19f4f3d2532d7196d64..51da1ee9e489a59488011d8439c300f1b265ebe3 100644 (file)
@@ -1888,6 +1888,17 @@ class Application(ReversibleRouter):
     If there's no match for the current request's host, then ``default_host``
     parameter value is matched against host regular expressions.
 
+
+    .. warning::
+
+       Applications that do not use TLS may be vulnerable to :ref:`DNS
+       rebinding <dnsrebinding>` attacks. This attack is especially
+       relevant to applications that only listen on ``127.0.0.1` or
+       other private networks. Appropriate host patterns must be used
+       (instead of the default of ``r'.*'``) to prevent this risk. The
+       ``default_host`` argument must not be used in applications that
+       may be vulnerable to DNS rebinding.
+
     You can serve static files by sending the ``static_path`` setting
     as a keyword argument. We will serve those files from the
     ``/static/`` URI (this is configurable with the
@@ -1898,6 +1909,7 @@ class Application(ReversibleRouter):
 
     .. versionchanged:: 4.5
        Integration with the new `tornado.routing` module.
+
     """
     def __init__(self, handlers=None, default_host=None, transforms=None,
                  **settings):