Blacklist urlopen-like functions in urllib, urllib2

The functions and objects urllib.urlopen, urllib.urlretrieve,
urllib.URLopener, urllib.FancyURLopener, urllib2.urlopen,
urllib2.Request allow opening http, ftp, and file urls. Often
the ability to open file urls is unexpected and can lead to
leakage of information about the local server or worse. This has
led to bugs in the past. See OSSA-2014-041. Alert that these need
to be audited.

Change-Id: Ia4c4c66efe39cbca7a4c781687b7c3debe418e16
This commit is contained in:
Lucas Fisher
2015-01-16 10:41:38 -08:00
parent 5d3a82d764
commit 24ba70179f
3 changed files with 43 additions and 1 deletions

View File

@@ -69,6 +69,9 @@ blacklist_functions:
- yaml_load:
qualname: yaml.load
message: "Use of unsafe yaml load. Allows instantiation of arbitrary objects. Consider yaml.safe_load()."
- urllib_urlopen:
qualname: urllib.urlopen, urllib.urlretrieve, urllib.URLopener, urllib.FancyURLopener, urllib2.urlopen, urllib2.Request
message: "Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected."
blacklist_imports:
bad_import_sets:
@@ -93,4 +96,4 @@ ssl_with_bad_version:
- 'PROTOCOL_SSLv3' # strict option
- 'PROTOCOL_TLSv1' # strict option
- 'SSLv3_METHOD' # strict option
- 'TLSv1_METHOD' # strict option
- 'TLSv1_METHOD' # strict option

34
examples/urlopen.py Normal file
View File

@@ -0,0 +1,34 @@
''' Example dangerous usage of urllib[2] opener functions
The urllib and urllib2 opener functions and object can open http, ftp,
and file urls. Often, the abilit to open file urls is overlooked leading
to code that can unexpectedly open files on the local server. This
could be used by an attacker to leak information about the server.
'''
import urllib
import urllib2
def test_urlopen():
# urllib
url = urllib.quote('file:///bin/ls')
urllib.urlopen(url, 'blah', 32)
urllib.urlretrieve('file:///bin/ls', '/bin/ls2')
opener = urllib.URLopener()
opener.open('file:///bin/ls')
opener.retrieve('file:///bin/ls')
opener = urllib.FancyURLopener()
opener.open('file:///bin/ls')
opener.retrieve('file:///bin/ls')
# urllib2
handler = urllib2.HTTPBasicAuthHandler()
handler.add_password(realm='test',
uri='http://mysite.com',
user='bob',
passwd='blah')
opener = urllib2.build_opener(handler)
urllib2.install_opener(opener)
urllib2.urlopen('file:///bin/ls')
urllib2.Request('file:///bin/ls')

View File

@@ -215,6 +215,11 @@ class FunctionalTests(unittest.TestCase):
self.b_mgr.run_scope([path])
self.assertEqual(self.b_mgr.scores[0], 16)
def test_urlopen(self):
path = os.path.join(os.getcwd(), 'examples', 'urlopen.py')
self.b_mgr.run_scope([path])
self.assertEqual(self.b_mgr.scores[0], 30)
def test_utils_shell(self):
path = os.path.join(os.getcwd(), 'examples', 'utils-shell.py')
self.b_mgr.run_scope([path])