Skip to content

Commit

Permalink
Address potential DoS with high compression ratio
Browse files Browse the repository at this point in the history
Fixes CVE-2024-28102

Signed-off-by: Simo Sorce <[email protected]>
  • Loading branch information
simo5 committed Mar 6, 2024
1 parent 240cc60 commit 446a292
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 0 deletions.
7 changes: 7 additions & 0 deletions jwcrypto/jwe.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
from jwcrypto.jwa import JWA
from jwcrypto.jwk import JWKSet

# 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?)
Expand Down Expand Up @@ -422,6 +425,10 @@ def _decrypt(self, key, ppe):

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
Expand Down
26 changes: 26 additions & 0 deletions jwcrypto/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2111,6 +2111,32 @@ def test_pbes2_hs256_aeskw_custom_params(self):
jwa.default_max_pbkdf2_iterations += 2
p2cenc.add_recipient(key)

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):
Expand Down

0 comments on commit 446a292

Please sign in to comment.