Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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

(cherry picked from commit ad32419)

Change-Id: If6109047307bd6e654ee9d1254f0d7f31cf741c1
  • Loading branch information...
commit 76363226bd8533256f7795bba358d7f4b8a6c9e6 1 parent 8992773
@ttx ttx authored markmc committed
View
1  MANIFEST.in
@@ -39,6 +39,7 @@ include nova/tests/bundle/1mb.part.0
include nova/tests/bundle/1mb.part.1
include nova/tests/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
View
13 nova/image/s3.py
@@ -100,7 +100,7 @@ def _conn(context):
@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
@@ -316,7 +316,18 @@ def _decrypt_image(encrypted_filename, encrypted_key, encrypted_iv,
'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]
View
BIN  nova/tests/image/abs.tar.gz
Binary file not shown
View
BIN  nova/tests/image/rel.tar.gz
Binary file not shown
View
10 nova/tests/image/test_s3.py
@@ -15,6 +15,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import os
+
from nova import context
from nova import test
from nova.image import s3
@@ -112,3 +114,11 @@ def test_s3_create(self):
{'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'))
Please sign in to comment.
Something went wrong with that request. Please try again.