CVE-2011-4596 (published 2011-12-23T22:55Z)

Multiple directory traversal vulnerabilities in OpenStack Nova before 2011.3.1, when the EC2 API and the S3/RegisterImage image-registration method are enabled, allow remote authenticated users to overwrite arbitrary files via a crafted (1) tarball or (2) manifest.

Severity: MEDIUM
CVSS v2 base score: 6.0 (AV:N/AC:M/Au:S/C:P/I:P/A:P)

Weakness information:
cwe_id: CWE-22
cwe_name: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
extended_description: 
            Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.
         
         

Fix information:
repo_url: https://github.com/openstack/nova
commit_details: repo_url: https://github.com/openstack/nova
author: Thierry Carrez
author_date: 2011-12-01 17:54:16+01:00
msg: Sanitize EC2 manifests and image tarballs

Prevent potential directory traversal with malicious EC2 image tarballs,
by making sure the tarfile is safe before unpacking it. Fixes bug 894755

Prevent potential directory traversal with malicious file names in
EC2 image manifests. Fixes bug 885167

Change-Id: If6109047307bd6e654ee9d1254f0d7f31cf741c1
repository: repo_url: https://github.com/openstack/nova
repo_name: openstack/nova
description: OpenStack Compute (Nova). Mirror of code maintained at opendev.org.
repo_language: Python
owner: openstack
file_changes: filename: MANIFEST.in
change_type: ModificationType.MODIFY
diff: @@ -37,6 +37,7 @@ include nova/tests/bundle/1mb.part.0
 include nova/tests/bundle/1mb.part.1
 include nova/tests/api/ec2/public_key/*
 include nova/tests/db/nova.austin.sqlite
+include nova/tests/image/*.tar.gz
 include plugins/xenapi/README
 include plugins/xenapi/etc/xapi.d/plugins/objectstore
 include plugins/xenapi/etc/xapi.d/plugins/pluginlib_nova.py

programming_language: Shell
filename: s3.py
change_type: ModificationType.MODIFY
diff: @@ -155,7 +155,7 @@ class S3ImageService(object):
     @staticmethod
     def _download_file(bucket, filename, local_dir):
         key = bucket.get_key(filename)
-        local_filename = os.path.join(local_dir, filename)
+        local_filename = os.path.join(local_dir, os.path.basename(filename))
         key.get_contents_to_filename(local_filename)
         return local_filename
 
@@ -387,8 +387,19 @@ class S3ImageService(object):
                                     {'image_file': encrypted_filename,
                                      'err': err})
 
+    @staticmethod
+    def _test_for_malicious_tarball(path, filename):
+        """Raises exception if extracting tarball would escape extract path"""
+        tar_file = tarfile.open(filename, 'r|gz')
+        for n in tar_file.getnames():
+            if not os.path.abspath(os.path.join(path, n)).startswith(path):
+                tar_file.close()
+                raise exception.Error(_('Unsafe filenames in image'))
+        tar_file.close()
+
     @staticmethod
     def _untarzip_image(path, filename):
+        S3ImageService._test_for_malicious_tarball(path, filename)
         tar_file = tarfile.open(filename, 'r|gz')
         tar_file.extractall(path)
         image_file = tar_file.getnames()[0]

programming_language: Python
filename: test_s3.py
change_type: ModificationType.MODIFY
diff: @@ -15,6 +15,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import os
+
 from nova import context
 import nova.db.api
 from nova import exception
@@ -130,3 +132,11 @@ class TestS3ImageService(test.TestCase):
             {'device_name': '/dev/sdb0',
              'no_device': True}]
         self.assertEqual(block_device_mapping, expected_bdm)
+
+    def test_s3_malicious_tarballs(self):
+        self.assertRaises(exception.Error,
+            self.image_service._test_for_malicious_tarball,
+            "/unused", os.path.join(os.path.dirname(__file__), 'abs.tar.gz'))
+        self.assertRaises(exception.Error,
+            self.image_service._test_for_malicious_tarball,
+            "/unused", os.path.join(os.path.dirname(__file__), 'rel.tar.gz'))

programming_language: Python