diff options
| author | Peter Marko <peter.marko@siemens.com> | 2024-11-08 23:49:00 +0100 |
|---|---|---|
| committer | Steve Sakoman <steve@sakoman.com> | 2024-11-18 06:59:35 -0800 |
| commit | 19b2afe4af9064461153820483db6c4b30d6996f (patch) | |
| tree | 1224e3c09066db0660ca13ddf4c21d6a4e83b4c4 | |
| parent | dce4163d42f7036ea216b52b9135968d51bec4c1 (diff) | |
| download | poky-19b2afe4af9064461153820483db6c4b30d6996f.tar.gz | |
dropbear: backport patch for CVE-2023-48795
Documentation for this patch is under
https://github.com/mkj/dropbear/commit/66bc1fcdee594c6cb1139df0ef8a6c9c5fc3fde3
(From OE-Core rev: 2ab0b4212aee85c77c3667ccfaedbe9540e78e3f)
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
| -rw-r--r-- | meta/recipes-core/dropbear/dropbear/CVE-2023-48795.patch | 234 | ||||
| -rw-r--r-- | meta/recipes-core/dropbear/dropbear_2022.83.bb | 1 |
2 files changed, 235 insertions, 0 deletions
diff --git a/meta/recipes-core/dropbear/dropbear/CVE-2023-48795.patch b/meta/recipes-core/dropbear/dropbear/CVE-2023-48795.patch new file mode 100644 index 0000000000..64b0405473 --- /dev/null +++ b/meta/recipes-core/dropbear/dropbear/CVE-2023-48795.patch | |||
| @@ -0,0 +1,234 @@ | |||
| 1 | From 6e43be5c7b99dbee49dc72b6f989f29fdd7e9356 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Matt Johnston <matt@ucc.asn.au> | ||
| 3 | Date: Mon, 20 Nov 2023 14:02:47 +0800 | ||
| 4 | Subject: [PATCH] Implement Strict KEX mode | ||
| 5 | |||
| 6 | As specified by OpenSSH with kex-strict-c-v00@openssh.com and | ||
| 7 | kex-strict-s-v00@openssh.com. | ||
| 8 | |||
| 9 | CVE: CVE-2023-48795 | ||
| 10 | Upstream-Status: Backport [https://github.com/mkj/dropbear/commit/6e43be5c7b99dbee49dc72b6f989f29fdd7e9356] | ||
| 11 | |||
| 12 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
| 13 | --- | ||
| 14 | cli-session.c | 11 +++++++++++ | ||
| 15 | common-algo.c | 6 ++++++ | ||
| 16 | common-kex.c | 26 +++++++++++++++++++++++++- | ||
| 17 | kex.h | 3 +++ | ||
| 18 | process-packet.c | 34 +++++++++++++++++++--------------- | ||
| 19 | ssh.h | 4 ++++ | ||
| 20 | svr-session.c | 3 +++ | ||
| 21 | 7 files changed, 71 insertions(+), 16 deletions(-) | ||
| 22 | |||
| 23 | diff --git a/cli-session.c b/cli-session.c | ||
| 24 | index 5981b24..d261c8f 100644 | ||
| 25 | --- a/cli-session.c | ||
| 26 | +++ b/cli-session.c | ||
| 27 | @@ -46,6 +46,7 @@ static void cli_finished(void) ATTRIB_NORETURN; | ||
| 28 | static void recv_msg_service_accept(void); | ||
| 29 | static void cli_session_cleanup(void); | ||
| 30 | static void recv_msg_global_request_cli(void); | ||
| 31 | +static void cli_algos_initialise(void); | ||
| 32 | |||
| 33 | struct clientsession cli_ses; /* GLOBAL */ | ||
| 34 | |||
| 35 | @@ -117,6 +118,7 @@ void cli_session(int sock_in, int sock_out, struct dropbear_progress_connection | ||
| 36 | } | ||
| 37 | |||
| 38 | chaninitialise(cli_chantypes); | ||
| 39 | + cli_algos_initialise(); | ||
| 40 | |||
| 41 | /* Set up cli_ses vars */ | ||
| 42 | cli_session_init(proxy_cmd_pid); | ||
| 43 | @@ -487,3 +489,12 @@ void cli_dropbear_log(int priority, const char* format, va_list param) { | ||
| 44 | fflush(stderr); | ||
| 45 | } | ||
| 46 | |||
| 47 | +static void cli_algos_initialise(void) { | ||
| 48 | + algo_type *algo; | ||
| 49 | + for (algo = sshkex; algo->name; algo++) { | ||
| 50 | + if (strcmp(algo->name, SSH_STRICT_KEX_S) == 0) { | ||
| 51 | + algo->usable = 0; | ||
| 52 | + } | ||
| 53 | + } | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | diff --git a/common-algo.c b/common-algo.c | ||
| 57 | index 378f0ca..f9d46eb 100644 | ||
| 58 | --- a/common-algo.c | ||
| 59 | +++ b/common-algo.c | ||
| 60 | @@ -307,6 +307,12 @@ algo_type sshkex[] = { | ||
| 61 | /* Set unusable by svr_algos_initialise() */ | ||
| 62 | {SSH_EXT_INFO_C, 0, NULL, 1, NULL}, | ||
| 63 | #endif | ||
| 64 | +#endif | ||
| 65 | +#if DROPBEAR_CLIENT | ||
| 66 | + {SSH_STRICT_KEX_C, 0, NULL, 1, NULL}, | ||
| 67 | +#endif | ||
| 68 | +#if DROPBEAR_SERVER | ||
| 69 | + {SSH_STRICT_KEX_S, 0, NULL, 1, NULL}, | ||
| 70 | #endif | ||
| 71 | {NULL, 0, NULL, 0, NULL} | ||
| 72 | }; | ||
| 73 | diff --git a/common-kex.c b/common-kex.c | ||
| 74 | index ac88442..8e33b12 100644 | ||
| 75 | --- a/common-kex.c | ||
| 76 | +++ b/common-kex.c | ||
| 77 | @@ -183,6 +183,10 @@ void send_msg_newkeys() { | ||
| 78 | gen_new_keys(); | ||
| 79 | switch_keys(); | ||
| 80 | |||
| 81 | + if (ses.kexstate.strict_kex) { | ||
| 82 | + ses.transseq = 0; | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | TRACE(("leave send_msg_newkeys")) | ||
| 86 | } | ||
| 87 | |||
| 88 | @@ -193,7 +197,11 @@ void recv_msg_newkeys() { | ||
| 89 | |||
| 90 | ses.kexstate.recvnewkeys = 1; | ||
| 91 | switch_keys(); | ||
| 92 | - | ||
| 93 | + | ||
| 94 | + if (ses.kexstate.strict_kex) { | ||
| 95 | + ses.recvseq = 0; | ||
| 96 | + } | ||
| 97 | + | ||
| 98 | TRACE(("leave recv_msg_newkeys")) | ||
| 99 | } | ||
| 100 | |||
| 101 | @@ -550,6 +558,10 @@ void recv_msg_kexinit() { | ||
| 102 | |||
| 103 | ses.kexstate.recvkexinit = 1; | ||
| 104 | |||
| 105 | + if (ses.kexstate.strict_kex && !ses.kexstate.donefirstkex && ses.recvseq != 1) { | ||
| 106 | + dropbear_exit("First packet wasn't kexinit"); | ||
| 107 | + } | ||
| 108 | + | ||
| 109 | TRACE(("leave recv_msg_kexinit")) | ||
| 110 | } | ||
| 111 | |||
| 112 | @@ -859,6 +871,18 @@ static void read_kex_algos() { | ||
| 113 | } | ||
| 114 | #endif | ||
| 115 | |||
| 116 | + if (!ses.kexstate.donefirstkex) { | ||
| 117 | + const char* strict_name; | ||
| 118 | + if (IS_DROPBEAR_CLIENT) { | ||
| 119 | + strict_name = SSH_STRICT_KEX_S; | ||
| 120 | + } else { | ||
| 121 | + strict_name = SSH_STRICT_KEX_C; | ||
| 122 | + } | ||
| 123 | + if (buf_has_algo(ses.payload, strict_name) == DROPBEAR_SUCCESS) { | ||
| 124 | + ses.kexstate.strict_kex = 1; | ||
| 125 | + } | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | algo = buf_match_algo(ses.payload, sshkex, kexguess2, &goodguess); | ||
| 129 | allgood &= goodguess; | ||
| 130 | if (algo == NULL || algo->data == NULL) { | ||
| 131 | diff --git a/kex.h b/kex.h | ||
| 132 | index 77cf21a..7fcc3c2 100644 | ||
| 133 | --- a/kex.h | ||
| 134 | +++ b/kex.h | ||
| 135 | @@ -83,6 +83,9 @@ struct KEXState { | ||
| 136 | |||
| 137 | unsigned our_first_follows_matches : 1; | ||
| 138 | |||
| 139 | + /* Boolean indicating that strict kex mode is in use */ | ||
| 140 | + unsigned int strict_kex; | ||
| 141 | + | ||
| 142 | time_t lastkextime; /* time of the last kex */ | ||
| 143 | unsigned int datatrans; /* data transmitted since last kex */ | ||
| 144 | unsigned int datarecv; /* data received since last kex */ | ||
| 145 | diff --git a/process-packet.c b/process-packet.c | ||
| 146 | index 9454160..133a152 100644 | ||
| 147 | --- a/process-packet.c | ||
| 148 | +++ b/process-packet.c | ||
| 149 | @@ -44,6 +44,7 @@ void process_packet() { | ||
| 150 | |||
| 151 | unsigned char type; | ||
| 152 | unsigned int i; | ||
| 153 | + unsigned int first_strict_kex = ses.kexstate.strict_kex && !ses.kexstate.donefirstkex; | ||
| 154 | time_t now; | ||
| 155 | |||
| 156 | TRACE2(("enter process_packet")) | ||
| 157 | @@ -54,22 +55,24 @@ void process_packet() { | ||
| 158 | now = monotonic_now(); | ||
| 159 | ses.last_packet_time_keepalive_recv = now; | ||
| 160 | |||
| 161 | - /* These packets we can receive at any time */ | ||
| 162 | - switch(type) { | ||
| 163 | |||
| 164 | - case SSH_MSG_IGNORE: | ||
| 165 | - goto out; | ||
| 166 | - case SSH_MSG_DEBUG: | ||
| 167 | - goto out; | ||
| 168 | + if (type == SSH_MSG_DISCONNECT) { | ||
| 169 | + /* Allowed at any time */ | ||
| 170 | + dropbear_close("Disconnect received"); | ||
| 171 | + } | ||
| 172 | |||
| 173 | - case SSH_MSG_UNIMPLEMENTED: | ||
| 174 | - /* debugging XXX */ | ||
| 175 | - TRACE(("SSH_MSG_UNIMPLEMENTED")) | ||
| 176 | - goto out; | ||
| 177 | - | ||
| 178 | - case SSH_MSG_DISCONNECT: | ||
| 179 | - /* TODO cleanup? */ | ||
| 180 | - dropbear_close("Disconnect received"); | ||
| 181 | + /* These packets may be received at any time, | ||
| 182 | + except during first kex with strict kex */ | ||
| 183 | + if (!first_strict_kex) { | ||
| 184 | + switch(type) { | ||
| 185 | + case SSH_MSG_IGNORE: | ||
| 186 | + goto out; | ||
| 187 | + case SSH_MSG_DEBUG: | ||
| 188 | + goto out; | ||
| 189 | + case SSH_MSG_UNIMPLEMENTED: | ||
| 190 | + TRACE(("SSH_MSG_UNIMPLEMENTED")) | ||
| 191 | + goto out; | ||
| 192 | + } | ||
| 193 | } | ||
| 194 | |||
| 195 | /* Ignore these packet types so that keepalives don't interfere with | ||
| 196 | @@ -98,7 +101,8 @@ void process_packet() { | ||
| 197 | if (type >= 1 && type <= 49 | ||
| 198 | && type != SSH_MSG_SERVICE_REQUEST | ||
| 199 | && type != SSH_MSG_SERVICE_ACCEPT | ||
| 200 | - && type != SSH_MSG_KEXINIT) | ||
| 201 | + && type != SSH_MSG_KEXINIT | ||
| 202 | + && !first_strict_kex) | ||
| 203 | { | ||
| 204 | TRACE(("unknown allowed packet during kexinit")) | ||
| 205 | recv_unimplemented(); | ||
| 206 | diff --git a/ssh.h b/ssh.h | ||
| 207 | index 1b4fec6..ef3efdc 100644 | ||
| 208 | --- a/ssh.h | ||
| 209 | +++ b/ssh.h | ||
| 210 | @@ -100,6 +100,10 @@ | ||
| 211 | #define SSH_EXT_INFO_C "ext-info-c" | ||
| 212 | #define SSH_SERVER_SIG_ALGS "server-sig-algs" | ||
| 213 | |||
| 214 | +/* OpenSSH strict KEX feature */ | ||
| 215 | +#define SSH_STRICT_KEX_S "kex-strict-s-v00@openssh.com" | ||
| 216 | +#define SSH_STRICT_KEX_C "kex-strict-c-v00@openssh.com" | ||
| 217 | + | ||
| 218 | /* service types */ | ||
| 219 | #define SSH_SERVICE_USERAUTH "ssh-userauth" | ||
| 220 | #define SSH_SERVICE_USERAUTH_LEN 12 | ||
| 221 | diff --git a/svr-session.c b/svr-session.c | ||
| 222 | index 769f073..a538e2c 100644 | ||
| 223 | --- a/svr-session.c | ||
| 224 | +++ b/svr-session.c | ||
| 225 | @@ -370,6 +370,9 @@ static void svr_algos_initialise(void) { | ||
| 226 | algo->usable = 0; | ||
| 227 | } | ||
| 228 | #endif | ||
| 229 | + if (strcmp(algo->name, SSH_STRICT_KEX_C) == 0) { | ||
| 230 | + algo->usable = 0; | ||
| 231 | + } | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
diff --git a/meta/recipes-core/dropbear/dropbear_2022.83.bb b/meta/recipes-core/dropbear/dropbear_2022.83.bb index 528eff1a10..686cb8a809 100644 --- a/meta/recipes-core/dropbear/dropbear_2022.83.bb +++ b/meta/recipes-core/dropbear/dropbear_2022.83.bb | |||
| @@ -22,6 +22,7 @@ SRC_URI = "http://matt.ucc.asn.au/dropbear/releases/dropbear-${PV}.tar.bz2 \ | |||
| 22 | ${@bb.utils.contains('DISTRO_FEATURES', 'pam', '${PAM_SRC_URI}', '', d)} \ | 22 | ${@bb.utils.contains('DISTRO_FEATURES', 'pam', '${PAM_SRC_URI}', '', d)} \ |
| 23 | ${@bb.utils.contains('PACKAGECONFIG', 'disable-weak-ciphers', 'file://dropbear-disable-weak-ciphers.patch', '', d)} \ | 23 | ${@bb.utils.contains('PACKAGECONFIG', 'disable-weak-ciphers', 'file://dropbear-disable-weak-ciphers.patch', '', d)} \ |
| 24 | file://CVE-2023-36328.patch \ | 24 | file://CVE-2023-36328.patch \ |
| 25 | file://CVE-2023-48795.patch \ | ||
| 25 | " | 26 | " |
| 26 | 27 | ||
| 27 | SRC_URI[sha256sum] = "bc5a121ffbc94b5171ad5ebe01be42746d50aa797c9549a4639894a16749443b" | 28 | SRC_URI[sha256sum] = "bc5a121ffbc94b5171ad5ebe01be42746d50aa797c9549a4639894a16749443b" |
