Skip to content

Commit 90477a3

Browse files
committed
Address potential DoS with high compression ratio
Fixes CVE-2024-28102 Signed-off-by: Simo Sorce <[email protected]>
1 parent 240cc60 commit 90477a3

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

jwcrypto/jwe.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
from jwcrypto.jwa import JWA
1111
from jwcrypto.jwk import JWKSet
1212

13+
# Limit the amount of data we are willing to decompress by default.
14+
default_max_compressed_size = 256 * 1024
15+
1316

1417
# RFC 7516 - 4.1
1518
# name: (description, supported?)
@@ -422,6 +425,10 @@ def _decrypt(self, key, ppe):
422425

423426
compress = jh.get('zip', None)
424427
if compress == 'DEF':
428+
if len(data) > default_max_compressed_size:
429+
raise InvalidJWEData(
430+
'Compressed data exceeds maximum allowed'
431+
'size' + f' ({default_max_compressed_size})')
425432
self.plaintext = zlib.decompress(data, -zlib.MAX_WBITS)
426433
elif compress is None:
427434
self.plaintext = data

jwcrypto/tests.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,6 +2111,32 @@ def test_pbes2_hs256_aeskw_custom_params(self):
21112111
jwa.default_max_pbkdf2_iterations += 2
21122112
p2cenc.add_recipient(key)
21132113

2114+
def test_jwe_decompression_max(self):
2115+
key = jwk.JWK(kty='oct', k=base64url_encode(b'A' * (128 // 8)))
2116+
payload = '{"u": "' + "u" * 400000000 + '", "uu":"' \
2117+
+ "u" * 400000000 + '"}'
2118+
protected_header = {
2119+
"alg": "A128KW",
2120+
"enc": "A128GCM",
2121+
"typ": "JWE",
2122+
"zip": "DEF",
2123+
}
2124+
enc = jwe.JWE(payload.encode('utf-8'),
2125+
recipient=key,
2126+
protected=protected_header).serialize(compact=True)
2127+
with self.assertRaises(jwe.InvalidJWEData):
2128+
check = jwe.JWE()
2129+
check.deserialize(enc)
2130+
check.decrypt(key)
2131+
2132+
defmax = jwe.default_max_compressed_size
2133+
jwe.default_max_compressed_size = 1000000000
2134+
# ensure we can eraise the limit and decrypt
2135+
check = jwe.JWE()
2136+
check.deserialize(enc)
2137+
check.decrypt(key)
2138+
jwe.default_max_compressed_size = defmax
2139+
21142140

21152141
class JWATests(unittest.TestCase):
21162142
def test_jwa_create(self):

0 commit comments

Comments
 (0)