Skip to content

Commit 6959e51

Browse files
[AUTO-CHERRYPICK] Patch rabbitmq-server to fix CVE-2023-50966 [Medium] - branch main (#12390)
Co-authored-by: Kanishk Bansal <103916909+Kanishk-Bansal@users.noreply.github.com>
1 parent fd2f126 commit 6959e51

2 files changed

Lines changed: 292 additions & 3 deletions

File tree

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
From 353268ce161dc90fefe599afa83561b9a3cbd14c Mon Sep 17 00:00:00 2001
2+
From: Kanishk-Bansal <kbkanishk975@gmail.com>
3+
Date: Thu, 13 Feb 2025 13:18:41 +0000
4+
Subject: [PATCH] Fix CVE
5+
# Upstream Source: https://github.com/potatosalad/erlang-jose/commit/718d213f07b08056737923f8063d5df56dcb66ae
6+
# Upstream Source2: https://github.com/potatosalad/erlang-jose/commit/a352bb579a98e5bdea4c72ac92b8923afea6dcec
7+
8+
---
9+
deps/jose/src/jose.app.src | 5 ++-
10+
deps/jose/src/jose.erl | 18 +++++++++--
11+
deps/jose/src/jose_server.erl | 39 ++++++++++++++++++++++--
12+
deps/jose/src/jwa/jose_jwa.erl | 2 +-
13+
deps/jose/src/jwe/jose_jwe_alg_pbes2.erl | 38 ++++++++++++++++++-----
14+
5 files changed, 87 insertions(+), 15 deletions(-)
15+
16+
diff --git a/deps/jose/src/jose.app.src b/deps/jose/src/jose.app.src
17+
index 3909e59..3378ea4 100644
18+
--- a/deps/jose/src/jose.app.src
19+
+++ b/deps/jose/src/jose.app.src
20+
@@ -10,4 +10,7 @@
21+
{licenses,["MIT"]},
22+
{links,[{"Github",
23+
"https://github.com/potatosalad/erlang-jose"}]},
24+
- {env,[{crypto_fallback,true}]}]}.
25+
+ {env, [
26+
+ {crypto_fallback, true},
27+
+ {pbes2_count_maximum, 10000}
28+
+ ]}]}.
29+
diff --git a/deps/jose/src/jose.erl b/deps/jose/src/jose.erl
30+
index 58e005d..fe47755 100644
31+
--- a/deps/jose/src/jose.erl
32+
+++ b/deps/jose/src/jose.erl
33+
@@ -23,6 +23,8 @@
34+
-export([encode/1]).
35+
-export([json_module/0]).
36+
-export([json_module/1]).
37+
+-export([pbes2_count_maximum/0]).
38+
+-export([pbes2_count_maximum/1]).
39+
-export([sha3_module/0]).
40+
-export([sha3_module/1]).
41+
-export([unsecured_signing/0]).
42+
@@ -84,17 +86,27 @@ json_module() ->
43+
json_module(JSONModule) when is_atom(JSONModule) ->
44+
?MAYBE_START_JOSE(jose_server:json_module(JSONModule)).
45+
46+
+-spec pbes2_count_maximum() -> non_neg_integer().
47+
+pbes2_count_maximum() ->
48+
+ ?MAYBE_START_JOSE(ets:lookup_element(?TAB, pbes2_count_maximum, 2)).
49+
+
50+
+-spec pbes2_count_maximum(PBES2CountMaximum) -> ok when PBES2CountMaximum :: non_neg_integer().
51+
+pbes2_count_maximum(PBES2CountMaximum) when is_integer(PBES2CountMaximum) andalso PBES2CountMaximum >= 0 ->
52+
+ ?MAYBE_START_JOSE(jose_server:pbes2_count_maximum(PBES2CountMaximum)).
53+
+
54+
sha3_module() ->
55+
?MAYBE_START_JOSE(ets:lookup_element(?TAB, sha3_module, 2)).
56+
57+
sha3_module(SHA3Module) when is_atom(SHA3Module) ->
58+
?MAYBE_START_JOSE(jose_server:sha3_module(SHA3Module)).
59+
60+
+-spec unsecured_signing() -> boolean().
61+
unsecured_signing() ->
62+
- jose_jwa:unsecured_signing().
63+
+ ?MAYBE_START_JOSE(ets:lookup_element(?TAB, unsecured_signing, 2)).
64+
65+
-unsecured_signing(Boolean) when is_boolean(Boolean) ->
66+
- jose_jwa:unsecured_signing(Boolean).
67+
+-spec unsecured_signing(UnsecuredSigning) -> ok when UnsecuredSigning :: boolean().
68+
+unsecured_signing(UnsecuredSigning) when is_boolean(UnsecuredSigning) ->
69+
+ ?MAYBE_START_JOSE(jose_server:unsecured_signing(UnsecuredSigning)).
70+
71+
xchacha20_poly1305_module() ->
72+
?MAYBE_START_JOSE(ets:lookup_element(?TAB, xchacha20_poly1305_module, 2)).
73+
diff --git a/deps/jose/src/jose_server.erl b/deps/jose/src/jose_server.erl
74+
index 94cbe37..9f3c02e 100644
75+
--- a/deps/jose/src/jose_server.erl
76+
+++ b/deps/jose/src/jose_server.erl
77+
@@ -22,7 +22,9 @@
78+
-export([curve25519_module/1]).
79+
-export([curve448_module/1]).
80+
-export([json_module/1]).
81+
+-export([pbes2_count_maximum/1]).
82+
-export([sha3_module/1]).
83+
+-export([unsecured_signing/1]).
84+
-export([xchacha20_poly1305_module/1]).
85+
86+
%% gen_server callbacks
87+
@@ -72,9 +74,17 @@ curve448_module(Curve448Module) when is_atom(Curve448Module) ->
88+
json_module(JSONModule) when is_atom(JSONModule) ->
89+
gen_server:call(?SERVER, {json_module, JSONModule}).
90+
91+
+-spec pbes2_count_maximum(PBES2CountMaximum) -> ok when PBES2CountMaximum :: non_neg_integer().
92+
+pbes2_count_maximum(PBES2CountMaximum) when is_integer(PBES2CountMaximum) andalso PBES2CountMaximum >= 0 ->
93+
+ gen_server:call(?SERVER, {pbes2_count_maximum, PBES2CountMaximum}).
94+
+
95+
sha3_module(SHA3Module) when is_atom(SHA3Module) ->
96+
gen_server:call(?SERVER, {sha3_module, SHA3Module}).
97+
98+
+-spec unsecured_signing(UnsecuredSigning) -> ok when UnsecuredSigning :: boolean().
99+
+unsecured_signing(UnsecuredSigning) when is_boolean(UnsecuredSigning) ->
100+
+ gen_server:call(?SERVER, {unsecured_signing, UnsecuredSigning}).
101+
+
102+
xchacha20_poly1305_module(XChaCha20Poly1305Module) when is_atom(XChaCha20Poly1305Module) ->
103+
gen_server:call(?SERVER, {xchacha20_poly1305_module, XChaCha20Poly1305Module}).
104+
105+
@@ -114,10 +124,20 @@ handle_call({json_module, M}, _From, State) ->
106+
JSONModule = check_json_module(M),
107+
true = ets:insert(?TAB, {json_module, JSONModule}),
108+
{reply, ok, State};
109+
+handle_call({pbes2_count_maximum, PBES2CountMaximum}, _From, State) when is_integer(PBES2CountMaximum) andalso PBES2CountMaximum >= 0 ->
110+
+ true = ets:insert(?TAB, {pbes2_count_maximum, PBES2CountMaximum}),
111+
+ {reply, ok, State};
112+
handle_call({sha3_module, M}, _From, State) ->
113+
SHA3Module = check_sha3_module(M),
114+
true = ets:insert(?TAB, {sha3_module, SHA3Module}),
115+
{reply, ok, State};
116+
+handle_call({unsecured_signing, UnsecuredSigning}, _From, State) when is_boolean(UnsecuredSigning) ->
117+
+ true = ets:insert(?TAB, {unsecured_signing, UnsecuredSigning}),
118+
+ _ = spawn(fun() ->
119+
+ _ = catch jose_jwa:unsecured_signing(UnsecuredSigning),
120+
+ exit(normal)
121+
+ end),
122+
+ {reply, ok, State};
123+
handle_call({xchacha20_poly1305_module, M}, _From, State) ->
124+
XChaCha20Poly1305Module = check_xchacha20_poly1305_module(M),
125+
Entries = lists:flatten(check_crypto(?CRYPTO_FALLBACK, [{xchacha20_poly1305_module, XChaCha20Poly1305Module}])),
126+
@@ -149,8 +169,18 @@ code_change(_OldVsn, State, _Extra) ->
127+
128+
%% @private
129+
support_check() ->
130+
+ PBES2CountMaximum =
131+
+ case application:get_env(jose, pbes2_count_maximum, 10000) of
132+
+ V1 when is_integer(V1) andalso V1 >= 0 ->
133+
+ V1
134+
+ end,
135+
+ UnsecuredSigning =
136+
+ case application:get_env(jose, unsecured_signing, false) of
137+
+ V2 when is_boolean(V2) ->
138+
+ V2
139+
+ end,
140+
Fallback = ?CRYPTO_FALLBACK,
141+
- Entries = lists:flatten(lists:foldl(fun(Check, Acc) ->
142+
+ Entries1 = lists:flatten(lists:foldl(fun(Check, Acc) ->
143+
Check(Fallback, Acc)
144+
end, [], [
145+
fun check_ec_key_mode/2,
146+
@@ -163,8 +193,13 @@ support_check() ->
147+
fun check_crypto/2,
148+
fun check_public_key/2
149+
])),
150+
+ Entries2 = [
151+
+ {pbes2_count_maximum, PBES2CountMaximum},
152+
+ {unsecured_signing, UnsecuredSigning}
153+
+ | Entries1
154+
+ ],
155+
true = ets:delete_all_objects(?TAB),
156+
- true = ets:insert(?TAB, Entries),
157+
+ true = ets:insert(?TAB, Entries2),
158+
ok.
159+
160+
%%%-------------------------------------------------------------------
161+
diff --git a/deps/jose/src/jwa/jose_jwa.erl b/deps/jose/src/jwa/jose_jwa.erl
162+
index 39fb565..394c796 100644
163+
--- a/deps/jose/src/jwa/jose_jwa.erl
164+
+++ b/deps/jose/src/jwa/jose_jwa.erl
165+
@@ -368,7 +368,7 @@ supports() ->
166+
].
167+
168+
unsecured_signing() ->
169+
- application:get_env(jose, unsecured_signing, false).
170+
+ jose:unsecured_signing().
171+
172+
unsecured_signing(Boolean) when is_boolean(Boolean) ->
173+
application:set_env(jose, unsecured_signing, Boolean),
174+
diff --git a/deps/jose/src/jwe/jose_jwe_alg_pbes2.erl b/deps/jose/src/jwe/jose_jwe_alg_pbes2.erl
175+
index 8c11f67..bc48502 100644
176+
--- a/deps/jose/src/jwe/jose_jwe_alg_pbes2.erl
177+
+++ b/deps/jose/src/jwe/jose_jwe_alg_pbes2.erl
178+
@@ -23,6 +23,7 @@
179+
-export([key_encrypt/3]).
180+
-export([next_cek/3]).
181+
%% API
182+
+-export([format_error/2]).
183+
-export([hmac_supported/0]).
184+
-export([wrap_supported/0]).
185+
186+
@@ -99,22 +100,22 @@ key_decrypt(Password, {_ENCModule, _ENC, EncryptedKey}, #jose_jwe_alg_pbes2{hmac
187+
when is_binary(Password)
188+
andalso is_binary(IV)
189+
andalso is_binary(TAG) ->
190+
- {ok, DerivedKey} = jose_jwa_pkcs5:pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
191+
+ {ok, DerivedKey} = pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
192+
jose_jwa:block_decrypt({aes_gcm, Bits}, DerivedKey, IV, {<<>>, EncryptedKey, TAG});
193+
key_decrypt(Password, {_ENCModule, _ENC, EncryptedKey}, #jose_jwe_alg_pbes2{hmac=HMAC, salt=Salt, iter=Iterations, wrap=aes_kw, bits=Bits}) when is_binary(Password) ->
194+
- {ok, DerivedKey} = jose_jwa_pkcs5:pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
195+
+ {ok, DerivedKey} = pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
196+
jose_jwa_aes_kw:unwrap(EncryptedKey, DerivedKey);
197+
key_decrypt(Password, {_ENCModule, _ENC, EncryptedKey}, #jose_jwe_alg_pbes2{hmac=HMAC, salt=Salt, iter=Iterations, wrap=c20p_kw, bits=Bits, iv=IV, tag=TAG})
198+
when is_binary(Password)
199+
andalso is_binary(IV)
200+
andalso is_binary(TAG) ->
201+
- {ok, DerivedKey} = jose_jwa_pkcs5:pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
202+
+ {ok, DerivedKey} = pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
203+
jose_jwa:block_decrypt({chacha20_poly1305, Bits}, DerivedKey, IV, {<<>>, EncryptedKey, TAG});
204+
key_decrypt(Password, {_ENCModule, _ENC, EncryptedKey}, #jose_jwe_alg_pbes2{hmac=HMAC, salt=Salt, iter=Iterations, wrap=xc20p_kw, bits=Bits, iv=IV, tag=TAG})
205+
when is_binary(Password)
206+
andalso is_binary(IV)
207+
andalso is_binary(TAG) ->
208+
- {ok, DerivedKey} = jose_jwa_pkcs5:pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
209+
+ {ok, DerivedKey} = pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
210+
jose_jwa:block_decrypt({xchacha20_poly1305, Bits}, DerivedKey, IV, {<<>>, EncryptedKey, TAG});
211+
key_decrypt(#jose_jwk{kty={KTYModule, KTY}}, EncryptedKey, JWEPBES2=#jose_jwe_alg_pbes2{}) ->
212+
key_decrypt(KTYModule:derive_key(KTY), EncryptedKey, JWEPBES2).
213+
@@ -131,7 +132,7 @@ key_encrypt(Password, DecryptedKey, JWEPBES2=#jose_jwe_alg_pbes2{hmac=HMAC, salt
214+
andalso is_binary(Salt)
215+
andalso is_integer(Iterations)
216+
andalso is_binary(IV) ->
217+
- {ok, DerivedKey} = jose_jwa_pkcs5:pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
218+
+ {ok, DerivedKey} = pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
219+
{CipherText, CipherTag} = jose_jwa:block_encrypt({aes_gcm, Bits}, DerivedKey, IV, {<<>>, DecryptedKey}),
220+
{CipherText, JWEPBES2#jose_jwe_alg_pbes2{ tag = CipherTag }};
221+
key_encrypt(Password, DecryptedKey, JWEPBES2=#jose_jwe_alg_pbes2{hmac=HMAC, salt=Salt, iter=Iterations, wrap=aes_kw, bits=Bits})
222+
@@ -139,7 +140,7 @@ key_encrypt(Password, DecryptedKey, JWEPBES2=#jose_jwe_alg_pbes2{hmac=HMAC, salt
223+
andalso is_binary(DecryptedKey)
224+
andalso is_binary(Salt)
225+
andalso is_integer(Iterations) ->
226+
- {ok, DerivedKey} = jose_jwa_pkcs5:pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
227+
+ {ok, DerivedKey} = pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
228+
{jose_jwa_aes_kw:wrap(DecryptedKey, DerivedKey), JWEPBES2};
229+
key_encrypt(Password, DecryptedKey, JWEPBES2=#jose_jwe_alg_pbes2{hmac=HMAC, salt=Salt, iter=Iterations, wrap=c20p_kw, bits=Bits, iv=IV})
230+
when is_binary(Password)
231+
@@ -147,7 +148,7 @@ key_encrypt(Password, DecryptedKey, JWEPBES2=#jose_jwe_alg_pbes2{hmac=HMAC, salt
232+
andalso is_binary(Salt)
233+
andalso is_integer(Iterations)
234+
andalso is_binary(IV) ->
235+
- {ok, DerivedKey} = jose_jwa_pkcs5:pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
236+
+ {ok, DerivedKey} = pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
237+
{CipherText, CipherTag} = jose_jwa:block_encrypt({chacha20_poly1305, Bits}, DerivedKey, IV, {<<>>, DecryptedKey}),
238+
{CipherText, JWEPBES2#jose_jwe_alg_pbes2{ tag = CipherTag }};
239+
key_encrypt(Password, DecryptedKey, JWEPBES2=#jose_jwe_alg_pbes2{hmac=HMAC, salt=Salt, iter=Iterations, wrap=xc20p_kw, bits=Bits, iv=IV})
240+
@@ -156,7 +157,7 @@ key_encrypt(Password, DecryptedKey, JWEPBES2=#jose_jwe_alg_pbes2{hmac=HMAC, salt
241+
andalso is_binary(Salt)
242+
andalso is_integer(Iterations)
243+
andalso is_binary(IV) ->
244+
- {ok, DerivedKey} = jose_jwa_pkcs5:pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
245+
+ {ok, DerivedKey} = pbkdf2({hmac, HMAC}, Password, Salt, Iterations, (Bits div 8) + (Bits rem 8)),
246+
{CipherText, CipherTag} = jose_jwa:block_encrypt({xchacha20_poly1305, Bits}, DerivedKey, IV, {<<>>, DecryptedKey}),
247+
{CipherText, JWEPBES2#jose_jwe_alg_pbes2{ tag = CipherTag }};
248+
key_encrypt(Password, DecryptedKey, JWEPBES2=#jose_jwe_alg_pbes2{wrap=aes_gcm_kw, iv=undefined}) when is_binary(Password) ->
249+
@@ -175,6 +176,12 @@ next_cek(_Key, {ENCModule, ENC}, ALG=#jose_jwe_alg_pbes2{}) ->
250+
%% API functions
251+
%%====================================================================
252+
253+
+-spec format_error(term(), term()) -> term().
254+
+format_error(_Reason, [{_M, _F, _As, Info} | _]) ->
255+
+ ErrorInfo = proplists:get_value(error_info, Info, #{}),
256+
+ ErrorDescription1 = maps:get(cause, ErrorInfo),
257+
+ ErrorDescription1.
258+
+
259+
hmac_supported() ->
260+
[sha256, sha384, sha512].
261+
262+
@@ -197,6 +204,21 @@ from_map_pbes2(F=#{ <<"tag">> := TAG }, H) ->
263+
from_map_pbes2(F, H) ->
264+
{H, F}.
265+
266+
+%% @private
267+
+pbkdf2(Mac, Password, Salt, Iterations, DerivedKeyLen) ->
268+
+ PBES2CountMaximum = jose:pbes2_count_maximum(),
269+
+ case PBES2CountMaximum < Iterations of
270+
+ false ->
271+
+ jose_jwa_pkcs5:pbkdf2(Mac, Password, Salt, Iterations, DerivedKeyLen);
272+
+ true ->
273+
+ erlang:error(badarg, [Mac, <<"REDACTED">>, Salt, Iterations, DerivedKeyLen], [
274+
+ {error_info, #{
275+
+ module => ?MODULE,
276+
+ cause => #{4 => lists:flatten(io_lib:format("maximum PBES2 iterations is set to ~w, but ~w was attempted (see jose:pbes2_count_maximum/0)", [PBES2CountMaximum, Iterations]))}
277+
+ }}
278+
+ ])
279+
+ end.
280+
+
281+
%% @private
282+
to_map_pbes2(F, H=#jose_jwe_alg_pbes2{ iter = P2C }) when is_integer(P2C) ->
283+
to_map_pbes2(F#{ <<"p2c">> => P2C }, H#jose_jwe_alg_pbes2{ iter = undefined });
284+
--
285+
2.45.2
286+

SPECS/rabbitmq-server/rabbitmq-server.spec

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Summary: rabbitmq-server
33
Name: rabbitmq-server
44
Version: 3.11.24
5-
Release: 1%{?dist}
5+
Release: 2%{?dist}
66
License: Apache-2.0 and MPL 2.0
77
Vendor: Microsoft Corporation
88
Distribution: Mariner
@@ -29,7 +29,7 @@ Source3: rabbitmq-server-hex-cache-%{version}.tar.gz
2929
# 7. Run `make generate-hex-cache -f rabbitmqHexCacheMakefile`
3030
# 8. Run `tar -czf rabbitmq-server-hex-cache-<version>.tar.gz cache.erl`
3131
# --------
32-
32+
Patch0: CVE-2023-50966.patch
3333
BuildRequires: erlang
3434
BuildRequires: elixir
3535
BuildRequires: libxslt
@@ -56,7 +56,7 @@ Requires: glibc-lang
5656
rabbitmq-server
5757

5858
%prep
59-
%autosetup
59+
%autosetup -p1
6060

6161
%build
6262
export LANG="en_US.UTF-8"
@@ -115,6 +115,9 @@ done
115115
%{_libdir}/rabbitmq/lib/rabbitmq_server-%{version}/*
116116

117117
%changelog
118+
* Thu Feb 13 2024 Kanishk Bansal <kanbansal@microsoft.com> - 3.11.24-2
119+
- Add patch for CVE-2023-50966
120+
118121
* Tue Oct 4 2024 Bhagyashri Pathak <bhapathak@microsoft.com> - 3.11.24-1
119122
- Upgrade version to 3.11.24 to fix CVE-2023-46118
120123

0 commit comments

Comments
 (0)