facebook/tornado — Issue #392: httpserver.py does not validate X-Forwarded-For is an IP address
Author: kseifriedredhat
Created: 2011-10-27 21:29:20+00:00
State: open

Hi, in httpserver.py we have:

>If ``xheaders`` is ``True``, we support the ``X-Real-Ip`` and ``X Scheme``
>headers, which override the remote IP and HTTP scheme for all requests.
>These headers are useful when running Tornado behind a reverse proxy or
>load balancer.

> .. attribute:: headers
> `HTTPHeader` dictionary-like object for request headers. Acts like
> a case-insensitive dictionary with additional methods for repeated
> headers.

self.headers = headers or httputil.HTTPHeaders()

if connection and connection.xheaders:
# Squid uses X-Forwarded-For, others use X-Real-IP
self.remote_ip = self.headers.get(
"X-Real-Ip", self.headers.get("X-Forwarded-For", remote_ip))
# AWS uses X-Forwarded-Proto
self.protocol = self.headers.get(
"X-Scheme", self.headers.get("X-Forwarded-Proto", protocol))
if self.protocol not in ("http", "https"):
self.protocol = "http"
else:
self.remote_ip = remote_ip
if protocol:
self.protocol = protocol
elif connection and isinstance(connection.stream,
iostream.SSLIOStream):
self.protocol = "https"
else:
self.protocol = "http"

and httputil.HTTPHeaders is just a key value split up, no validation takes place there, so the X-Forwarded-For, which should be an IP, could be anything (JavaScript, text with a new line, etc.) which could potentially result in log file manipulation, XSS, etc.

This is similar to CVE-2011-3187 and CVE-2011-3624 (Rails and Ruby respectively)

Thanks, Kurt Seifried
kseifried@redhat.com, Red Hat Security Response Team