Skip to content
Permalink
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ttx committed Dec 13, 2011
1 parent 1c08592 commit ad32419
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 @@ -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
Expand Down
13 changes: 12 additions & 1 deletion nova/image/s3.py
Expand Up @@ -155,7 +155,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 @@ -387,8 +387,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
import nova.db.api
from nova import exception
Expand Down Expand Up @@ -130,3 +132,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 ad32419

Please sign in to comment.