[Python-checkins] cpython (merge 2.5 -> 2.6): Merge urllib/urllib2 security fix from 2.5 branch.

guido.van.rossum python-checkins at python.org
Tue Mar 29 22:11:05 CEST 2011


http://hg.python.org/cpython/rev/c15ab33017ff
changeset: 69045:c15ab33017ff
branch: 2.6
parent: 68802:b99c94261225
parent: 69044:92293101839c
user: guido at google.com
date: Tue Mar 29 10:48:23 2011 -0700
summary:
 Merge urllib/urllib2 security fix from 2.5 branch.
files:
 Lib/test/test_urllib.py | 14 ++++++++++++++
 Lib/test/test_urllib2.py | 22 ++++++++++++++++++++++
 Lib/urllib.py | 12 ++++++++++++
 Lib/urllib2.py | 11 +++++++++++
 Misc/NEWS | 2 ++
 5 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py
--- a/Lib/test/test_urllib.py
+++ b/Lib/test/test_urllib.py
@@ -162,6 +162,20 @@
 finally:
 self.unfakehttp()
 
+ def test_invalid_redirect(self):
+ # urlopen() should raise IOError for many error codes.
+ self.fakehttp("""HTTP/1.1 302 Found
+Date: 2008年1月02日 03:03:54 GMT
+Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
+Location: file:README
+Connection: close
+Content-Type: text/html; charset=iso-8859-1
+""")
+ try:
+ self.assertRaises(IOError, urllib.urlopen, "http://python.org/")
+ finally:
+ self.unfakehttp()
+
 def test_empty_socket(self):
 # urlopen() raises IOError if the underlying socket does not send any
 # data. (#1680230)
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -942,6 +942,28 @@
 self.assertEqual(count,
 urllib2.HTTPRedirectHandler.max_redirections)
 
+ def test_invalid_redirect(self):
+ from_url = "http://example.com/a.html"
+ valid_schemes = ['http', 'https', 'ftp']
+ invalid_schemes = ['file', 'imap', 'ldap']
+ schemeless_url = "example.com/b.html"
+ h = urllib2.HTTPRedirectHandler()
+ o = h.parent = MockOpener()
+ req = Request(from_url)
+ req.timeout = socket._GLOBAL_DEFAULT_TIMEOUT
+
+ for scheme in invalid_schemes:
+ invalid_url = scheme + '://' + schemeless_url
+ self.assertRaises(urllib2.HTTPError, h.http_error_302,
+ req, MockFile(), 302, "Security Loophole",
+ MockHeaders({"location": invalid_url}))
+
+ for scheme in valid_schemes:
+ valid_url = scheme + '://' + schemeless_url
+ h.http_error_302(req, MockFile(), 302, "That's fine",
+ MockHeaders({"location": valid_url}))
+ self.assertEqual(o.req.get_full_url(), valid_url)
+
 def test_cookie_redirect(self):
 # cookies shouldn't leak into redirected requests
 from cookielib import CookieJar
diff --git a/Lib/urllib.py b/Lib/urllib.py
--- a/Lib/urllib.py
+++ b/Lib/urllib.py
@@ -652,6 +652,18 @@
 fp.close()
 # In case the server sent a relative URL, join with original:
 newurl = basejoin(self.type + ":" + url, newurl)
+
+ # For security reasons we do not allow redirects to protocols
+ # other than HTTP, HTTPS or FTP.
+ newurl_lower = newurl.lower()
+ if not (newurl_lower.startswith('http://') or
+ newurl_lower.startswith('https://') or
+ newurl_lower.startswith('ftp://')):
+ raise IOError('redirect error', errcode,
+ errmsg + " - Redirection to url '%s' is not allowed" %
+ newurl,
+ headers)
+
 return self.open(newurl)
 
 def http_error_301(self, url, fp, errcode, errmsg, headers, data=None):
diff --git a/Lib/urllib2.py b/Lib/urllib2.py
--- a/Lib/urllib2.py
+++ b/Lib/urllib2.py
@@ -578,6 +578,17 @@
 
 newurl = urlparse.urljoin(req.get_full_url(), newurl)
 
+ # For security reasons we do not allow redirects to protocols
+ # other than HTTP, HTTPS or FTP.
+ newurl_lower = newurl.lower()
+ if not (newurl_lower.startswith('http://') or
+ newurl_lower.startswith('https://') or
+ newurl_lower.startswith('ftp://')):
+ raise HTTPError(newurl, code,
+ msg + " - Redirection to url '%s' is not allowed" %
+ newurl,
+ headers, fp)
+
 # XXX Probably want to forget about the state of the current
 # request, although that might interact poorly with other
 # handlers that also use handler-specific request attributes
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,8 @@
 *NOTE: Python 2.6 is in security-fix-only mode. No non-security bug fixes are
 allowed. Python 2.6.7 and beyond will be source only releases.*
 
+- Issue #11662: Make urllib and urllib2 ignore redirections if the
+ scheme is not HTTP, HTTPS or FTP (CVE-2011-1521).
 
 Core and Builtins
 -----------------
-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /