From 4ee7708bf6dbfaa712749f081eec1f0d122fa001 Mon Sep 17 00:00:00 2001 From: Sergio Correia Date: Mon, 1 Apr 2024 12:10:54 +0100 Subject: [PATCH] Fix potential DoS issue with p2c header Unbounded p2c headers may be used to cause an application that accept PBES algorithms to spend a lot of resources running PBKDF2 with a very high number of iterations. Limit the maximum number of iterations to to 32768. Fixes: CVE-2023-50967 Signed-off-by: Sergio Correia --- lib/openssl/pbes2.c | 9 +++++++-- tests/cve-2023-50967/cve-2023-50967.jwe | 1 + tests/cve-2023-50967/cve-2023-50967.jwk | 1 + tests/jose-jwe-dec | 5 +++++ tests/meson.build | 2 ++ 5 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tests/cve-2023-50967/cve-2023-50967.jwe create mode 100644 tests/cve-2023-50967/cve-2023-50967.jwk diff --git a/lib/openssl/pbes2.c b/lib/openssl/pbes2.c index aae40059..1b3ca309 100644 --- a/lib/openssl/pbes2.c +++ b/lib/openssl/pbes2.c @@ -25,6 +25,8 @@ #include #define NAMES "PBES2-HS256+A128KW", "PBES2-HS384+A192KW", "PBES2-HS512+A256KW" +#define P2C_MIN_ITERATIONS 1000 +#define P2C_MAX_ITERATIONS 32768 static json_t * pbkdf2(const char *alg, jose_cfg_t *cfg, const json_t *jwk, int iter, @@ -193,7 +195,7 @@ alg_wrap_wrp(const jose_hook_alg_t *alg, jose_cfg_t *cfg, json_t *jwe, json_auto_t *hdr = NULL; const char *aes = NULL; json_t *h = NULL; - int p2c = 10000; + int p2c = P2C_MAX_ITERATIONS; size_t stl = 0; if (!json_object_get(cek, "k") && !jose_jwk_gen(cfg, cek)) @@ -226,7 +228,7 @@ alg_wrap_wrp(const jose_hook_alg_t *alg, jose_cfg_t *cfg, json_t *jwe, json_object_set_new(h, "p2c", json_integer(p2c)) < 0) return false; - if (p2c < 1000) + if (p2c < P2C_MIN_ITERATIONS || p2c > P2C_MAX_ITERATIONS) return false; if (json_object_set_new(h, "p2s", jose_b64_enc(st, stl)) == -1) @@ -268,6 +270,9 @@ alg_wrap_unw(const jose_hook_alg_t *alg, jose_cfg_t *cfg, const json_t *jwe, if (json_unpack(hdr, "{s:I}", "p2c", &p2c) == -1) return false; + if (p2c > P2C_MAX_ITERATIONS) + return false; + stl = jose_b64_dec(json_object_get(hdr, "p2s"), NULL, 0); if (stl < 8 || stl > sizeof(st)) return false; diff --git a/tests/cve-2023-50967/cve-2023-50967.jwe b/tests/cve-2023-50967/cve-2023-50967.jwe new file mode 100644 index 00000000..70bfc42e --- /dev/null +++ b/tests/cve-2023-50967/cve-2023-50967.jwe @@ -0,0 +1 @@ +{"ciphertext":"aaPb-JYGACs-loPwJkZewg","encrypted_key":"P1h8q8wLVxqYsZUuw6iEQTzgXVZHCsu8Eik-oqbE4AJGIDto3gb3SA","header":{"alg":"PBES2-HS256+A128KW","p2c":1000000000,"p2s":"qUQQWWkyyIqculSiC93mlg"},"iv":"Clg3JX9oNl_ck3sLSGrlgg","protected":"eyJlbmMiOiJBMTI4Q0JDLUhTMjU2In0","tag":"i7vga9tJkwRswFd7HlyD_A"} diff --git a/tests/cve-2023-50967/cve-2023-50967.jwk b/tests/cve-2023-50967/cve-2023-50967.jwk new file mode 100644 index 00000000..d7fb1beb --- /dev/null +++ b/tests/cve-2023-50967/cve-2023-50967.jwk @@ -0,0 +1 @@ +{"alg":"PBES2-HS256+A128KW","k":"VHBLJ4-PmnqELoKbQoXuRA","key_ops":["wrapKey","unwrapKey"],"kty":"oct"} diff --git a/tests/jose-jwe-dec b/tests/jose-jwe-dec index 7a0c3bfb..e02d12e0 100755 --- a/tests/jose-jwe-dec +++ b/tests/jose-jwe-dec @@ -53,3 +53,8 @@ test "`jose jwe dec -i $prfx.12.jweg -k $prfx.12.jwk`" = "`cat $prfx.12.pt`" test "`jose jwe dec -i $prfx.13.jweg -k $prfx.13.1.jwk`" = "`cat $prfx.13.pt`" test "`jose jwe dec -i $prfx.13.jweg -k $prfx.13.2.jwk`" = "`cat $prfx.13.pt`" test "`jose jwe dec -i $prfx.13.jweg -k $prfx.13.3.jwk`" = "`cat $prfx.13.pt`" + +# CVE-2023-50967 - test originally from https://github.com/P3ngu1nW/CVE_Request/blob/main/latch-jose.md +# This test is expected to fail quickly on patched systems. +prfx="${CVE_2023_50967}/cve-2023-50967" +! test "$(jose jwe dec -i $prfx.jwe -k $prfx.jwk)" diff --git a/tests/meson.build b/tests/meson.build index 37b910a8..1de53a13 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -31,6 +31,8 @@ progs = [ e = environment() e.prepend('PATH', meson.current_build_dir() + '/../cmd', separator: ':') e.set('VECTORS', meson.current_source_dir() + '/vectors') +e.set('CVE_2023_50967', meson.current_source_dir() + '/cve-2023-50967') + foreach p: progs exe = executable(p, p + '.c', dependencies: libjose_dep)