diff options
-rw-r--r-- | swift/common/middleware/s3api/etree.py | 2 | ||||
-rw-r--r-- | test/unit/common/middleware/s3api/test_multi_delete.py | 40 |
2 files changed, 41 insertions, 1 deletions
diff --git a/swift/common/middleware/s3api/etree.py b/swift/common/middleware/s3api/etree.py index dcdd7f616..fa4f63b43 100644 --- a/swift/common/middleware/s3api/etree.py +++ b/swift/common/middleware/s3api/etree.py @@ -128,7 +128,7 @@ class _Element(lxml.etree.ElementBase): parser_lookup = lxml.etree.ElementDefaultClassLookup(element=_Element) -parser = lxml.etree.XMLParser() +parser = lxml.etree.XMLParser(resolve_entities=False, no_network=True) parser.set_element_class_lookup(parser_lookup) Element = parser.makeelement diff --git a/test/unit/common/middleware/s3api/test_multi_delete.py b/test/unit/common/middleware/s3api/test_multi_delete.py index c8bb7206f..8042c2bd9 100644 --- a/test/unit/common/middleware/s3api/test_multi_delete.py +++ b/test/unit/common/middleware/s3api/test_multi_delete.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 import json import unittest from datetime import datetime @@ -373,6 +374,45 @@ class TestS3ApiMultiDelete(S3ApiTestCase): elem = fromstring(body) self.assertEqual(len(elem.findall('Deleted')), len(self.keys)) + def test_object_multi_DELETE_with_system_entity(self): + self.keys = ['Key1', 'Key2'] + self.swift.register( + 'DELETE', '/v1/AUTH_test/bucket/%s' % self.keys[0], + swob.HTTPNotFound, {}, None) + self.swift.register( + 'DELETE', '/v1/AUTH_test/bucket/%s' % self.keys[1], + swob.HTTPNoContent, {}, None) + + elem = Element('Delete') + for key in self.keys: + obj = SubElement(elem, 'Object') + SubElement(obj, 'Key').text = key + body = tostring(elem, use_s3ns=False) + body = body.replace( + b'?>\n', + b'?>\n<!DOCTYPE foo ' + b'[<!ENTITY ent SYSTEM "file:///etc/passwd"> ]>\n', + ).replace(b'>Key1<', b'>Key1&ent;<') + content_md5 = ( + base64.b64encode(md5(body).digest()) + .strip()) + + req = Request.blank('/bucket?delete', + environ={'REQUEST_METHOD': 'POST'}, + headers={ + 'Authorization': 'AWS test:full_control:hmac', + 'Date': self.get_date_header(), + 'Content-MD5': content_md5}, + body=body) + req.date = datetime.now() + req.content_type = 'text/plain' + + status, headers, body = self.call_s3api(req) + self.assertEqual(status, '200 OK', body) + self.assertIn(b'<Deleted><Key>Key2</Key></Deleted>', body) + self.assertNotIn(b'root:/root', body) + self.assertIn(b'<Deleted><Key>Key1</Key></Deleted>', body) + def _test_no_body(self, use_content_length=False, use_transfer_encoding=False, string_to_md5=''): content_md5 = md5(string_to_md5).digest().encode('base64').strip() |