From: Ben Darnell Date: Sun, 4 Mar 2018 16:52:06 +0000 (-0500) Subject: docs: Add warnings about DNS rebinding attacks X-Git-Tag: v5.0.0~3^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9e21ef7bf527b2901234eedd6b668da02aa5ca45;p=thirdparty%2Ftornado.git docs: Add warnings about DNS rebinding attacks Fixes #2256 --- diff --git a/docs/guide/security.rst b/docs/guide/security.rst index 02c16f0ba..f71f323ae 100644 --- a/docs/guide/security.rst +++ b/docs/guide/security.rst @@ -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 `_ 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. diff --git a/tornado/web.py b/tornado/web.py index 8abe4bc2a..51da1ee9e 100644 --- a/tornado/web.py +++ b/tornado/web.py @@ -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 ` 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):