components/openstack/swift/patches/CVE-2015-5223.patch
changeset 6853 cf1567491b1b
parent 6852 bf55de364b19
child 6854 52081f923019
--- a/components/openstack/swift/patches/CVE-2015-5223.patch	Wed Sep 07 14:48:42 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-This upstream patch addresses CVE-2015-5223 in swift. It may be removed
-when swift 2.4.0 or later is integrated.
-
-From 0694e1911d10a18075ff99462c96781372422b2c Mon Sep 17 00:00:00 2001
-From: Clay Gerrard <[email protected]>
-Date: Thu, 23 Jul 2015 22:36:21 -0700
-Subject: Disallow unsafe tempurl operations to point to unauthorized data
-
-Do not allow PUT tempurls to create pointers to other data. Specifically
-disallow the creation of DLO object manifests by returning an error if a
-non-safe tempurl request includes an X-Object-Manifest header regardless of
-the value of the header.
-
-This prevents discoverability attacks which can use any PUT tempurl to probe
-for private data by creating a DLO object manifest and then using the PUT
-tempurl to head the object which would 404 if the prefix does not match any
-object data or form a valid DLO HEAD response if it does.
-
-This also prevents a tricky and potentially unexpected consequence of PUT
-tempurls which would make it unsafe to allow a user to download objects
-created by tempurl (even if they just created them) because the result of
-reading the object created via tempurl may not be the data which was uploaded.
-
-[CVE-2015-5223]
-
-Co-Authored-By: Kota Tsuyuzaki <[email protected]>
-
-Closes-Bug: 1453948
-
-Change-Id: I91161dfb0f089c3990aca1b4255b520299ef73c8
-
---- swift-2.3.0/swift/common/middleware/tempurl.py.~1~	2015-04-30 09:57:42.000000000 -0400
-+++ swift-2.3.0/swift/common/middleware/tempurl.py	2015-11-03 17:11:02.364113024 -0500
-@@ -122,11 +122,13 @@
- from urlparse import parse_qs
- 
- from swift.proxy.controllers.base import get_account_info, get_container_info
--from swift.common.swob import HeaderKeyDict, HTTPUnauthorized
-+from swift.common.swob import HeaderKeyDict, HTTPUnauthorized, HTTPBadRequest
- from swift.common.utils import split_path, get_valid_utf8_str, \
-     register_swift_info, get_hmac, streq_const_time, quote
- 
- 
-+DISALLOWED_INCOMING_HEADERS = 'x-object-manifest'
-+
- #: Default headers to remove from incoming requests. Simply a whitespace
- #: delimited list of header names and names can optionally end with '*' to
- #: indicate a prefix match. DEFAULT_INCOMING_ALLOW_HEADERS is a list of
-@@ -230,6 +232,10 @@
-         #: The methods allowed with Temp URLs.
-         self.methods = methods
- 
-+        self.disallowed_headers = set(
-+            'HTTP_' + h.upper().replace('-', '_')
-+            for h in DISALLOWED_INCOMING_HEADERS.split())
-+
-         headers = DEFAULT_INCOMING_REMOVE_HEADERS
-         if 'incoming_remove_headers' in conf:
-             headers = conf['incoming_remove_headers']
-@@ -323,6 +329,13 @@
-                             for hmac in hmac_vals)
-         if not is_valid_hmac:
-             return self._invalid(env, start_response)
-+        # disallowed headers prevent accidently allowing upload of a pointer
-+        # to data that the PUT tempurl would not otherwise allow access for.
-+        # It should be safe to provide a GET tempurl for data that an
-+        # untrusted client just uploaded with a PUT tempurl.
-+        resp = self._clean_disallowed_headers(env, start_response)
-+        if resp:
-+            return resp
-         self._clean_incoming_headers(env)
-         env['swift.authorize'] = lambda req: None
-         env['swift.authorize_override'] = True
-@@ -465,6 +478,22 @@
-             body = '401 Unauthorized: Temp URL invalid\n'
-         return HTTPUnauthorized(body=body)(env, start_response)
- 
-+    def _clean_disallowed_headers(self, env, start_response):
-+        """
-+        Validate the absense of disallowed headers for "unsafe" operations.
-+
-+        :returns: None for safe operations or swob.HTTPBadResponse if the
-+                  request includes disallowed headers.
-+        """
-+        if env['REQUEST_METHOD'] in ('GET', 'HEAD', 'OPTIONS'):
-+            return
-+        for h in env:
-+            if h in self.disallowed_headers:
-+                return HTTPBadRequest(
-+                    body='The header %r is not allowed in this tempurl' %
-+                    h[len('HTTP_'):].title().replace('_', '-'))(
-+                        env, start_response)
-+
-     def _clean_incoming_headers(self, env):
-         """
-         Removes any headers from the WSGI environment as per the
---- swift-2.3.0/test/functional/tests.py.~1~	2015-04-30 09:57:42.000000000 -0400
-+++ swift-2.3.0/test/functional/tests.py	2015-11-03 15:27:42.202245458 -0500
-@@ -2732,6 +2732,42 @@
-         self.assert_(new_obj.info(parms=put_parms,
-                                   cfg={'no_auth_token': True}))
- 
-+    def test_PUT_manifest_access(self):
-+        new_obj = self.env.container.file(Utils.create_name())
-+
-+        # give out a signature which allows a PUT to new_obj
-+        expires = int(time.time()) + 86400
-+        sig = self.tempurl_sig(
-+            'PUT', expires, self.env.conn.make_path(new_obj.path),
-+            self.env.tempurl_key)
-+        put_parms = {'temp_url_sig': sig,
-+                     'temp_url_expires': str(expires)}
-+
-+        # try to create manifest pointing to some random container
-+        try:
-+            new_obj.write('', {
-+                'x-object-manifest': '%s/foo' % 'some_random_container'
-+            }, parms=put_parms, cfg={'no_auth_token': True})
-+        except ResponseError as e:
-+            self.assertEqual(e.status, 400)
-+        else:
-+            self.fail('request did not error')
-+
-+        # create some other container
-+        other_container = self.env.account.container(Utils.create_name())
-+        if not other_container.create():
-+            raise ResponseError(self.conn.response)
-+
-+        # try to create manifest pointing to new container
-+        try:
-+            new_obj.write('', {
-+                'x-object-manifest': '%s/foo' % other_container
-+            }, parms=put_parms, cfg={'no_auth_token': True})
-+        except ResponseError as e:
-+            self.assertEqual(e.status, 400)
-+        else:
-+            self.fail('request did not error')
-+
-     def test_HEAD(self):
-         expires = int(time.time()) + 86400
-         sig = self.tempurl_sig(
---- swift-2.3.0/test/unit/common/middleware/test_tempurl.py.~1~	2015-04-30 09:57:42.000000000 -0400
-+++ swift-2.3.0/test/unit/common/middleware/test_tempurl.py	2015-11-03 15:27:42.202552552 -0500
-@@ -649,6 +649,25 @@
-         self.assertTrue('Temp URL invalid' in resp.body)
-         self.assertTrue('Www-Authenticate' in resp.headers)
- 
-+    def test_disallowed_header_object_manifest(self):
-+        self.tempurl = tempurl.filter_factory({})(self.auth)
-+        method = 'PUT'
-+        expires = int(time() + 86400)
-+        path = '/v1/a/c/o'
-+        key = 'abc'
-+        hmac_body = '%s\n%s\n%s' % (method, expires, path)
-+        sig = hmac.new(key, hmac_body, sha1).hexdigest()
-+        req = self._make_request(
-+            path, method='PUT', keys=[key],
-+            headers={'x-object-manifest': 'private/secret'},
-+            environ={'QUERY_STRING': 'temp_url_sig=%s&temp_url_expires=%s' % (
-+                sig, expires)})
-+        resp = req.get_response(self.tempurl)
-+        self.assertEquals(resp.status_int, 400)
-+        self.assertTrue('header' in resp.body)
-+        self.assertTrue('not allowed' in resp.body)
-+        self.assertTrue('X-Object-Manifest' in resp.body)
-+
-     def test_removed_incoming_header(self):
-         self.tempurl = tempurl.filter_factory({
-             'incoming_remove_headers': 'x-remove-this'})(self.auth)