!55 fix CVE-2025-30211, CVE-2025-32433

From: @fundawang 
Reviewed-by: @wk333 
Signed-off-by: @wk333
This commit is contained in:
openeuler-ci-bot 2025-04-27 01:13:15 +00:00 committed by Gitee
commit 2f0d581fe4
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
10 changed files with 802 additions and 1 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
*.gz filter=lfs diff=lfs merge=lfs -text

2
.lfsconfig Normal file
View File

@ -0,0 +1,2 @@
[lfs]
url = https://artlfs.openeuler.openatom.cn/src-openEuler/erlang

45
CVE-2025-30211-1.patch Normal file
View File

@ -0,0 +1,45 @@
diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl
index 65f3c21..8cf18b1 100644
--- a/lib/ssh/src/ssh_message.erl
+++ b/lib/ssh/src/ssh_message.erl
@@ -24,6 +24,7 @@
-module(ssh_message).
-include_lib("public_key/include/public_key.hrl").
+-include_lib("kernel/include/logger.hrl").
-include("ssh.hrl").
-include("ssh_connect.hrl").
@@ -51,6 +52,7 @@
-define(Ename_list(X), ?STRING(ssh_bits:name_list(X)) ).
-define(Empint(X), (ssh_bits:mpint(X))/binary ).
-define(Ebinary(X), ?STRING(X) ).
+-define(ALG_NAME_LIMIT, 64).
ucl(B) ->
try unicode:characters_to_list(B) of
@@ -591,8 +593,22 @@ decode_kex_init(<<?BYTE(Bool)>>, Acc, 0) ->
X = 0,
list_to_tuple(lists:reverse([X, erl_boolean(Bool) | Acc]));
decode_kex_init(<<?DEC_BIN(Data,__0), Rest/binary>>, Acc, N) ->
- Names = string:tokens(?unicode_list(Data), ","),
- decode_kex_init(Rest, [Names | Acc], N -1).
+ BinParts = binary:split(Data, <<$,>>, [global]),
+ Process =
+ fun(<<>>, PAcc) ->
+ PAcc;
+ (Part, PAcc) ->
+ case byte_size(Part) > ?ALG_NAME_LIMIT of
+ true ->
+ ?LOG_DEBUG("Ignoring too long name", []),
+ PAcc;
+ false ->
+ Name = binary:bin_to_list(Part),
+ [Name | PAcc]
+ end
+ end,
+ Names = lists:foldr(Process, [], BinParts),
+ decode_kex_init(Rest, [Names | Acc], N - 1).
%%%================================================================

37
CVE-2025-30211-2.patch Normal file
View File

