Kaydet (Commit) 75d7b615 authored tarafından Senthil Kumaran's avatar Senthil Kumaran

Prevent HTTPoxy attack (CVE-2016-1000110)

Ignore the HTTP_PROXY variable when REQUEST_METHOD environment is set, which
indicates that the script is in CGI mode.

Issue reported and patch contributed by Rémi Rampin.
üst a850ef69
...@@ -525,6 +525,11 @@ setting up a `Basic Authentication`_ handler: :: ...@@ -525,6 +525,11 @@ setting up a `Basic Authentication`_ handler: ::
through a proxy. However, this can be enabled by extending urllib2 as through a proxy. However, this can be enabled by extending urllib2 as
shown in the recipe [#]_. shown in the recipe [#]_.
.. note::
``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; see
the documentation on :func:`~urllib.getproxies`.
Sockets and Layers Sockets and Layers
================== ==================
......
...@@ -295,6 +295,16 @@ Utility functions ...@@ -295,6 +295,16 @@ Utility functions
If both lowercase and uppercase environment variables exist (and disagree), If both lowercase and uppercase environment variables exist (and disagree),
lowercase is preferred. lowercase is preferred.
.. note::
If the environment variable ``REQUEST_METHOD`` is set, which usually
indicates your script is running in a CGI environment, the environment
variable ``HTTP_PROXY`` (uppercase ``_PROXY``) will be ignored. This is
because that variable can be injected by a client using the "Proxy:"
HTTP header. If you need to use an HTTP proxy in a CGI environment,
either use ``ProxyHandler`` explicitly, or make sure the variable name
is in lowercase (or at least the ``_proxy`` suffix).
.. note:: .. note::
urllib also exposes certain utility functions like splittype, splithost and urllib also exposes certain utility functions like splittype, splithost and
others parsing URL into various components. But it is recommended to use others parsing URL into various components. But it is recommended to use
......
...@@ -229,6 +229,11 @@ The following classes are provided: ...@@ -229,6 +229,11 @@ The following classes are provided:
To disable autodetected proxy pass an empty dictionary. To disable autodetected proxy pass an empty dictionary.
.. note::
``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set;
see the documentation on :func:`~urllib.getproxies`.
.. class:: HTTPPasswordMgr() .. class:: HTTPPasswordMgr()
......
...@@ -170,6 +170,18 @@ class ProxyTests(unittest.TestCase): ...@@ -170,6 +170,18 @@ class ProxyTests(unittest.TestCase):
self.assertTrue(urllib.proxy_bypass_environment('anotherdomain.com:8888')) self.assertTrue(urllib.proxy_bypass_environment('anotherdomain.com:8888'))
self.assertTrue(urllib.proxy_bypass_environment('newdomain.com:1234')) self.assertTrue(urllib.proxy_bypass_environment('newdomain.com:1234'))
def test_proxy_cgi_ignore(self):
try:
self.env.set('HTTP_PROXY', 'http://somewhere:3128')
proxies = urllib.getproxies_environment()
self.assertEqual('http://somewhere:3128', proxies['http'])
self.env.set('REQUEST_METHOD', 'GET')
proxies = urllib.getproxies_environment()
self.assertNotIn('http', proxies)
finally:
self.env.unset('REQUEST_METHOD')
self.env.unset('HTTP_PROXY')
def test_proxy_bypass_environment_host_match(self): def test_proxy_bypass_environment_host_match(self):
bypass = urllib.proxy_bypass_environment bypass = urllib.proxy_bypass_environment
self.env.set('NO_PROXY', self.env.set('NO_PROXY',
......
...@@ -1380,12 +1380,21 @@ def getproxies_environment(): ...@@ -1380,12 +1380,21 @@ def getproxies_environment():
If you need a different way, you can pass a proxies dictionary to the If you need a different way, you can pass a proxies dictionary to the
[Fancy]URLopener constructor. [Fancy]URLopener constructor.
""" """
# Get all variables
proxies = {} proxies = {}
for name, value in os.environ.items(): for name, value in os.environ.items():
name = name.lower() name = name.lower()
if value and name[-6:] == '_proxy': if value and name[-6:] == '_proxy':
proxies[name[:-6]] = value proxies[name[:-6]] = value
# CVE-2016-1000110 - If we are running as CGI script, forget HTTP_PROXY
# (non-all-lowercase) as it may be set from the web server by a "Proxy:"
# header from the client
# If "proxy" is lowercase, it will still be used thanks to the next block
if 'REQUEST_METHOD' in os.environ:
proxies.pop('http', None)
# Get lowercase variables
for name, value in os.environ.items(): for name, value in os.environ.items():
if name[-6:] == '_proxy': if name[-6:] == '_proxy':
name = name.lower() name = name.lower()
......
...@@ -1123,6 +1123,7 @@ Burton Radons ...@@ -1123,6 +1123,7 @@ Burton Radons
Jeff Ramnani Jeff Ramnani
Varpu Rantala Varpu Rantala
Brodie Rao Brodie Rao
Rémi Rampin
Senko Rasic Senko Rasic
Antti Rasinen Antti Rasinen
Nikolaus Rath Nikolaus Rath
......
...@@ -29,6 +29,10 @@ Core and Builtins ...@@ -29,6 +29,10 @@ Core and Builtins
Library Library
------- -------
- Issue #27568: Prevent HTTPoxy attack (CVE-2016-1000110). Ignore the
HTTP_PROXY variable when REQUEST_METHOD environment is set, which indicates
that the script is in CGI mode.
- Issue #27130: In the "zlib" module, fix handling of large buffers - Issue #27130: In the "zlib" module, fix handling of large buffers
(typically 2 or 4 GiB). Previously, inputs were limited to 2 GiB, and (typically 2 or 4 GiB). Previously, inputs were limited to 2 GiB, and
compression and decompression operations did not properly handle results of compression and decompression operations did not properly handle results of
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment