Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
f4a99783cf
!265 [sync] PR-259: 修复KEX交换处理中内存泄露
From: @openeuler-sync-bot 
Reviewed-by: @robertxw 
Signed-off-by: @robertxw
2024-02-17 08:53:02 +00:00
Corwin-Song
7e6a7e53cd fix memory leak in kex2 exchange function
Signed-off-by: Corwin-Song <songjuntao@kylinos.cn>
(cherry picked from commit aaf74beffae0f0b281357bdf9e895942ee0ed11d)
2024-02-17 09:25:43 +08:00
openeuler-ci-bot
f71bca9db0
!239 [sync] PR-237: fix CVE-2023-48795
From: @openeuler-sync-bot 
Reviewed-by: @gebidelidaye 
Signed-off-by: @gebidelidaye
2024-01-10 01:09:45 +00:00
renmingshuai
b230dd71da fix CVE-2023-48795
(cherry picked from commit 3adb7d0af669a9ce6c1734a112644b5e336b9290)
2024-01-09 22:33:00 +08:00
openeuler-ci-bot
71abbfffbe
!235 [sync] PR-233: sync from sp1
From: @openeuler-sync-bot 
Reviewed-by: @gebidelidaye 
Signed-off-by: @gebidelidaye
2023-12-28 12:24:50 +00:00
renmingshuai
8d5a10f9fa sync from sp1
(cherry picked from commit c9ca9cd82558ea419c793bc6d372bbc1ac52519f)
2023-12-28 19:21:30 +08:00
openeuler-ci-bot
dc71184201
!229 [sync] PR-228: fix CVE-2023-51385
From: @openeuler-sync-bot 
Reviewed-by: @robertxw 
Signed-off-by: @robertxw
2023-12-25 12:19:35 +00:00
renmingshuai
17255e7fac fix CVE-2023-51385
(cherry picked from commit 6bac1f41016dd6d7257ed0e0135299f87155a4ec)
2023-12-25 19:29:23 +08:00
openeuler-ci-bot
e287adfc75
!216 CVE-2023-38408
From: @dedv_dwe 
Reviewed-by: @gebidelidaye 
Signed-off-by: @gebidelidaye
2023-08-02 09:58:06 +00:00
ut004527
a6bfca2b2a CVE:CVE-2023-38408 2023-08-02 10:07:54 +08:00
9 changed files with 2375 additions and 40 deletions

View File