@ -0,0 +1,37 @@
From: Jakub Witczak <kuba@erlang.org>
Date: Fri, 21 Mar 2025 17:50:21 +0100
Subject: [PATCH] ssh: use chars_limit for bad packets error messages
origin: backport, https://github.com/erlang/otp/commit/d64d9fb0688092356a336e38a8717499113312a0
bug: https://github.com/erlang/otp/security/advisories/GHSA-vvr3-fjhh-cfwc
bug-debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1101713
---
lib/ssh/src/ssh_connection_handler.erl | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 1d9151b..859db8e 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -1379,8 +1379,8 @@ handle_event(info, {Proto, Sock, NewData}, StateName,
MaxLogItemLen = ?GET_OPT(max_log_item_len,SshParams#ssh.opts),
{Shutdown, D} =
?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR,
- io_lib:format("Bad packet: Decrypted, but can't decode~n~p:~p~n~P",
- [C,E,ST,MaxLogItemLen]),
+ io_lib:format("Bad packet: Decrypted, but can't decode~n~p:~p~n~p",
+ [C,E,ST], [{chars_limit, MaxLogItemLen}]),
StateName, D1),
{stop, Shutdown, D}
end;
@@ -1414,8 +1414,8 @@ handle_event(info, {Proto, Sock, NewData}, StateName,
MaxLogItemLen = ?GET_OPT(max_log_item_len,SshParams#ssh.opts),
{Shutdown, D} =
?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR,
- io_lib:format("Bad packet: Couldn't decrypt~n~p:~p~n~P",
- [C,E,ST,MaxLogItemLen]),
+ io_lib:format("Bad packet: Couldn't decrypt~n~p:~p~n~p",
+ [C,E,ST], [{chars_limit, MaxLogItemLen}]),
StateName, D0),
{stop, Shutdown, D}
end;

132
CVE-2025-30211-3.patch Normal file
View File

@ -0,0 +1,132 @@
From: Jakub Witczak <kuba@erlang.org>
Date: Mon, 24 Mar 2025 11:31:39 +0100
Subject: [PATCH] ssh: custom_kexinit test added
origin: backport, https://github.com/erlang/otp/commit/5ee26eb412a76ba1c6afdf4524b62939a48d1bce
bug: https://github.com/erlang/otp/security/advisories/GHSA-vvr3-fjhh-cfwc
bug-debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1101713
---
lib/ssh/test/ssh_protocol_SUITE.erl | 89 +++++++++++++++++++++++++++++++++++--
1 file changed, 86 insertions(+), 3 deletions(-)
Index: erlang-22.2.7+dfsg/lib/ssh/test/ssh_protocol_SUITE.erl
===================================================================
--- erlang-22.2.7+dfsg.orig/lib/ssh/test/ssh_protocol_SUITE.erl
+++ erlang-22.2.7+dfsg/lib/ssh/test/ssh_protocol_SUITE.erl
@@ -80,7 +80,8 @@ groups() ->
{field_size_error, [], [service_name_length_too_large,
service_name_length_too_short]},
- {kex, [], [no_common_alg_server_disconnects,
+ {kex, [], [custom_kexinit,
+ no_common_alg_server_disconnects,
no_common_alg_client_disconnects,
gex_client_init_option_groups,
gex_server_gex_limit,
@@ -119,7 +120,7 @@ init_per_suite(Config) ->
end_per_suite(Config) ->
stop_apps(Config).
-init_per_testcase(no_common_alg_server_disconnects, Config) ->
+init_per_testcase(Tc, Config) when Tc == no_common_alg_server_disconnects; Tc == custom_kexinit ->
start_std_daemon(Config, [{preferred_algorithms,[{public_key,['ssh-rsa']},
{cipher,?DEFAULT_CIPHERS}
]}]);
@@ -165,7 +166,7 @@ init_per_testcase(TC, Config) when TC ==
init_per_testcase(_TestCase, Config) ->
check_std_daemon_works(Config, ?LINE).
-end_per_testcase(no_common_alg_server_disconnects, Config) ->
+end_per_testcase(Tc, Config) when Tc == no_common_alg_server_disconnects; Tc == custom_kexinit ->
stop_std_daemon(Config);
end_per_testcase(kex_strict_negotiated, Config) ->
Config;
@@ -326,6 +327,88 @@ no_common_alg_server_disconnects(Config)
]
).
+custom_kexinit(Config) ->
+ %% 16#C0 value causes unicode:characters_to_list to return a big error value
+ Trash = lists:duplicate(260000, 16#C0),
+ FunnyAlg = "curve25519-sha256",
+ KexInit =
+ #ssh_msg_kexinit{cookie = <<"Ã/Ï!9zñKá:ñÀv¿JÜ">>,
+ kex_algorithms =
+ [FunnyAlg ++ Trash],
+ server_host_key_algorithms = ["ssh-rsa"],
+ encryption_algorithms_client_to_server =
+ ["aes256-ctr","aes192-ctr","aes128-ctr","aes128-cbc","3des-cbc"],
+ encryption_algorithms_server_to_client =
+ ["aes256-ctr","aes192-ctr","aes128-ctr","aes128-cbc","3des-cbc"],
+ mac_algorithms_client_to_server =
+ ["hmac-sha2-512-etm@openssh.com","hmac-sha2-256-etm@openssh.com",
+ "hmac-sha2-512","hmac-sha2-256","hmac-sha1-etm@openssh.com","hmac-sha1"],
+ mac_algorithms_server_to_client =
+ ["hmac-sha2-512-etm@openssh.com","hmac-sha2-256-etm@openssh.com",
+ "hmac-sha2-512","hmac-sha2-256","hmac-sha1-etm@openssh.com","hmac-sha1"],
+ compression_algorithms_client_to_server = ["none","zlib@openssh.com","zlib"],
+ compression_algorithms_server_to_client = ["none","zlib@openssh.com","zlib"],
+ languages_client_to_server = [],
+ languages_server_to_client = [],
+ first_kex_packet_follows = false,
+ reserved = 0
+ },
+ PacketFun =
+ fun(Msg, Ssh) ->
+ BinMsg = custom_encode(Msg),
+ ssh_transport:pack(BinMsg, Ssh, 0)
+ end,
+ {ok,_} =
+ ssh_trpt_test_lib:exec(
+ [{set_options, [print_ops, {print_messages,detail}]},
+ {connect,
+ server_host(Config),server_port(Config),
+ [{silently_accept_hosts, true},
+ {user_dir, user_dir(Config)},
+ {user_interaction, false},
+ {preferred_algorithms,[{public_key,['ssh-rsa']},
+ {cipher,?DEFAULT_CIPHERS}
+ ]}
+ ]},
+ receive_hello,
+ {send, hello},
+ {match, #ssh_msg_kexinit{_='_'}, receive_msg},
+ {send, {special, KexInit, PacketFun}}, % with server unsupported 'ssh-dss' !
+ {match, disconnect(), receive_msg}
+ ]
+ ).
+
+custom_encode(#ssh_msg_kexinit{
+ cookie = Cookie,
+ kex_algorithms = KeyAlgs,
+ server_host_key_algorithms = HostKeyAlgs,
+ encryption_algorithms_client_to_server = EncAlgC2S,
+ encryption_algorithms_server_to_client = EncAlgS2C,
+ mac_algorithms_client_to_server = MacAlgC2S,
+ mac_algorithms_server_to_client = MacAlgS2C,
+ compression_algorithms_client_to_server = CompAlgS2C,
+ compression_algorithms_server_to_client = CompAlgC2S,
+ languages_client_to_server = LangC2S,
+ languages_server_to_client = LangS2C,
+ first_kex_packet_follows = Bool,
+ reserved = Reserved
+ }) ->
+ KeyAlgsBin0 = <<?Ename_list(KeyAlgs)>>,
+ <<?UINT32(Len0), Data:Len0/binary>> = KeyAlgsBin0,
+ KeyAlgsBin = <<?UINT32(Len0), Data/binary>>,
+ <<?Ebyte(?SSH_MSG_KEXINIT), Cookie/binary,
+ KeyAlgsBin/binary,
+ ?Ename_list(HostKeyAlgs),
+ ?Ename_list(EncAlgC2S),
+ ?Ename_list(EncAlgS2C),
+ ?Ename_list(MacAlgC2S),
+ ?Ename_list(MacAlgS2C),
+ ?Ename_list(CompAlgS2C),
+ ?Ename_list(CompAlgC2S),
+ ?Ename_list(LangC2S),
+ ?Ename_list(LangS2C),
+ ?Eboolean(Bool), ?Euint32(Reserved)>>.
+
%%--------------------------------------------------------------------
%%% Algo negotiation fail. This should result in a ssh_msg_disconnect
%%% being sent from the client.

57
CVE-2025-30211-pre1.patch Normal file
View File

@ -0,0 +1,57 @@
From: Jakub Witczak <kuba@erlang.org>
Date: Fri, 27 Jan 2023 17:13:31 +0100
Subject: [PATCH] ssh: reduce log length
origin: backport, https://github.com/erlang/otp/commit/e93e40cf8150539338e7320b9fd9bad825b0a6d0
bug: https://github.com/erlang/otp/security/advisories/GHSA-vvr3-fjhh-cfwc
bug-debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1101713
---
lib/ssh/src/ssh_connection_handler.erl | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index ee397ac..1d9151b 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -1329,8 +1329,10 @@ handle_event(info, {Proto, Sock, Info}, {hello,_}, #data{socket = Sock,
end;
-handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
- transport_protocol = Proto}) ->
+handle_event(info, {Proto, Sock, NewData}, StateName,
+ D0 = #data{socket = Sock,
+ transport_protocol = Proto,
+ ssh_params = SshParams}) ->
try ssh_transport:handle_packet_part(
D0#data.decrypted_data_buffer,
<<(D0#data.encrypted_data_buffer)/binary, NewData/binary>>,
@@ -1374,10 +1376,11 @@ handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
]}
catch
C:E:ST ->
- {Shutdown, D} =
+ MaxLogItemLen = ?GET_OPT(max_log_item_len,SshParams#ssh.opts),
+ {Shutdown, D} =
?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR,
- io_lib:format("Bad packet: Decrypted, but can't decode~n~p:~p~n~p",
- [C,E,ST]),
+ io_lib:format("Bad packet: Decrypted, but can't decode~n~p:~p~n~P",
+ [C,E,ST,MaxLogItemLen]),
StateName, D1),
{stop, Shutdown, D}
end;
@@ -1408,9 +1411,11 @@ handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
{stop, Shutdown, D}
catch
C:E:ST ->
- {Shutdown, D} =
+ MaxLogItemLen = ?GET_OPT(max_log_item_len,SshParams#ssh.opts),
+ {Shutdown, D} =
?send_disconnect(?SSH_DISCONNECT_PROTOCOL_ERROR,
- io_lib:format("Bad packet: Couldn't decrypt~n~p:~p~n~p",[C,E,ST]),
+ io_lib:format("Bad packet: Couldn't decrypt~n~p:~p~n~P",
+ [C,E,ST,MaxLogItemLen]),
StateName, D0),
{stop, Shutdown, D}
end;

302
CVE-2025-32433-pre1.patch Normal file
View File

@ -0,0 +1,302 @@
Origin: https://github.com/erlang/otp/commit/c9e4b22bc4b1faffef07c94ef8e4751b1a36870d
Reviewed-by: Sylvain Beucler <beuc@debian.org>
Last-Update: 2025-04-22
From c9e4b22bc4b1faffef07c94ef8e4751b1a36870d Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Thu, 14 Jan 2021 17:25:39 +0100
Subject: [PATCH] ssh: Add 4th argument (#ssh) to ssh_connection:handl_msg
to be able to use the hello-string whens settting pty options.
---
lib/ssh/src/ssh_connection.erl | 76 +++++++++++++-------------
lib/ssh/src/ssh_connection_handler.erl | 4 +-
2 files changed, 40 insertions(+), 40 deletions(-)
Index: erlang-22.2.7+dfsg/lib/ssh/src/ssh_connection.erl
===================================================================
--- erlang-22.2.7+dfsg.orig/lib/ssh/src/ssh_connection.erl
+++ erlang-22.2.7+dfsg/lib/ssh/src/ssh_connection.erl
@@ -42,7 +42,7 @@
%% Internal SSH application API
-export([channel_data/5,
- handle_msg/3,
+ handle_msg/4,
handle_stop/1,
channel_adjust_window_msg/2,
@@ -450,7 +450,7 @@ handle_msg(#ssh_msg_channel_open_confirm
sender_channel = RemoteId,
initial_window_size = WindowSz,
maximum_packet_size = PacketSz},
- #connection{channel_cache = Cache} = Connection0, _) ->
+ #connection{channel_cache = Cache} = Connection0, _, _SSH) ->
#channel{remote_id = undefined} = Channel =
ssh_client_channel:cache_lookup(Cache, ChannelId),
@@ -468,22 +468,22 @@ handle_msg(#ssh_msg_channel_open_failure
reason = Reason,
description = Descr,
lang = Lang},
- #connection{channel_cache = Cache} = Connection0, _) ->
+ #connection{channel_cache = Cache} = Connection0, _, _SSH) ->
Channel = ssh_client_channel:cache_lookup(Cache, ChannelId),
ssh_client_channel:cache_delete(Cache, ChannelId),
reply_msg(Channel, Connection0, {open_error, Reason, Descr, Lang});
-handle_msg(#ssh_msg_channel_success{recipient_channel = ChannelId}, Connection, _) ->
+handle_msg(#ssh_msg_channel_success{recipient_channel = ChannelId}, Connection, _, _SSH) ->
reply_msg(ChannelId, Connection, success);
-handle_msg(#ssh_msg_channel_failure{recipient_channel = ChannelId}, Connection, _) ->
+handle_msg(#ssh_msg_channel_failure{recipient_channel = ChannelId}, Connection, _, _SSH) ->
reply_msg(ChannelId, Connection, failure);
-handle_msg(#ssh_msg_channel_eof{recipient_channel = ChannelId}, Connection, _) ->
+handle_msg(#ssh_msg_channel_eof{recipient_channel = ChannelId}, Connection, _, _SSH) ->
reply_msg(ChannelId, Connection, {eof, ChannelId});
handle_msg(#ssh_msg_channel_close{recipient_channel = ChannelId},
- #connection{channel_cache = Cache} = Connection0, _) ->
+ #connection{channel_cache = Cache} = Connection0, _, _SSH) ->
case ssh_client_channel:cache_lookup(Cache, ChannelId) of
#channel{sent_close = Closed, remote_id = RemoteId,
@@ -516,18 +516,18 @@ handle_msg(#ssh_msg_channel_close{recipi
handle_msg(#ssh_msg_channel_data{recipient_channel = ChannelId,
data = Data},
- Connection, _) ->
+ Connection, _, _SSH) ->
channel_data_reply_msg(ChannelId, Connection, 0, Data);
handle_msg(#ssh_msg_channel_extended_data{recipient_channel = ChannelId,
data_type_code = DataType,
data = Data},
- Connection, _) ->
+ Connection, _, _SSH) ->
channel_data_reply_msg(ChannelId, Connection, DataType, Data);
handle_msg(#ssh_msg_channel_window_adjust{recipient_channel = ChannelId,
bytes_to_add = Add},
- #connection{channel_cache = Cache} = Connection, _) ->
+ #connection{channel_cache = Cache} = Connection, _, _SSH) ->
#channel{send_window_size = Size, remote_id = RemoteId} =
Channel0 = ssh_client_channel:cache_lookup(Cache, ChannelId),
@@ -546,7 +546,7 @@ handle_msg(#ssh_msg_channel_open{channel
initial_window_size = WindowSz,
maximum_packet_size = PacketSz},
#connection{options = SSHopts} = Connection0,
- server) ->
+ server, _SSH) ->
MinAcceptedPackSz =
?GET_OPT(minimal_remote_max_packet_size, SSHopts),
@@ -574,7 +574,7 @@ handle_msg(#ssh_msg_channel_open{channel
handle_msg(#ssh_msg_channel_open{channel_type = "session",
sender_channel = RemoteId},
Connection,
- client) ->
+ client, _SSH) ->
%% Client implementations SHOULD reject any session channel open
%% requests to make it more difficult for a corrupt server to attack the
%% client. See See RFC 4254 6.1.
@@ -583,7 +583,7 @@ handle_msg(#ssh_msg_channel_open{channel
"Connection refused", "en"),
{[{connection_reply, FailMsg}], Connection};
-handle_msg(#ssh_msg_channel_open{sender_channel = RemoteId}, Connection, _) ->
+handle_msg(#ssh_msg_channel_open{sender_channel = RemoteId}, Connection, _, _SSH) ->
FailMsg = channel_open_failure_msg(RemoteId,
?SSH_OPEN_ADMINISTRATIVELY_PROHIBITED,
"Not allowed", "en"),
@@ -592,7 +592,7 @@ handle_msg(#ssh_msg_channel_open{sender_
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "exit-status",
data = Data},
- Connection, _) ->
+ Connection, _, _SSH) ->
<<?UINT32(Status)>> = Data,
reply_msg(ChannelId, Connection, {exit_status, ChannelId, Status});
@@ -600,7 +600,7 @@ handle_msg(#ssh_msg_channel_request{reci
request_type = "exit-signal",
want_reply = false,
data = Data},
- #connection{channel_cache = Cache} = Connection0, _) ->
+ #connection{channel_cache = Cache} = Connection0, _, _SSH) ->
<<?DEC_BIN(SigName, _SigLen),
?BOOLEAN(_Core),
?DEC_BIN(Err, _ErrLen),
@@ -619,7 +619,7 @@ handle_msg(#ssh_msg_channel_request{reci
request_type = "xon-xoff",
want_reply = false,
data = Data},
- Connection, _) ->
+ Connection, _, _SSH) ->
<<?BOOLEAN(CDo)>> = Data,
reply_msg(ChannelId, Connection, {xon_xoff, ChannelId, CDo=/= 0});
@@ -627,7 +627,7 @@ handle_msg(#ssh_msg_channel_request{reci
request_type = "window-change",
want_reply = false,
data = Data},
- Connection0, _) ->
+ Connection0, _, _SSH) ->
<<?UINT32(Width),?UINT32(Height),
?UINT32(PixWidth), ?UINT32(PixHeight)>> = Data,
reply_msg(ChannelId, Connection0, {window_change, ChannelId,
@@ -637,7 +637,7 @@ handle_msg(#ssh_msg_channel_request{reci
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "signal",
data = Data},
- Connection0, _) ->
+ Connection0, _, _SSH) ->
<<?DEC_BIN(SigName, _SigLen)>> = Data,
reply_msg(ChannelId, Connection0, {signal, ChannelId,
binary_to_list(SigName)});
@@ -646,7 +646,7 @@ handle_msg(#ssh_msg_channel_request{reci
request_type = "subsystem",
want_reply = WantReply,
data = Data},
- #connection{channel_cache = Cache} = Connection, server) ->
+ #connection{channel_cache = Cache} = Connection, server, _SSH) ->
<<?DEC_BIN(SsName,_SsLen)>> = Data,
#channel{remote_id=RemoteId} = Channel =
ssh_client_channel:cache_lookup(Cache, ChannelId),
@@ -668,7 +668,7 @@ handle_msg(#ssh_msg_channel_request{reci
{[{connection_reply,Reply}], Connection};
handle_msg(#ssh_msg_channel_request{request_type = "subsystem"},
- Connection, client) ->
+ Connection, client, _SSH) ->
%% The client SHOULD ignore subsystem requests. See RFC 4254 6.5.
{[], Connection};
@@ -676,7 +676,7 @@ handle_msg(#ssh_msg_channel_request{reci
request_type = "pty-req",
want_reply = WantReply,
data = Data},
- Connection, server) ->
+ Connection, server, _SSH) ->
<<?DEC_BIN(BTermName,_TermLen),
?UINT32(Width),?UINT32(Height),
?UINT32(PixWidth), ?UINT32(PixHeight),
@@ -688,19 +688,19 @@ handle_msg(#ssh_msg_channel_request{reci
{pty, ChannelId, WantReply, PtyRequest});
handle_msg(#ssh_msg_channel_request{request_type = "pty-req"},
- Connection, client) ->
+ Connection, client, _SSH) ->
%% The client SHOULD ignore pty requests. See RFC 4254 6.2.
{[], Connection};
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = "shell",
want_reply = WantReply},
- Connection, server) ->
+ Connection, server, _SSH) ->
handle_cli_msg(Connection, ChannelId,
{shell, ChannelId, WantReply});
handle_msg(#ssh_msg_channel_request{request_type = "shell"},
- Connection, client) ->
+ Connection, client, _SSH) ->
%% The client SHOULD ignore shell requests. See RFC 4254 6.5.
{[], Connection};
@@ -708,13 +708,13 @@ handle_msg(#ssh_msg_channel_request{reci
request_type = "exec",
want_reply = WantReply,
data = Data},
- Connection, server) ->
+ Connection, server, _SSH) ->
<<?DEC_BIN(Command, _Len)>> = Data,
handle_cli_msg(Connection, ChannelId,
{exec, ChannelId, WantReply, binary_to_list(Command)});
handle_msg(#ssh_msg_channel_request{request_type = "exec"},
- Connection, client) ->
+ Connection, client, _SSH) ->
%% The client SHOULD ignore exec requests. See RFC 4254 6.5.
{[], Connection};
@@ -722,20 +722,20 @@ handle_msg(#ssh_msg_channel_request{reci
request_type = "env",
want_reply = WantReply,
data = Data},
- Connection, server) ->
+ Connection, server, _SSH) ->
<<?DEC_BIN(Var,_VarLen), ?DEC_BIN(Value,_ValLen)>> = Data,
handle_cli_msg(Connection, ChannelId,
{env, ChannelId, WantReply, Var, Value});
handle_msg(#ssh_msg_channel_request{request_type = "env"},
- Connection, client) ->
+ Connection, client, _SSH) ->
%% The client SHOULD ignore env requests.
{[], Connection};
handle_msg(#ssh_msg_channel_request{recipient_channel = ChannelId,
request_type = _Other,
want_reply = WantReply},
- #connection{channel_cache = Cache} = Connection, _) ->
+ #connection{channel_cache = Cache} = Connection, _, _SSH) ->
if WantReply == true ->
case ssh_client_channel:cache_lookup(Cache, ChannelId) of
#channel{remote_id = RemoteId} ->
@@ -750,7 +750,7 @@ handle_msg(#ssh_msg_channel_request{reci
handle_msg(#ssh_msg_global_request{name = _Type,
want_reply = WantReply,
- data = _Data}, Connection, _) ->
+ data = _Data}, Connection, _, _SSH) ->
if WantReply == true ->
FailMsg = request_failure_msg(),
{[{connection_reply, FailMsg}], Connection};
@@ -759,18 +759,18 @@ handle_msg(#ssh_msg_global_request{name
end;
handle_msg(#ssh_msg_request_failure{},
- #connection{requests = [{_, From} | Rest]} = Connection, _) ->
+ #connection{requests = [{_, From} | Rest]} = Connection, _, _SSH) ->
{[{channel_request_reply, From, {failure, <<>>}}],
Connection#connection{requests = Rest}};
handle_msg(#ssh_msg_request_success{data = Data},
- #connection{requests = [{_, From} | Rest]} = Connection, _) ->
+ #connection{requests = [{_, From} | Rest]} = Connection, _, _SSH) ->
{[{channel_request_reply, From, {success, Data}}],
Connection#connection{requests = Rest}};
handle_msg(#ssh_msg_disconnect{code = Code,
description = Description},
- Connection, _) ->
+ Connection, _, _SSH) ->
{disconnect, {Code, Description}, handle_stop(Connection)}.
Index: erlang-22.2.7+dfsg/lib/ssh/src/ssh_connection_handler.erl
===================================================================
--- erlang-22.2.7+dfsg.orig/lib/ssh/src/ssh_connection_handler.erl
+++ erlang-22.2.7+dfsg/lib/ssh/src/ssh_connection_handler.erl
@@ -1006,7 +1006,7 @@ handle_event(_, {#ssh_msg_kexinit{},_},
handle_event(_, #ssh_msg_disconnect{description=Desc} = Msg, StateName, D0) ->
{disconnect, _, RepliesCon} =
- ssh_connection:handle_msg(Msg, D0#data.connection_state, role(StateName)),
+ ssh_connection:handle_msg(Msg, D0#data.connection_state, role(StateName), D0#data.ssh_params),
{Actions,D} = send_replies(RepliesCon, D0),
disconnect_fun("Received disconnect: "++Desc, D),
{stop_and_reply, {shutdown,Desc}, Actions, D};
@@ -1036,7 +1036,7 @@ handle_event(internal, {conn_msg,Msg}, S
event_queue = Qev0} = D0) ->
Role = role(StateName),
Rengotation = renegotiation(StateName),
- try ssh_connection:handle_msg(Msg, Connection0, Role) of
+ try ssh_connection:handle_msg(Msg, Connection0, Role, D0#data.ssh_params) of
{disconnect, Reason0, RepliesConn} ->
{Repls, D} = send_replies(RepliesConn, D0),
case {Reason0,Role} of

214
CVE-2025-32433.patch Normal file
View File

@ -0,0 +1,214 @@
Origin: https://github.com/erlang/otp/commit/0fcd9c56524b28615e8ece65fc0c3f66ef6e4c12
Reviewed-by: Sylvain Beucler <beuc@debian.org>
Last-Update: 2025-04-22
From 0fcd9c56524b28615e8ece65fc0c3f66ef6e4c12 Mon Sep 17 00:00:00 2001
From: Jakub Witczak <kuba@erlang.org>
Date: Mon, 14 Apr 2025 16:33:21 +0200
Subject: [PATCH] ssh: early RCE fix
- disconnect when connection protocol message arrives
- when user is not authenticated for connection
- see RFC4252 sec.6
---
lib/ssh/src/ssh_connection.erl | 28 ++++++++--
lib/ssh/test/ssh_protocol_SUITE.erl | 86 +++++++++++++++--------------
2 files changed, 67 insertions(+), 47 deletions(-)
Index: erlang-22.2.7+dfsg/lib/ssh/src/ssh_connection.erl
===================================================================
--- erlang-22.2.7+dfsg.orig/lib/ssh/src/ssh_connection.erl
+++ erlang-22.2.7+dfsg/lib/ssh/src/ssh_connection.erl
@@ -26,6 +26,8 @@
-module(ssh_connection).
+-include_lib("kernel/include/logger.hrl").
+
-include("ssh.hrl").
-include("ssh_connect.hrl").
-include("ssh_transport.hrl").
@@ -446,6 +448,25 @@ channel_data(ChannelId, DataType, Data0,
%%% Replies {Reply, UpdatedConnection}
%%%
+handle_msg(#ssh_msg_disconnect{code = Code, description = Description}, Connection, _, _SSH) ->
+ {disconnect, {Code, Description}, handle_stop(Connection)};
+
+handle_msg(Msg, Connection, server, Ssh = #ssh{authenticated = false}) ->
+ %% See RFC4252 6.
+ %% Message numbers of 80 and higher are reserved for protocols running
+ %% after this authentication protocol, so receiving one of them before
+ %% authentication is complete is an error, to which the server MUST
+ %% respond by disconnecting, preferably with a proper disconnect message
+ %% sent to ease troubleshooting.
+ MsgFun = fun(M) ->
+ MaxLogItemLen = ?GET_OPT(max_log_item_len, Ssh#ssh.opts),
+ io_lib:format("Connection terminated. Unexpected message for unauthenticated user."
+ " Message: ~w", [M],
+ [{chars_limit, MaxLogItemLen}])
+ end,
+ ?LOG_DEBUG(MsgFun, [Msg]),
+ {disconnect, {?SSH_DISCONNECT_PROTOCOL_ERROR, "Connection refused"}, handle_stop(Connection)};
+
handle_msg(#ssh_msg_channel_open_confirmation{recipient_channel = ChannelId,
sender_channel = RemoteId,
initial_window_size = WindowSz,
@@ -766,12 +787,7 @@ handle_msg(#ssh_msg_request_failure{},
handle_msg(#ssh_msg_request_success{data = Data},
#connection{requests = [{_, From} | Rest]} = Connection, _, _SSH) ->
{[{channel_request_reply, From, {success, Data}}],
- Connection#connection{requests = Rest}};
-
-handle_msg(#ssh_msg_disconnect{code = Code,
- description = Description},
- Connection, _, _SSH) ->
- {disconnect, {Code, Description}, handle_stop(Connection)}.
+ Connection#connection{requests = Rest}}.
%%%----------------------------------------------------------------
Index: erlang-22.2.7+dfsg/lib/ssh/test/ssh_protocol_SUITE.erl
===================================================================
--- erlang-22.2.7+dfsg.orig/lib/ssh/test/ssh_protocol_SUITE.erl
+++ erlang-22.2.7+dfsg/lib/ssh/test/ssh_protocol_SUITE.erl
@@ -59,6 +59,7 @@ suite() ->
all() ->
[{group,tool_tests},
client_info_line,
+ early_rce,
{group,kex},
{group,service_requests},
{group,authentication},
@@ -76,10 +77,8 @@ groups() ->
]},
{packet_size_error, [], [packet_length_too_large,
packet_length_too_short]},
-
{field_size_error, [], [service_name_length_too_large,
service_name_length_too_short]},
-
{kex, [], [custom_kexinit,
no_common_alg_server_disconnects,
no_common_alg_client_disconnects,
@@ -120,7 +119,8 @@ init_per_suite(Config) ->
end_per_suite(Config) ->
stop_apps(Config).
-init_per_testcase(Tc, Config) when Tc == no_common_alg_server_disconnects; Tc == custom_kexinit ->
+init_per_testcase(Tc, Config) when Tc == no_common_alg_server_disconnects;
+ Tc == custom_kexinit ->
start_std_daemon(Config, [{preferred_algorithms,[{public_key,['ssh-rsa']},
{cipher,?DEFAULT_CIPHERS}
]}]);
@@ -166,7 +166,8 @@ init_per_testcase(TC, Config) when TC ==
init_per_testcase(_TestCase, Config) ->
check_std_daemon_works(Config, ?LINE).
-end_per_testcase(Tc, Config) when Tc == no_common_alg_server_disconnects; Tc == custom_kexinit ->
+end_per_testcase(Tc, Config) when Tc == no_common_alg_server_disconnects;
+ Tc == custom_kexinit ->
stop_std_daemon(Config);
end_per_testcase(kex_strict_negotiated, Config) ->
Config;
@@ -327,6 +328,44 @@ no_common_alg_server_disconnects(Config)
]
).
+early_rce(Config) ->
+ {ok,InitialState} =
+ ssh_trpt_test_lib:exec([{set_options, [print_ops, print_seqnums, print_messages]}]),
+ TypeOpen = "session",
+ ChannelId = 0,
+ WinSz = 425984,
+ PktSz = 65536,
+ DataOpen = <<>>,
+ SshMsgChannelOpen = ssh_connection:channel_open_msg(TypeOpen, ChannelId, WinSz, PktSz, DataOpen),
+
+ Id = 0,
+ TypeReq = "exec",
+ WantReply = true,
+ DataReq = <<?STRING(<<"lists:seq(1,10).">>)>>,
+ SshMsgChannelRequest =
+ ssh_connection:channel_request_msg(Id, TypeReq, WantReply, DataReq),
+ {ok,AfterKexState} =
+ ssh_trpt_test_lib:exec(
+ [{connect,
+ server_host(Config),server_port(Config),
+ [{preferred_algorithms,[{kex,[?DEFAULT_KEX]},
+ {cipher,?DEFAULT_CIPHERS}
+ ]},
+ {silently_accept_hosts, true},
+ {recv_ext_info, false},
+ {user_dir, user_dir(Config)},
+ {user_interaction, false}
+ | proplists:get_value(extra_options,Config,[])]},
+ receive_hello,
+ {send, hello},
+ {send, ssh_msg_kexinit},
+ {match, #ssh_msg_kexinit{_='_'}, receive_msg},
+ {send, SshMsgChannelOpen},
+ {send, SshMsgChannelRequest},
+ {match, disconnect(), receive_msg}
+ ], InitialState),
+ ok.
+
custom_kexinit(Config) ->
%% 16#C0 value causes unicode:characters_to_list to return a big error value
Trash = lists:duplicate(260000, 16#C0),
@@ -353,11 +392,6 @@ custom_kexinit(Config) ->
first_kex_packet_follows = false,
reserved = 0
},
- PacketFun =
- fun(Msg, Ssh) ->
- BinMsg = custom_encode(Msg),
- ssh_transport:pack(BinMsg, Ssh, 0)
- end,
{ok,_} =
ssh_trpt_test_lib:exec(
[{set_options, [print_ops, {print_messages,detail}]},
@@ -373,42 +407,11 @@ custom_kexinit(Config) ->
receive_hello,
{send, hello},
{match, #ssh_msg_kexinit{_='_'}, receive_msg},
- {send, {special, KexInit, PacketFun}}, % with server unsupported 'ssh-dss' !
+ {send, KexInit}, % with server unsupported 'ssh-dss' !
{match, disconnect(), receive_msg}
]
).
-custom_encode(#ssh_msg_kexinit{
- cookie = Cookie,
- kex_algorithms = KeyAlgs,
- server_host_key_algorithms = HostKeyAlgs,
- encryption_algorithms_client_to_server = EncAlgC2S,
- encryption_algorithms_server_to_client = EncAlgS2C,
- mac_algorithms_client_to_server = MacAlgC2S,
- mac_algorithms_server_to_client = MacAlgS2C,
- compression_algorithms_client_to_server = CompAlgS2C,
- compression_algorithms_server_to_client = CompAlgC2S,
- languages_client_to_server = LangC2S,
- languages_server_to_client = LangS2C,
- first_kex_packet_follows = Bool,
- reserved = Reserved
- }) ->
- KeyAlgsBin0 = <<?Ename_list(KeyAlgs)>>,
- <<?UINT32(Len0), Data:Len0/binary>> = KeyAlgsBin0,
- KeyAlgsBin = <<?UINT32(Len0), Data/binary>>,
- <<?Ebyte(?SSH_MSG_KEXINIT), Cookie/binary,
- KeyAlgsBin/binary,
- ?Ename_list(HostKeyAlgs),
- ?Ename_list(EncAlgC2S),
- ?Ename_list(EncAlgS2C),
- ?Ename_list(MacAlgC2S),
- ?Ename_list(MacAlgS2C),
- ?Ename_list(CompAlgS2C),
- ?Ename_list(CompAlgC2S),
- ?Ename_list(LangC2S),
- ?Ename_list(LangS2C),
- ?Eboolean(Bool), ?Euint32(Reserved)>>.
-
%%--------------------------------------------------------------------
%%% Algo negotiation fail. This should result in a ssh_msg_disconnect
%%% being sent from the client.

View File

@ -11,7 +11,7 @@
%global __with_wxwidgets 1
Name: erlang
Version: 21.3.3
Release: 5
Release: 6
Summary: General-purpose programming language and runtime environment
License: Apache-2.0
URL: https://www.erlang.org
@ -33,6 +33,14 @@ Patch9: otp-0009-Load-man-pages-from-system-wide-directory.patch
Patch10: otp-0010-Improve-nodes-querying.patch
Patch11: CVE-2023-48795-erlang21.patch
Patch12: CVE-2025-26618.patch
# Patch13...18 comes from debian
# https://salsa.debian.org/erlang-team/packages/erlang/-/tree/buster/debian/patches
Patch13: CVE-2025-30211-pre1.patch
Patch14: CVE-2025-30211-1.patch
Patch15: CVE-2025-30211-2.patch
Patch16: CVE-2025-30211-3.patch
Patch17: CVE-2025-32433-pre1.patch
Patch18: CVE-2025-32433.patch
BuildRequires: gcc gcc-c++ flex
%if %{with doc}
%if 0%{?need_bootstrap} < 1
@ -1726,6 +1734,9 @@ useradd -r -g epmd -d /dev/null -s /sbin/nologin \
%endif
%changelog
* Sat Apr 26 2025 Funda Wang <fundawang@yeah.net> - 21.3.3-6
- fix CVE-2025-30211, CVE-2025-32433
* Mon Feb 24 2025 yaoxin <1024769339@qq.com> - 21.3.3-5
- Fix CVE-2025-26618

Binary file not shown.