diff options
author | Chanho Park <chanho61.park@samsung.com> | 2014-08-19 19:55:55 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-08-19 20:00:12 +0900 |
commit | a7f7fc4c2f1ea290272be7b1145a0a99e85d6acc (patch) | |
tree | 1571928bee6bb229fe1404b8eee0dfebd20503df | |
parent | 89f389745fc16562630b4abb183c1277e91c987d (diff) | |
download | python-a7f7fc4c2f1ea290272be7b1145a0a99e85d6acc.tar.gz python-a7f7fc4c2f1ea290272be7b1145a0a99e85d6acc.tar.bz2 python-a7f7fc4c2f1ea290272be7b1145a0a99e85d6acc.zip |
xmlrpc gzip
Limit the maximum number of decoded data
Change-Id: I90c485b734c36ecfb8a065ab33e7259d8905cb21
Signed-off-by: Chanho Park <chanho61.park@samsung.com>
-rw-r--r-- | Doc/library/xmlrpclib.rst | 9 | ||||
-rw-r--r-- | Lib/test/test_xmlrpc.py | 28 | ||||
-rw-r--r-- | Lib/xmlrpclib.py | 12 |
3 files changed, 47 insertions, 2 deletions
diff --git a/Doc/library/xmlrpclib.rst b/Doc/library/xmlrpclib.rst index 0e9ff4b..ad9b535 100644 --- a/Doc/library/xmlrpclib.rst +++ b/Doc/library/xmlrpclib.rst @@ -127,6 +127,15 @@ between conformable Python objects and XML on the wire. *__dict__* attribute and don't have a base class that is marshalled in a special way. +.. data:: MAX_GZIP_DECODE + + The module constant specifies the amount of bytes that are decompressed by + :func:`gzip_decode`. The default value is *20 MB*. A value of *-1* disables + the protection. + + .. versionadded:: 2.7.4 + The constant was added to strengthen the module against gzip bomb + attacks. .. seealso:: diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index 09235fd..270532e 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -24,6 +24,11 @@ except ImportError: gzip = None try: + import gzip +except ImportError: + gzip = None + +try: unicode except NameError: have_unicode = False @@ -737,7 +742,7 @@ class GzipServerTestCase(BaseServerTestCase): with cm: p.pow(6, 8) - def test_gsip_response(self): + def test_gzip_response(self): t = self.Transport() p = xmlrpclib.ServerProxy(URL, transport=t) old = self.requestHandler.encode_threshold @@ -750,6 +755,27 @@ class GzipServerTestCase(BaseServerTestCase): self.requestHandler.encode_threshold = old self.assertTrue(a>b) + def test_gzip_decode_limit(self): + data = '\0' * xmlrpclib.MAX_GZIP_DECODE + encoded = xmlrpclib.gzip_encode(data) + decoded = xmlrpclib.gzip_decode(encoded) + self.assertEqual(len(decoded), xmlrpclib.MAX_GZIP_DECODE) + + data = '\0' * (xmlrpclib.MAX_GZIP_DECODE + 1) + encoded = xmlrpclib.gzip_encode(data) + + with self.assertRaisesRegexp(ValueError, + "max gzipped payload length exceeded"): + xmlrpclib.gzip_decode(encoded) + + oldmax = xmlrpclib.MAX_GZIP_DECODE + try: + xmlrpclib.MAX_GZIP_DECODE = -1 + xmlrpclib.gzip_decode(encoded) + finally: + xmlrpclib.MAX_GZIP_DECODE = oldmax + + #Test special attributes of the ServerProxy object class ServerProxyTestCase(unittest.TestCase): def setUp(self): diff --git a/Lib/xmlrpclib.py b/Lib/xmlrpclib.py index 1a8b3fb..b87e651 100644 --- a/Lib/xmlrpclib.py +++ b/Lib/xmlrpclib.py @@ -49,6 +49,7 @@ # 2003-07-12 gp Correct marshalling of Faults # 2003-10-31 mvl Add multicall support # 2004-08-20 mvl Bump minimum supported Python version to 2.1 +# 2013-01-20 ch Add workaround for gzip bomb vulnerability # # Copyright (c) 1999-2002 by Secret Labs AB. # Copyright (c) 1999-2002 by Fredrik Lundh. @@ -147,6 +148,10 @@ try: except ImportError: gzip = None #python can be built without zlib/gzip support +# Limit the maximum amount of decoded data that is decompressed. The +# limit prevents gzip bomb attacks. +MAX_GZIP_DECODE = 20 * 1024 * 1024 # 20 MB + # -------------------------------------------------------------------- # Internal stuff @@ -1178,11 +1183,16 @@ def gzip_decode(data): f = StringIO.StringIO(data) gzf = gzip.GzipFile(mode="rb", fileobj=f) try: - decoded = gzf.read() + if MAX_GZIP_DECODE < 0: # no limit + decoded = gzf.read() + else: + decoded = gzf.read(MAX_GZIP_DECODE + 1) except IOError: raise ValueError("invalid data") f.close() gzf.close() + if MAX_GZIP_DECODE >= 0 and len(decoded) > MAX_GZIP_DECODE: + raise ValueError("max gzipped payload length exceeded") return decoded ## |