@ -0,0 +1,465 @@
From 802a7af111c9ddb438ca4fd8c5cc35534e199fda Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Mon, 18 Dec 2023 14:45:17 +0000
Subject: upstream: implement "strict key exchange" in ssh and sshd
This adds a protocol extension to improve the integrity of the SSH
transport protocol, particular in and around the initial key exchange
(KEX) phase.
Full details of the extension are in the PROTOCOL file.
with markus@
OpenBSD-Commit-ID: 2a66ac962f0a630d7945fee54004ed9e9c439f14
Origin: backport, https://anongit.mindrot.org/openssh.git/commit/?id=1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5
Last-Update: 2023-12-21
Patch-Name: CVE-2023-48795.patch
Reference:https://sources.debian.org/src/openssh/1%3A8.4p1-5%2Bdeb11u3/debian/patches/CVE-2023-48795.patch/
Conflict:NA
---
PROTOCOL | 26 +++++++++++++++++
kex.c | 68 ++++++++++++++++++++++++++++++++-----------
kex.h | 1 +
packet.c | 80 ++++++++++++++++++++++++++++++++++++++-------------
sshconnect2.c | 14 +++------
sshd.c | 8 ++++--
6 files changed, 149 insertions(+), 48 deletions(-)
diff --git a/PROTOCOL b/PROTOCOL
index f75c1c0..89bddfe 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -102,6 +102,32 @@ OpenSSH supports the use of ECDH in Curve25519 for key exchange as
described at:
http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.org.txt?h=curve25519
+1.9 transport: strict key exchange extension
+
+OpenSSH supports a number of transport-layer hardening measures under
+a "strict KEX" feature. This feature is signalled similarly to the
+RFC8308 ext-info feature: by including a additional algorithm in the
+initiial SSH2_MSG_KEXINIT kex_algorithms field. The client may append
+"kex-strict-c-v00@openssh.com" to its kex_algorithms and the server
+may append "kex-strict-s-v00@openssh.com". These pseudo-algorithms
+are only valid in the initial SSH2_MSG_KEXINIT and MUST be ignored
+if they are present in subsequent SSH2_MSG_KEXINIT packets.
+
+When an endpoint that supports this extension observes this algorithm
+name in a peer's KEXINIT packet, it MUST make the following changes to
+the the protocol:
+
+a) During initial KEX, terminate the connection if any unexpected or
+ out-of-sequence packet is received. This includes terminating the
+ connection if the first packet received is not SSH2_MSG_KEXINIT.
+ Unexpected packets for the purpose of strict KEX include messages
+ that are otherwise valid at any time during the connection such as
+ SSH2_MSG_DEBUG and SSH2_MSG_IGNORE.
+b) After sending or receiving a SSH2_MSG_NEWKEYS message, reset the
+ packet sequence number to zero. This behaviour persists for the
+ duration of the connection (i.e. not just the first
+ SSH2_MSG_NEWKEYS).
+
2. Connection protocol changes
2.1. connection: Channel write close extension "eow@openssh.com"
diff --git a/kex.c b/kex.c
index 7c5f635..77eb7c0 100644
--- a/kex.c
+++ b/kex.c
@@ -72,7 +72,7 @@
#endif
/* prototype */
-static int kex_choose_conf(struct ssh *);
+static int kex_choose_conf(struct ssh *, uint32_t seq);
static int kex_input_newkeys(int, u_int32_t, struct ssh *);
static const char *proposal_names[PROPOSAL_MAX] = {
@@ -215,6 +215,18 @@ kex_names_valid(const char *names)
return 1;
}
+/* returns non-zero if proposal contains any algorithm from algs */
+static int
+has_any_alg(const char *proposal, const char *algs)
+{
+ char *cp;
+
+ if ((cp = match_list(proposal, algs, NULL)) == NULL)
+ return 0;
+ free(cp);
+ return 1;
+}
+
/*
* Concatenate algorithm names, avoiding duplicates in the process.
* Caller must free returned string.
@@ -222,7 +234,7 @@ kex_names_valid(const char *names)
char *
kex_names_cat(const char *a, const char *b)
{
- char *ret = NULL, *tmp = NULL, *cp, *p, *m;
+ char *ret = NULL, *tmp = NULL, *cp, *p;
size_t len;
if (a == NULL || *a == '\0')
@@ -239,10 +251,8 @@ kex_names_cat(const char *a, const char *b)
}
strlcpy(ret, a, len);
for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
- if ((m = match_list(ret, p, NULL)) != NULL) {
- free(m);
+ if (has_any_alg(ret, p))
continue; /* Algorithm already present */
- }
if (strlcat(ret, ",", len) >= len ||
strlcat(ret, p, len) >= len) {
free(tmp);
@@ -474,7 +484,12 @@ kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
{
int r;
- error("kex protocol error: type %d seq %u", type, seq);
+ /* If in strict mode, any unexpected message is an error */
+ if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) {
+ ssh_packet_disconnect(ssh, "strict KEX violation: "
+ "unexpected packet type %u (seqnr %u)", type, seq);
+ }
+ error("%s: type %u seq %u", __func__, type, seq);
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
@@ -546,6 +561,11 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
return r;
+ if (ninfo >= 1024) {
+ error("SSH2_MSG_EXT_INFO with too many entries, expected "
+ "<=1024, received %u", ninfo);
+ return dispatch_protocol_error(type, seq, ssh);
+ }
for (i = 0; i < ninfo; i++) {
if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
return r;
@@ -646,7 +666,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
error("%s: no hex", __func__);
return SSH_ERR_INTERNAL_ERROR;
}
- ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
ptr = sshpkt_ptr(ssh, &dlen);
if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
return r;
@@ -682,7 +702,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
if (!(kex->flags & KEX_INIT_SENT))
if ((r = kex_send_kexinit(ssh)) != 0)
return r;
- if ((r = kex_choose_conf(ssh)) != 0)
+ if ((r = kex_choose_conf(ssh, seq)) != 0)
return r;
if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
@@ -960,7 +980,13 @@ proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
}
static int
-kex_choose_conf(struct ssh *ssh)
+kexalgs_contains(char **peer, const char *ext)
+{
+ return has_any_alg(peer[PROPOSAL_KEX_ALGS], ext);
+}
+
+static int
+kex_choose_conf(struct ssh *ssh, uint32_t seq)
{
struct kex *kex = ssh->kex;
struct newkeys *newkeys;
@@ -985,13 +1011,23 @@ kex_choose_conf(struct ssh *ssh)
sprop=peer;
}
- /* Check whether client supports ext_info_c */
- if (kex->server && (kex->flags & KEX_INITIAL)) {
- char *ext;
-
- ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL);
- kex->ext_info_c = (ext != NULL);
- free(ext);
+ /* Check whether peer supports ext_info/kex_strict */
+ if ((kex->flags & KEX_INITIAL) != 0) {
+ if (kex->server) {
+ kex->ext_info_c = kexalgs_contains(peer, "ext-info-c");
+ kex->kex_strict = kexalgs_contains(peer,
+ "kex-strict-c-v00@openssh.com");
+ } else {
+ kex->kex_strict = kexalgs_contains(peer,
+ "kex-strict-s-v00@openssh.com");
+ }
+ if (kex->kex_strict) {
+ debug3("%s: will use strict KEX ordering", __func__);
+ if (seq != 0)
+ ssh_packet_disconnect(ssh,
+ "strict KEX violation: "
+ "KEXINIT was not the first packet");
+ }
}
/* Algorithm Negotiation */
diff --git a/kex.h b/kex.h
index eabae1d..5d3895c 100644
--- a/kex.h
+++ b/kex.h
@@ -155,6 +155,7 @@ struct kex {
u_int kex_type;
char *server_sig_algs;
int ext_info_c;
+ int kex_strict;
struct sshbuf *my;
struct sshbuf *peer;
struct sshbuf *client_version;
diff --git a/packet.c b/packet.c
index f3231e1..16b87f5 100644
--- a/packet.c
+++ b/packet.c
@@ -1228,8 +1228,13 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
sshbuf_dump(state->output, stderr);
#endif
/* increment sequence number for outgoing packets */
- if (++state->p_send.seqnr == 0)
+ if (++state->p_send.seqnr == 0) {
+ if ((ssh->kex->flags & KEX_INITIAL) != 0) {
+ ssh_packet_disconnect(ssh, "outgoing sequence number "
+ "wrapped during initial key exchange");
+ }
logit("outgoing seqnr wraps around");
+ }
if (++state->p_send.packets == 0)
if (!(ssh->compat & SSH_BUG_NOREKEY))
return SSH_ERR_NEED_REKEY;
@@ -1237,6 +1242,12 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
state->p_send.bytes += len;
sshbuf_reset(state->outgoing_packet);
+ if (type == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) {
+ debug("%s: resetting send seqnr %u", __func__,
+ state->p_send.seqnr);
+ state->p_send.seqnr = 0;
+ }
+
if (type == SSH2_MSG_NEWKEYS)
r = ssh_set_newkeys(ssh, MODE_OUT);
else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side)
@@ -1370,8 +1381,7 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
/* Stay in the loop until we have received a complete packet. */
for (;;) {
/* Try to read a packet from the buffer. */
- r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p);
- if (r != 0)
+ if ((r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p)) != 0)
break;
/* If we got a packet, return it. */
if (*typep != SSH_MSG_NONE)
@@ -1658,10 +1668,16 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
goto out;
}
+
if (seqnr_p != NULL)
*seqnr_p = state->p_read.seqnr;
- if (++state->p_read.seqnr == 0)
+ if (++state->p_read.seqnr == 0) {
+ if ((ssh->kex->flags & KEX_INITIAL) != 0) {
+ ssh_packet_disconnect(ssh, "incoming sequence number "
+ "wrapped during initial key exchange");
+ }
logit("incoming seqnr wraps around");
+ }
if (++state->p_read.packets == 0)
if (!(ssh->compat & SSH_BUG_NOREKEY))
return SSH_ERR_NEED_REKEY;
@@ -1727,6 +1743,11 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
#endif
/* reset for next packet */
state->packlen = 0;
+ if (*typep == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) {
+ debug("%s: resetting read seqnr %u", __func__,
+ state->p_read.seqnr);
+ state->p_read.seqnr = 0;
+ }
/* do we need to rekey? */
if (ssh_packet_need_rekeying(ssh, 0)) {
@@ -1747,10 +1768,39 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
if (r != 0)
return r;
- if (*typep) {
- state->keep_alive_timeouts = 0;
- DBG(debug("received packet type %d", *typep));
+ if (*typep == 0) {
+ /* no message ready */
+ return 0;
+ }
+ state->keep_alive_timeouts = 0;
+ DBG(debug("received packet type %d", *typep));
+
+ /* Always process disconnect messages */
+ if (*typep == SSH2_MSG_DISCONNECT) {
+ if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
+ return r;
+ /* Ignore normal client exit notifications */
+ do_log2(ssh->state->server_side &&
+ reason == SSH2_DISCONNECT_BY_APPLICATION ?
+ SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
+ "Received disconnect from %s port %d:"
+ "%u: %.400s", ssh_remote_ipaddr(ssh),
+ ssh_remote_port(ssh), reason, msg);
+ free(msg);
+ return SSH_ERR_DISCONNECTED;
}
+
+ /*
+ * Do not implicitly handle any messages here during initial
+ * KEX when in strict mode. They will be need to be allowed
+ * explicitly by the KEX dispatch table or they will generate
+ * protocol errors.
+ */
+ if (ssh->kex != NULL &&
+ (ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict)
+ return 0;
+ /* Implicitly handle transport-level messages */
switch (*typep) {
case SSH2_MSG_IGNORE:
debug3("Received SSH2_MSG_IGNORE");
@@ -1765,19 +1815,6 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
debug("Remote: %.900s", msg);
free(msg);
break;
- case SSH2_MSG_DISCONNECT:
- if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
- return r;
- /* Ignore normal client exit notifications */
- do_log2(ssh->state->server_side &&
- reason == SSH2_DISCONNECT_BY_APPLICATION ?
- SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
- "Received disconnect from %s port %d:"
- "%u: %.400s", ssh_remote_ipaddr(ssh),
- ssh_remote_port(ssh), reason, msg);
- free(msg);
- return SSH_ERR_DISCONNECTED;
case SSH2_MSG_UNIMPLEMENTED:
if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
return r;
@@ -2321,6 +2358,7 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
(r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 ||
(r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 ||
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
+ (r = sshbuf_put_u32(m, kex->kex_strict)) != 0 ||
(r = sshbuf_put_stringb(m, kex->my)) != 0 ||
(r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
(r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
@@ -2483,6 +2521,7 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 ||
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 ||
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
+ (r = sshbuf_get_u32(m, &kex->kex_strict)) != 0 ||
(r = sshbuf_get_stringb(m, kex->my)) != 0 ||
(r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
(r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
@@ -2810,6 +2849,7 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...)
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
+ debug2("%s: sending SSH2_MSG_DISCONNECT: %s", __func__, buf);
if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
(r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
diff --git a/sshconnect2.c b/sshconnect2.c
index 82846b5..1827f65 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -236,7 +236,8 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
fatal("%s: kex_assemble_namelist", __func__);
free(all_key);
- if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
+ if ((s = kex_names_cat(options.kex_algorithms,
+ "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
fatal("%s: kex_names_cat", __func__);
myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s);
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
@@ -430,7 +431,6 @@ struct cauthmethod {
};
static int input_userauth_service_accept(int, u_int32_t, struct ssh *);
-static int input_userauth_ext_info(int, u_int32_t, struct ssh *);
static int input_userauth_success(int, u_int32_t, struct ssh *);
static int input_userauth_failure(int, u_int32_t, struct ssh *);
static int input_userauth_banner(int, u_int32_t, struct ssh *);
@@ -554,7 +554,7 @@ ssh_userauth2(struct ssh *ssh, const char *local_user,
ssh->authctxt = &authctxt;
ssh_dispatch_init(ssh, &input_userauth_error);
- ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info);
+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, kex_input_ext_info);
ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept);
ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */
pubkey_cleanup(ssh);
@@ -602,13 +602,6 @@ input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh)
return r;
}
-/* ARGSUSED */
-static int
-input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh)
-{
- return kex_input_ext_info(type, seqnr, ssh);
-}
-
void
userauth(struct ssh *ssh, char *authlist)
{
@@ -690,6 +683,7 @@ input_userauth_success(int type, u_int32_t seq, struct ssh *ssh)
free(authctxt->methoddata);
authctxt->methoddata = NULL;
authctxt->success = 1; /* break out */
+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, dispatch_protocol_error);
return 0;
}
diff --git a/sshd.c b/sshd.c
index ed5f075..e544b0c 100644
--- a/sshd.c
+++ b/sshd.c
@@ -2494,9 +2494,12 @@ do_ssh2_kex(struct ssh *ssh)
char *myproposal[PROPOSAL_MAX] = { KEX_SERVER };
struct kex *kex;
+ char *s;
int r;
- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
- options.kex_algorithms);
+ if ((s = kex_names_cat(options.kex_algorithms,
+ "kex-strict-s-v00@openssh.com")) == NULL)
+ fatal("%s: kex_names_cat", __func__);
+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s);
myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(
options.ciphers);
myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(
@@ -2615,6 +2618,7 @@ do_ssh2_kex(struct ssh *ssh)
packet_send();
packet_write_wait();
#endif
+ free(s);
debug("KEX done");
}
--
2.33.0

View File

@ -0,0 +1,100 @@
From 7ef3787c84b6b524501211b11a26c742f829af1a Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Mon, 18 Dec 2023 14:47:44 +0000
Subject: [PATCH] upstream: ban user/hostnames with most shell metacharacters
This makes ssh(1) refuse user or host names provided on the
commandline that contain most shell metacharacters.
Some programs that invoke ssh(1) using untrusted data do not filter
metacharacters in arguments they supply. This could create
interactions with user-specified ProxyCommand and other directives
that allow shell injection attacks to occur.
It's a mistake to invoke ssh(1) with arbitrary untrusted arguments,
but getting this stuff right can be tricky, so this should prevent
most obvious ways of creating risky situations. It however is not
and cannot be perfect: ssh(1) has no practical way of interpreting
what shell quoting rules are in use and how they interact with the
user's specified ProxyCommand.
To allow configurations that use strange user or hostnames to
continue to work, this strictness is applied only to names coming
from the commandline. Names specified using User or Hostname
directives in ssh_config(5) are not affected.
feedback/ok millert@ markus@ dtucker@ deraadt@
OpenBSD-Commit-ID: 3b487348b5964f3e77b6b4d3da4c3b439e94b2d9
Reference:https://anongit.mindrot.org/openssh.git/commit?id=7ef3787c84b6b524501211b11a26c742f829af1a
---
ssh.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/ssh.c b/ssh.c
index 35c48e62d..48d93ddf2 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.519 2020/02/07 03:54:44 dtucker Exp $ */
+/* $OpenBSD: ssh.c,v 1.599 2023/12/18 14:47:44 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -570,6 +570,41 @@ set_addrinfo_port(struct addrinfo *addrs, int port)
}
}
+static int
+valid_hostname(const char *s)
+{
+ size_t i;
+
+ if (*s == '-')
+ return 0;
+ for (i = 0; s[i] != 0; i++) {
+ if (strchr("'`\"$\\;&<>|(){}", s[i]) != NULL ||
+ isspace((u_char)s[i]) || iscntrl((u_char)s[i]))
+ return 0;
+ }
+ return 1;
+}
+
+static int
+valid_ruser(const char *s)
+{
+ size_t i;
+
+ if (*s == '-')
+ return 0;
+ for (i = 0; s[i] != 0; i++) {
+ if (strchr("'`\";&<>|(){}", s[i]) != NULL)
+ return 0;
+ /* Disallow '-' after whitespace */
+ if (isspace((u_char)s[i]) && s[i + 1] == '-')
+ return 0;
+ /* Disallow \ in last position */
+ if (s[i] == '\\' && s[i + 1] == '\0')
+ return 0;
+ }
+ return 1;
+}
+
/*
* Main program for the ssh client.
*/
@@ -1118,6 +1153,10 @@ main(int ac, char **av)
if (!host)
usage();
+ if (!valid_hostname(host))
+ fatal("hostname contains invalid characters");
+ if (options.user != NULL && !valid_ruser(options.user))
+ fatal("remote username contains invalid characters");
host_arg = xstrdup(host);
/* Initialize the command to execute on remote host. */
--
2.23.0

View File

@ -0,0 +1,41 @@
From a0b5816f8f1f645acdf74f7bc11b34455ec30bac Mon Sep 17 00:00:00 2001
From: "djm@openbsd.org" <djm@openbsd.org>
Date: Fri, 18 Mar 2022 02:31:25 +0000
Subject: [PATCH] upstream: ssh-keygen -Y check-novalidate requires namespace
or SEGV
will ensue. Patch from Mateusz Adamowski via GHPR#307
OpenBSD-Commit-ID: 99e8ec38f9feb38bce6de240335be34aedeba5fd
Reference:https://github.com/openssh/openssh-portable/commit/a0b5816f8f1f645acdf74f7bc11b34455ec30bac
Conflict:NA
---
ssh-keygen.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/ssh-keygen.c b/ssh-keygen.c
index d2b4781..9559f70 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.398 2020/02/07 03:27:54 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.449 2022/03/18 02:31:25 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -3405,6 +3405,12 @@ main(int argc, char **argv)
return sig_sign(identity_file, cert_principals,
argc, argv);
} else if (strncmp(sign_op, "check-novalidate", 16) == 0) {
+ if (cert_principals == NULL ||
+ *cert_principals == '\0') {
+ error("Too few arguments for check-novalidate: "
+ "missing namespace");
+ exit(1);
+ }
if (ca_key_path == NULL) {
error("Too few arguments for check-novalidate: "
"missing signature file");
--
2.23.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
From c1345cb819e50e55ae1d3245e148da90260255ca Mon Sep 17 00:00:00 2001
From: songjuntao <songjuntao@kylinos.cn>
Date: Fri, 2 Feb 2024 16:05:29 +0800
Subject: [PATCH] fix memory leak in kex exchange function
Signed-off-by: songjuntao <songjuntao@kylinos.cn>
---
sshconnect2.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sshconnect2.c b/sshconnect2.c
index b82a118..ae018ff 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -354,6 +354,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
(r = ssh_packet_write_wait(ssh)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
#endif
+ free(s);
}
/*
--
2.33.0

View File

@ -6,7 +6,7 @@
%{?no_gtk2:%global gtk2 0}
%global sshd_uid 74
%global openssh_release 20
%global openssh_release 30
Name: openssh
Version: 8.2p1
@ -29,6 +29,7 @@ Source12: sshd-keygen@.service
Source13: sshd-keygen
Source14: sshd.tmpfiles
Source15: sshd-keygen.target
Source16: ssh-keygen-bash-completion.sh
Patch0: openssh-6.7p1-coverity.patch
Patch1: openssh-7.6p1-audit.patch
Patch2: openssh-7.1p2-audit-race-condition.patch
@ -97,13 +98,19 @@ Patch64: backport-CVE-2021-41617-2.patch
Patch65: backport-CVE-2021-28041.patch
Patch66: backport-change-convtime-form-returning-long-to-returning-int.patch
Patch67: backport-change-types-in-convtime-unit-test-to-int-to-match.patch
Patch68: backport-fix-possible-NULL-deref-when-built-without-FIDO.patch
Patch69: set-ssh-config.patch
Patch70: backport-fix-CVE-2023-38408-upstream-terminate-process.patch
Patch68: feature-add-SMx-support.patch
Patch69: backport-upstream-ssh-keygen-Y-check-novalidate-requires-name.patch
Patch70: backport-fix-possible-NULL-deref-when-built-without-FIDO.patch
Patch71: backport-fix-CVE-2023-38408-upstream-terminate-process.patch
Patch72: set-ssh-config.patch
Patch73: backport-CVE-2023-51385-upstream-ban-user-hostnames-with-most-shell-metachar.patch
Patch74: backport-CVE-2023-48795.patch
Patch75: fix-memory-leak-in-kex-exchange.patch
Requires: /sbin/nologin
Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8
Requires: openssh-server = %{version}-%{release} %{name}-help
Requires: openssh-server = %{version}-%{release}
Requires: openssl-libs >= 1:1.1.1f-1
BuildRequires: gtk2-devel libX11-devel openldap-devel autoconf automake perl-interpreter perl-generators
BuildRequires: zlib-devel audit-libs-devel >= 2.0.5 util-linux groff pam-devel fipscheck-devel >= 1.3.0
@ -271,7 +278,12 @@ popd
%patch67 -p1
%patch68 -p1
%patch69 -p1
#%patch70 -p1
%patch70 -p1
%patch71 -p1
%patch72 -p1
%patch73 -p1
%patch74 -p1
%patch75 -p1
autoreconf
pushd pam_ssh_agent_auth-0.10.3
@ -352,6 +364,7 @@ mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh
mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh/ssh_config.d
mkdir -p -m755 $RPM_BUILD_ROOT%{_libexecdir}/openssh
mkdir -p -m755 $RPM_BUILD_ROOT%{_var}/empty/sshd
mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d
%make_install
@ -375,6 +388,7 @@ install -m755 contrib/ssh-copy-id $RPM_BUILD_ROOT%{_bindir}/
install contrib/ssh-copy-id.1 $RPM_BUILD_ROOT%{_mandir}/man1/
install -m644 -D %{SOURCE14} $RPM_BUILD_ROOT%{_tmpfilesdir}/%{name}.conf
install contrib/gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/gnome-ssh-askpass
install -m644 %{SOURCE16} $RPM_BUILD_ROOT/etc/bash_completion.d/ssh-keygen-bash-completion.sh
ln -s gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/ssh-askpass
install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/
@ -413,6 +427,7 @@ getent passwd sshd >/dev/null || \
%attr(0755,root,root) %{_bindir}/ssh-keygen
%attr(0755,root,root) %dir %{_libexecdir}/openssh
%attr(2555,root,ssh_keys) %{_libexecdir}/openssh/ssh-keysign
%attr(0644,root,root) %{_sysconfdir}/bash_completion.d/ssh-keygen-bash-completion.sh
%files clients
%attr(0755,root,root) %{_bindir}/ssh
@ -478,49 +493,109 @@ getent passwd sshd >/dev/null || \
%attr(0644,root,root) %{_mandir}/man8/sftp-server.8*
%changelog
* Thu Jul 27 2023 renmingshuai<renmingshuai@huawei.cn> - 8.2p1-20
* Fri Feb 2 2024 songjuntao<songjuntao@kylinos.cn> - 8.2p1-30
- Type:bugfix
- CVE:
- SUG:NA
- DESC: fix memory leak in kex2 exchange function
* Tue Jan 9 2024 renmingshuai<renmingshuai@huawei.cn> - 8.2p1-29
- Type:CVE
- CVE:CVE-2023-48795
- SUG:NA
- DESC:fix CVE-2023-48795
* Mon Dec 25 2023 renmingshuai<renmingshuai@huawei.cn> - 8.2p1-28
- Type:CVE
- CVE:CVE-2023-51385
- SUG:NA
- DESC:fix CVE-2023-51385
* Thu Jul 27 2023 renmingshuai<renmingshuai@huawei.cn> - 8.2p1-27
- Type:CVE
- CVE:CVE-2023-38408
- SUG:NA
- DESC:fix CVE-2023-38408
- DESC:fix CVE-2023-38408 and set ssh default config
* Tue Feb 28 2023 renmingshuai<renmingshuai@huawei.cn> - 8.2p1-19
- Type:bugfix
- CVE:NA
- SUG:NA
- DESC:set default ssh_config
* Mon Jan 09 2023 renmingshuai<renmingshuai@huawei.cn> - 8.2p1-18
* Mon Jan 09 2023 renmingshuai<renmingshuai@huawei.cn> - 8.2p1-26
- Type:bugfix
- CVE:
- SUG:NA
- DESC:fix possible NULL deref when built without FIDO
* Fri Jan 06 2023 renmingshuai<renmingshuai@hauwei.com> - 8.2p1-17
- Type:requirement
- CVE:NA
- SUG:NA
- DESC:enable make tests
* Tue Feb 8 2022 renmingshuai<renmingshuai@hauwei.com> - 8.2P1-16
* Tue Jan 03 2023 renmingshuai<renmingshuai@huawei.cn> - 8.2p1-25
- Type:bugfix
- CVE:NA
- CVE:
- SUG:NA
- DESC:change convtime from returning long to returning int
- DESC:always make tests
* Wed Dec 15 2021 renmingshuai<renmingshuai@hauwei.com> - 8.2P1-15
* Mon Nov 28 2022 renmingshuai<renmingshuai@huawei.cn> - 8.2P1-24
- Type:bugfix
- CVE:
- SUG:NA
- DESC:ssh-keygen -Y check-novalidate requires namespace or SEGV
* Fri Sep 9 2022 lvfei<lvfei@kylinos.cn> - 8.2P1-23
- Type:bugfix
- CVE:
- SUG:NA
- DESC: remove require openssh-help version
* Thu Sep 8 2022 licihua<licihua@huawei.com> - 8.2P1-22
- Type:bugfix
- CVE:
- SUG:NA
- DESC: define openssh-develp version
* Wed Sep 5 2022 renmingshuai<renmingshuai@huawei.com> - 8.2P1-21
- Type:bugfix
- CVE:
- SUG:NA
- DESC:add require openssl version
* Mon Sep 5 2022 renmingshuai<renmingshuai@huawei.com> - 8.2P1-20
- Type:bugfix
- CVE:
- SUG:NA
- DESC:set ssh_config
* Mon Sep 5 2022 renmingshuai<renmingshuai@huawei.com> - 8.2P1-19
- Type:bugfix
- CVE:
- SUG:NA
- DESC:add ssh-keygen bash completion
* Sat Sep 3 2022 renmingshuai<renmingshuai@huawei.com> - 8.2P1-18
- Type:bugfix
- CVE:
- SUG:NA
- DESC:modify After=network.target in sshd.service
* Thu Sep 1 2022 renmingshuai<renmingshuai@huawei.com> - 8.2P1-17
- Type:requirement
- CVE:
- SUG:NA
- DESC:add SMx support in openssh
* Tue Feb 8 2022 renmingshuai<renmingshuai@huawei.com> - 8.2P1-16
- Type:bugfix
- CVE:
- SUG:NA
- DESC:change convtime form returning long to returning int
* Wed Dec 15 2021 renmingshuai<renmingshuai@huawei.com> - 8.2P1-15
- Type:cves
- CVE:CVE-2021-28041
- SUG:NA
- DESC:fix CVE-2021-28041
* Sat Oct 09 2021 renmingshuai<renmingshuai@hauwei.com> - 8.2P1-14
* Sat Oct 09 2021 renmingshuai<renmingshuai@huawei.com> - 8.2P1-14
- Type:bugfix
- CVE:CVE-2021-41617
- SUG:NA
- DESC:fix CVE-2021-41617
* Sat Aug 7 2021 seuzw<930zhaowei@163.com> - 8.2P1-13
* Mon Aug 09 2021 chxssg<chxssg@qq.com> - 8.2P1-13
- Type:bugfix
- CVE:NA
- SUG:NA
@ -532,28 +607,28 @@ getent passwd sshd >/dev/null || \
- SUG:NA
- DESC:add strict-scp-check for check command injection
* Wed Jul 21 2021 panchenbo<panchenbo@uniontech.com> - 8.2P1-11
* Mon Jul 12 2021 panchenbo<panchenbo@uniontech.com> - 8.2P1-11
- fix pam_ssh_agent_auth.8.gz conflicts
* Fri May 21 2021 renmingshuai<renmingshuai@huawei.com> - 8.2P1-10
- Type:cves
- ID:NA
- SUG:NA
- DESC:fix /etc/ssh generate key file access permission error
* Tue Jan 12 2021 yuboyun<yuboyun@huawei.com> - 8.2P1-9
* Tue Jan 12 2021 yuboyun<yuboyun@huawei.com> - 8.2P1-10
- Type:cves
- ID:CVE-2020-14145
- SUG:NA
- DESC:Fix CVE-2020-14145
* Wed Nov 18 2020 gaihuiying<gaihuiying1@huawei.com> - 8.2P1-8
* Fri Dec 18 2020 gaihuiying<gaihuiying1@huawei.com> - 8.2P1-9
- Type:bugfix
- CVE:NA
- SUG:NA
- DESC:adjust pam_ssh_agent_auth release number
- DESC:update key file permissions to 600
* Tue Nov 17 2020 gaihuiying<gaihuiying1@huawei.com> - 8.2P1-7
* Wed Dec 09 2020 quanhongfei<quanhongfei@huawei.com> - 8.2P1-8
- Type:bugfix
- CVE:NA
- SUG:NA
- DESC:fix /etc/ssh/ generate key file access premission error
* Wed Nov 18 2020 gaihuiying<gaihuiying1@huawei.com> - 8.2P1-7
- Type:bugfix
- CVE:NA
- SUG:NA

View File

@ -21,7 +21,7 @@ index df22e2f..46b0987 100644
+ ForwardX11Trusted yes
+ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+ SendEnv LC_IDENTIFIACTION LC_ALL_LANGUAGE
+ SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE
+ SendEnv XMODIFIERS
+
Include /etc/ssh/ssh_config.d/*.conf

View File

@ -0,0 +1,63 @@
# ssh-keygen(1) completion -*- shell-script -*-
_ssh_keygen()
{
local cur prev words cword
_init_completion -n = || return
case $prev in
-*[abCIJjMNnrPSVWz])
return
;;
-*E)
COMPREPLY=( $(compgen -W 'md5 sha256' -- "$cur") )
return
;;
-*[FR])
# TODO: trim this down to actual entries in known hosts files
_known_hosts_real -- "$cur"
return
;;
-*D)
_filedir so
return
;;
-*[fGKsT])
_filedir
return
;;
-*m)
COMPREPLY=( $(compgen -W 'PEM PKCS8 RFC4716' -- "$cur") )
return
;;
-*O)
if [[ $cur != *=* ]]; then
COMPREPLY=( $(compgen -W 'clear force-command=
no-agent-forwarding no-port-forwarding no-pty no-user-rc
no-x11-forwarding permit-agent-forwarding
permit-port-forwarding permit-pty permit-user-rc
permit-x11-forwarding source-address=' -- "$cur") )
[[ $COMPREPLY == *= ]] && compopt -o nospace
fi
return
;;
-*t)
local protocols=$(_xfunc ssh _ssh_query "$1" protocol-version)
local types='dsa ecdsa ed25519 rsa sm2'
if [[ $protocols == *1* ]]; then
types+=' rsa1'
fi
COMPREPLY=( $(compgen -W "$types" -- "$cur") )
return
;;
esac
if [[ $cur == -* ]]; then
local opts=$(_parse_usage "$1" "-?")
[[ -z "$opts" ]] && opts=$(_parse_help "$1" "-?") # OpenSSH < 7
COMPREPLY=( $(compgen -W "$opts" -- "$cur") )
fi
} &&
complete -F _ssh_keygen ssh-keygen
# ex: filetype=sh

View File

@ -1,7 +1,8 @@
# /usr/lib/systemd/system/sshd.service
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.target
After=network-online.target sshd-keygen.target
Wants=sshd-keygen.target
[Service]