From 95c1565dde6bbd42539fce143abec68f3f2743c2 Mon Sep 17 00:00:00 2001 From: Sergio Arroutbi Date: Thu, 9 May 2024 17:20:05 +0200 Subject: [PATCH] Avoid potential DoS with high decompression chunks Signed-off-by: Sergio Arroutbi --- lib/hooks.h | 2 ++ lib/zlib/deflate.c | 3 +++ tests/alg_comp.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/lib/hooks.h b/lib/hooks.h index d4cd5f93..4208c254 100644 --- a/lib/hooks.h +++ b/lib/hooks.h @@ -20,6 +20,8 @@ #include #include +#define MAX_COMPRESSED_SIZE (256*1024) + typedef enum { JOSE_HOOK_JWK_KIND_NONE = 0, JOSE_HOOK_JWK_KIND_TYPE, diff --git a/lib/zlib/deflate.c b/lib/zlib/deflate.c index 07eca0c9..04ded33e 100644 --- a/lib/zlib/deflate.c +++ b/lib/zlib/deflate.c @@ -113,6 +113,9 @@ def_free(jose_io_t *io) static bool inf_feed(jose_io_t *io, const void *in, size_t len) { + if (len > MAX_COMPRESSED_SIZE) { + return false; + } return feed(io, in, len, inflate); } diff --git a/tests/alg_comp.c b/tests/alg_comp.c index fcd305c1..753566ba 100644 --- a/tests/alg_comp.c +++ b/tests/alg_comp.c @@ -19,6 +19,10 @@ #include #include #include +#include + +static int g_high_compression_tested = 0; +static int g_low_compression_tested = 0; const struct { const char *alg; @@ -41,6 +45,62 @@ const struct { {} }; +const uint32_t long_string_tests[] = { + 2000, 200000, 10000000, 0 +}; + +static uint8_t* get_random_string(uint32_t length) +{ + assert(length); + uint8_t* c = (uint8_t*)malloc(length*sizeof(uint8_t)); + for (uint32_t i=0; icomp.def(a, NULL, b); + assert(z); + + assert(z->feed(z, str, inputlen)); + assert(z->done(z)); + + /* Test decompression now */ + c = jose_io_malloc(NULL, &buf2, &clen); + assert(b); + z = a->comp.inf(a, NULL, c); + assert(z); + + /* If length>MAX_COMPRESSED_SIZE, it must fail due to high decompression size */ + if(blen > MAX_COMPRESSED_SIZE) { + assert(!z->feed(z, buf1, blen)); + g_high_compression_tested = 1; + } else { + assert(z->feed(z, buf1, blen)); + g_low_compression_tested = 1; + /* Compare the final output with the original input. */ + assert(clen == inputlen); + assert(memcmp(buf2, str, inputlen) == 0); + } + assert(z->done(z)); + free(str); +} + static void test(const jose_hook_alg_t *a, bool iter, const uint8_t *i, size_t il) @@ -119,5 +179,12 @@ main(int argc, char *argv[]) tst_inf, sizeof(tst_inf)); } + for (size_t i = 0; long_string_tests[i]; i++) { + test_long_string(long_string_tests[i]); + } + + assert(1 == g_high_compression_tested); + assert(1 == g_low_compression_tested); + return EXIT_SUCCESS; }