Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid potential DoS with high decompression chunks #157

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}