Commit 8a753256 authored by Benjamin Peterson's avatar Benjamin Peterson

add a default limit for the amount of data xmlrpclib.gzip_decode will return (closes #16043)

parent 0da1af0f
...@@ -776,7 +776,7 @@ class GzipServerTestCase(BaseServerTestCase): ...@@ -776,7 +776,7 @@ class GzipServerTestCase(BaseServerTestCase):
p.pow(6, 8) p.pow(6, 8)
p("close")() p("close")()
def test_gsip_response(self): def test_gzip_response(self):
t = self.Transport() t = self.Transport()
p = xmlrpclib.ServerProxy(URL, transport=t) p = xmlrpclib.ServerProxy(URL, transport=t)
old = self.requestHandler.encode_threshold old = self.requestHandler.encode_threshold
...@@ -790,6 +790,26 @@ class GzipServerTestCase(BaseServerTestCase): ...@@ -790,6 +790,26 @@ class GzipServerTestCase(BaseServerTestCase):
self.requestHandler.encode_threshold = old self.requestHandler.encode_threshold = old
self.assertTrue(a>b) self.assertTrue(a>b)
class GzipUtilTestCase(unittest.TestCase):
def test_gzip_decode_limit(self):
max_gzip_decode = 20 * 1024 * 1024
data = b'\0' * max_gzip_decode
encoded = xmlrpclib.gzip_encode(data)
decoded = xmlrpclib.gzip_decode(encoded)
self.assertEqual(len(decoded), max_gzip_decode)
data = b'\0' * (max_gzip_decode + 1)
encoded = xmlrpclib.gzip_encode(data)
with self.assertRaisesRegexp(ValueError,
"max gzipped payload length exceeded"):
xmlrpclib.gzip_decode(encoded)
xmlrpclib.gzip_decode(encoded, max_decode=-1)
#Test special attributes of the ServerProxy object #Test special attributes of the ServerProxy object
class ServerProxyTestCase(unittest.TestCase): class ServerProxyTestCase(unittest.TestCase):
def setUp(self): def setUp(self):
...@@ -990,6 +1010,7 @@ def test_main(): ...@@ -990,6 +1010,7 @@ def test_main():
try: try:
import gzip import gzip
xmlrpc_tests.append(GzipServerTestCase) xmlrpc_tests.append(GzipServerTestCase)
xmlrpc_tests.append(GzipUtilTestCase)
except ImportError: except ImportError:
pass #gzip not supported in this build pass #gzip not supported in this build
xmlrpc_tests.append(MultiPathServerTestCase) xmlrpc_tests.append(MultiPathServerTestCase)
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
# 2003-07-12 gp Correct marshalling of Faults # 2003-07-12 gp Correct marshalling of Faults
# 2003-10-31 mvl Add multicall support # 2003-10-31 mvl Add multicall support
# 2004-08-20 mvl Bump minimum supported Python version to 2.1 # 2004-08-20 mvl Bump minimum supported Python version to 2.1
# 2014-12-02 ch/doko Add workaround for gzip bomb vulnerability
# #
# Copyright (c) 1999-2002 by Secret Labs AB. # Copyright (c) 1999-2002 by Secret Labs AB.
# Copyright (c) 1999-2002 by Fredrik Lundh. # Copyright (c) 1999-2002 by Fredrik Lundh.
...@@ -1017,10 +1018,13 @@ def gzip_encode(data): ...@@ -1017,10 +1018,13 @@ def gzip_encode(data):
# in the HTTP header, as described in RFC 1952 # in the HTTP header, as described in RFC 1952
# #
# @param data The encoded data # @param data The encoded data
# @keyparam max_decode Maximum bytes to decode (20MB default), use negative
# values for unlimited decoding
# @return the unencoded data # @return the unencoded data
# @raises ValueError if data is not correctly coded. # @raises ValueError if data is not correctly coded.
# @raises ValueError if max gzipped payload length exceeded
def gzip_decode(data): def gzip_decode(data, max_decode=20971520):
"""gzip encoded data -> unencoded data """gzip encoded data -> unencoded data
Decode data using the gzip content encoding as described in RFC 1952 Decode data using the gzip content encoding as described in RFC 1952
...@@ -1030,11 +1034,16 @@ def gzip_decode(data): ...@@ -1030,11 +1034,16 @@ def gzip_decode(data):
f = BytesIO(data) f = BytesIO(data)
gzf = gzip.GzipFile(mode="rb", fileobj=f) gzf = gzip.GzipFile(mode="rb", fileobj=f)
try: try:
decoded = gzf.read() if max_decode < 0: # no limit
decoded = gzf.read()
else:
decoded = gzf.read(max_decode + 1)
except IOError: except IOError:
raise ValueError("invalid data") raise ValueError("invalid data")
f.close() f.close()
gzf.close() gzf.close()
if max_decode >= 0 and len(decoded) > max_decode:
raise ValueError("max gzipped payload length exceeded")
return decoded return decoded
## ##
......
...@@ -16,6 +16,9 @@ Core and Builtins ...@@ -16,6 +16,9 @@ Core and Builtins
Library Library
------- -------
- Issue #16043: Add a default limit for the amount of data xmlrpclib.gzip_decode
will return. This resolves CVE-2013-1753.
- Issue #16040: CVE-2013-1752: nntplib: Limit maximum line lengths to 2048 to - Issue #16040: CVE-2013-1752: nntplib: Limit maximum line lengths to 2048 to
prevent readline() calls from consuming too much memory. Patch by Jyrki prevent readline() calls from consuming too much memory. Patch by Jyrki
Pulliainen. Pulliainen.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment