1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
commit 90477a3b6e73da69740e00b8161f53fea19b831f
Author: Simo Sorce <simo@redhat.com>
Date: Tue Mar 5 16:57:17 2024 -0500
Address potential DoS with high compression ratio
Fixes CVE-2024-28102
Signed-off-by: Simo Sorce <simo@redhat.com>
Index: os-python-jwcrypto/jwcrypto/jwe.py
===================================================================
--- os-python-jwcrypto.orig/jwcrypto/jwe.py
+++ os-python-jwcrypto/jwcrypto/jwe.py
@@ -9,6 +9,9 @@ from jwcrypto.common import base64url_de
from jwcrypto.common import json_decode, json_encode
from jwcrypto.jwa import JWA
+# Limit the amount of data we are willing to decompress by default.
+default_max_compressed_size = 256 * 1024
+
# RFC 7516 - 4.1
# name: (description, supported?)
@@ -387,6 +390,10 @@ class JWE:
compress = jh.get('zip', None)
if compress == 'DEF':
+ if len(data) > default_max_compressed_size:
+ raise InvalidJWEData(
+ 'Compressed data exceeds maximum allowed'
+ 'size' + f' ({default_max_compressed_size})')
self.plaintext = zlib.decompress(data, -zlib.MAX_WBITS)
elif compress is None:
self.plaintext = data
Index: os-python-jwcrypto/jwcrypto/tests.py
===================================================================
--- os-python-jwcrypto.orig/jwcrypto/tests.py
+++ os-python-jwcrypto/jwcrypto/tests.py
@@ -1716,6 +1716,32 @@ class ConformanceTests(unittest.TestCase
check.decrypt(key)
self.assertEqual(check.payload, b'plain')
+ def test_jwe_decompression_max(self):
+ key = jwk.JWK(kty='oct', k=base64url_encode(b'A' * (128 // 8)))
+ payload = '{"u": "' + "u" * 400000000 + '", "uu":"' \
+ + "u" * 400000000 + '"}'
+ protected_header = {
+ "alg": "A128KW",
+ "enc": "A128GCM",
+ "typ": "JWE",
+ "zip": "DEF",
+ }
+ enc = jwe.JWE(payload.encode('utf-8'),
+ recipient=key,
+ protected=protected_header).serialize(compact=True)
+ with self.assertRaises(jwe.InvalidJWEData):
+ check = jwe.JWE()
+ check.deserialize(enc)
+ check.decrypt(key)
+
+ defmax = jwe.default_max_compressed_size
+ jwe.default_max_compressed_size = 1000000000
+ # ensure we can eraise the limit and decrypt
+ check = jwe.JWE()
+ check.deserialize(enc)
+ check.decrypt(key)
+ jwe.default_max_compressed_size = defmax
+
class JWATests(unittest.TestCase):
def test_jwa_create(self):
|