Skip to content

Commit

Permalink
Sanitize EC2 manifests and image tarballs
Browse files Browse the repository at this point in the history
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
ttx authored and markmc committed Dec 13, 2011
1 parent 8992773 commit 7636322
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 1 deletion.
1 change: 1 addition & 0 deletions MANIFEST.in
Expand Up @@ -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
Expand Down
13 changes: 12 additions & 1 deletion nova/image/s3.py
Expand Up @@ -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

Expand Down Expand Up @@ -315,8 +315,19 @@ def _decrypt_image(encrypted_filename, encrypted_key, encrypted_iv,
{'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]
Expand Down
Binary file added nova/tests/image/abs.tar.gz
Binary file not shown.
Binary file added nova/tests/image/rel.tar.gz
Binary file not shown.
10 changes: 10 additions & 0 deletions nova/tests/image/test_s3.py
Expand Up @@ -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
Expand Down Expand Up @@ -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'))

0 comments on commit 7636322

Please sign in to comment.