diff options
| author | Chris McDonough <chrism@plope.com> | 2011-09-08 01:17:11 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-09-08 01:17:11 -0400 |
| commit | 05b8a60dc1e9bac7e8f7edd2a3f41f6bd8131307 (patch) | |
| tree | 227fc54bae60c0e59a735ba0bf696da5cb264a43 | |
| parent | d542103badc125214ef2a518245b93bb63d1642b (diff) | |
| download | pyramid-05b8a60dc1e9bac7e8f7edd2a3f41f6bd8131307.tar.gz pyramid-05b8a60dc1e9bac7e8f7edd2a3f41f6bd8131307.tar.bz2 pyramid-05b8a60dc1e9bac7e8f7edd2a3f41f6bd8131307.zip | |
add additional oob tests and optimize _secure_path
| -rw-r--r-- | pyramid/static.py | 15 | ||||
| -rw-r--r-- | pyramid/tests/test_integration.py | 5 | ||||
| -rw-r--r-- | pyramid/tests/test_static.py | 72 |
3 files changed, 78 insertions, 14 deletions
diff --git a/pyramid/static.py b/pyramid/static.py index 08bade4b3..71534d09c 100644 --- a/pyramid/static.py +++ b/pyramid/static.py @@ -1,3 +1,4 @@ +import os from os.path import normcase, normpath, join, getmtime, getsize, isdir, exists from pkg_resources import resource_exists, resource_filename, resource_isdir import mimetypes @@ -132,9 +133,6 @@ class static_view(object): path = _secure_path(path_tuple) if path is None: - # belt-and-suspenders security; this should never be true - # unless someone screws up the traversal_path code - # (request.subpath is computed via traversal_path too) return HTTPNotFound('Out of bounds: %s' % request.url) if self.package_name: # package resource @@ -168,13 +166,16 @@ class static_view(object): url = url + '?' + qs return HTTPMovedPermanently(url) -has_insecure_pathelement = set(['..', '.', '/', '']).intersection +has_insecure_pathelement = set(['..', '.', '']).intersection +contains_slash = set(['/', os.sep]).intersection @lru_cache(1000) def _secure_path(path_tuple): if has_insecure_pathelement(path_tuple): + # belt-and-suspenders security; this should never be true + # unless someone screws up the traversal_path code + # (request.subpath is computed via traversal_path too) + return None + if any([contains_slash(item) for item in path_tuple]): return None - for item in path_tuple: - if '../' in item: - return None return '/'.join([x.encode('utf-8') for x in path_tuple]) diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index b78cddf4f..753a55d36 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -153,15 +153,10 @@ class TestStaticAppBase(IntegrationBase): def test_oob_dotdotslash_encoded(self): self.testapp.get('/static/%2E%2E%2F/test_integration.py', status=404) - # XXX pdb this def test_oob_slash(self): self.testapp.get('/%2F/test_integration.py', status=404) - def test_oob_dotdotslash_encoded(self): - self.testapp.get('/static/%2E%2E%2F/test_integration.py', status=404) - - class TestStaticAppUsingAbsPath(TestStaticAppBase, unittest.TestCase): package = 'pyramid.tests.pkgs.static_abspath' diff --git a/pyramid/tests/test_static.py b/pyramid/tests/test_static.py index 503552a8e..6dc38fc57 100644 --- a/pyramid/tests/test_static.py +++ b/pyramid/tests/test_static.py @@ -46,13 +46,47 @@ class Test_static_view_use_subpath_False(unittest.TestCase): response = inst(context, request) self.assertTrue('<html>static</html>' in response.body) - def test_resource_out_of_bounds(self): + def test_oob_singledot(self): + inst = self._makeOne('pyramid.tests:fixtures/static') + request = self._makeRequest({'PATH_INFO':'/./index.html'}) + context = DummyContext() + response = inst(context, request) + self.assertEqual(response.status, '200 OK') + self.assertTrue('<html>static</html>' in response.body) + + def test_oob_emptyelement(self): + inst = self._makeOne('pyramid.tests:fixtures/static') + request = self._makeRequest({'PATH_INFO':'//index.html'}) + context = DummyContext() + response = inst(context, request) + self.assertEqual(response.status, '200 OK') + self.assertTrue('<html>static</html>' in response.body) + + def test_oob_dotdotslash(self): inst = self._makeOne('pyramid.tests:fixtures/static') request = self._makeRequest({'PATH_INFO':'/subdir/../../minimal.pt'}) context = DummyContext() response = inst(context, request) self.assertEqual(response.status, '404 Not Found') + def test_oob_dotdotslash_encoded(self): + inst = self._makeOne('pyramid.tests:fixtures/static') + request = self._makeRequest( + {'PATH_INFO':'/subdir/%2E%2E%2F%2E%2E/minimal.pt'}) + context = DummyContext() + response = inst(context, request) + self.assertEqual(response.status, '404 Not Found') + + def test_oob_os_sep(self): + import os + inst = self._makeOne('pyramid.tests:fixtures/static') + dds = '..' + os.sep + request = self._makeRequest({'PATH_INFO':'/subdir/%s%sminimal.pt' % + (dds, dds)}) + context = DummyContext() + response = inst(context, request) + self.assertEqual(response.status, '404 Not Found') + def test_resource_doesnt_exist(self): inst = self._makeOne('pyramid.tests:fixtures/static') request = self._makeRequest({'PATH_INFO':'/notthere'}) @@ -168,7 +202,23 @@ class Test_static_view_use_subpath_True(unittest.TestCase): response = inst(context, request) self.assertTrue('<html>static</html>' in response.body) - def test_resource_out_of_bounds(self): + def test_oob_singledot(self): + inst = self._makeOne('pyramid.tests:fixtures/static') + request = self._makeRequest() + request.subpath = ('.', 'index.html') + context = DummyContext() + response = inst(context, request) + self.assertEqual(response.status, '404 Not Found') + + def test_oob_emptyelement(self): + inst = self._makeOne('pyramid.tests:fixtures/static') + request = self._makeRequest() + request.subpath = ('', 'index.html') + context = DummyContext() + response = inst(context, request) + self.assertEqual(response.status, '404 Not Found') + + def test_oob_dotdotslash(self): inst = self._makeOne('pyramid.tests:fixtures/static') request = self._makeRequest() request.subpath = ('subdir', '..', '..', 'minimal.pt') @@ -176,6 +226,24 @@ class Test_static_view_use_subpath_True(unittest.TestCase): response = inst(context, request) self.assertEqual(response.status, '404 Not Found') + def test_oob_dotdotslash_encoded(self): + inst = self._makeOne('pyramid.tests:fixtures/static') + request = self._makeRequest() + request.subpath = ('subdir', '%2E%2E', '%2E%2E', 'minimal.pt') + context = DummyContext() + response = inst(context, request) + self.assertEqual(response.status, '404 Not Found') + + def test_oob_os_sep(self): + import os + inst = self._makeOne('pyramid.tests:fixtures/static') + dds = '..' + os.sep + request = self._makeRequest() + request.subpath = ('subdir', dds, dds, 'minimal.pt') + context = DummyContext() + response = inst(context, request) + self.assertEqual(response.status, '404 Not Found') + def test_resource_doesnt_exist(self): inst = self._makeOne('pyramid.tests:fixtures/static') request = self._makeRequest() |
