Skip to content

Commit

Permalink
Avoid potential DoS with high decompression chunks (#157)
Browse files Browse the repository at this point in the history
Signed-off-by: Sergio Arroutbi <[email protected]>
  • Loading branch information
sarroutbi authored May 17, 2024
1 parent 76ec70b commit efb5cfa
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include <jose/jws.h>
#include <jose/jwe.h>

#define MAX_COMPRESSED_SIZE (256*1024)

typedef enum {
JOSE_HOOK_JWK_KIND_NONE = 0,
JOSE_HOOK_JWK_KIND_TYPE,
Expand Down
3 changes: 3 additions & 0 deletions lib/zlib/deflate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
67 changes: 67 additions & 0 deletions tests/alg_comp.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
#include <jose/jose.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>

static int g_high_compression_tested = 0;
static int g_low_compression_tested = 0;

const struct {
const char *alg;
Expand All @@ -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; i<length; i++) {
c[i] = 'A' + (random() % 26);
}
return c;
}

static void
test_long_string(size_t inputlen) {
jose_io_auto_t *b = NULL;
jose_io_auto_t *c = NULL;
jose_io_auto_t *z = NULL;
void *buf1 = NULL;
void *buf2 = NULL;
size_t blen = 0;
size_t clen = 0;
const jose_hook_alg_t *a = jose_hook_alg_find(JOSE_HOOK_ALG_KIND_COMP, "DEF");
uint8_t* str = get_random_string(inputlen);

/* Test compression first. */
b = jose_io_malloc(NULL, &buf1, &blen);
assert(b);
z = a->comp.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)
Expand Down Expand Up @@ -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;
}

0 comments on commit efb5cfa

Please sign in to comment.