diff options
| author | Vijay Anusuri <vanusuri@mvista.com> | 2024-01-19 08:56:19 +0530 |
|---|---|---|
| committer | Armin Kuster <akuster808@gmail.com> | 2024-02-07 18:41:41 -0500 |
| commit | 8ce84b09e5877200e4dfaad6d0f8443fbcb6a954 (patch) | |
| tree | f2d2722374eb709464922997bdb9943332fe5cde | |
| parent | dbb7b798f96ab652628743ceb6c7eaa9b593121d (diff) | |
| download | meta-openembedded-8ce84b09e5877200e4dfaad6d0f8443fbcb6a954.tar.gz | |
libssh: Backport fix for CVE-2023-48795
Upstream-Status: Backport
[https://gitlab.com/libssh/libssh-mirror/-/commit/4cef5e965a46e9271aed62631b152e4bd23c1e3c
&
https://gitlab.com/libssh/libssh-mirror/-/commit/0870c8db28be9eb457ee3d4f9a168959d9507efd
&
https://gitlab.com/libssh/libssh-mirror/-/commit/5846e57538c750c5ce67df887d09fa99861c79c6]
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
4 files changed, 561 insertions, 0 deletions
diff --git a/meta-oe/recipes-support/libssh/libssh/CVE-2023-48795-1.patch b/meta-oe/recipes-support/libssh/libssh/CVE-2023-48795-1.patch new file mode 100644 index 0000000000..413e5b3d11 --- /dev/null +++ b/meta-oe/recipes-support/libssh/libssh/CVE-2023-48795-1.patch | |||
| @@ -0,0 +1,385 @@ | |||
| 1 | From 4cef5e965a46e9271aed62631b152e4bd23c1e3c Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Aris Adamantiadis <aris@0xbadc0de.be> | ||
| 3 | Date: Tue, 12 Dec 2023 23:09:57 +0100 | ||
| 4 | Subject: [PATCH] CVE-2023-48795: client side mitigation | ||
| 5 | |||
| 6 | Signed-off-by: Aris Adamantiadis <aris@0xbadc0de.be> | ||
| 7 | Signed-off-by: Jakub Jelen <jjelen@redhat.com> | ||
| 8 | Reviewed-by: Andreas Schneider <asn@cryptomilk.org> | ||
| 9 | |||
| 10 | Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/4cef5e965a46e9271aed62631b152e4bd23c1e3c] | ||
| 11 | CVE: CVE-2023-48795 | ||
| 12 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
| 13 | --- | ||
| 14 | include/libssh/packet.h | 1 + | ||
| 15 | include/libssh/session.h | 6 +++++ | ||
| 16 | src/curve25519.c | 18 +++---------- | ||
| 17 | src/dh.c | 6 +---- | ||
| 18 | src/ecdh.c | 7 +---- | ||
| 19 | src/ecdh_crypto.c | 10 ++----- | ||
| 20 | src/ecdh_gcrypt.c | 10 +++---- | ||
| 21 | src/ecdh_mbedcrypto.c | 11 +++----- | ||
| 22 | src/kex.c | 34 ++++++++++++++++++++---- | ||
| 23 | src/packet.c | 56 +++++++++++++++++++++++++++++++++++++++- | ||
| 24 | src/packet_cb.c | 12 +++++++++ | ||
| 25 | 11 files changed, 118 insertions(+), 53 deletions(-) | ||
| 26 | |||
| 27 | diff --git a/include/libssh/packet.h b/include/libssh/packet.h | ||
| 28 | index fbe09700..8800e16b 100644 | ||
| 29 | --- a/include/libssh/packet.h | ||
| 30 | +++ b/include/libssh/packet.h | ||
| 31 | @@ -63,6 +63,7 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info); | ||
| 32 | SSH_PACKET_CALLBACK(ssh_packet_kexdh_init); | ||
| 33 | #endif | ||
| 34 | |||
| 35 | +int ssh_packet_send_newkeys(ssh_session session); | ||
| 36 | int ssh_packet_send_unimplemented(ssh_session session, uint32_t seqnum); | ||
| 37 | int ssh_packet_parse_type(ssh_session session); | ||
| 38 | //int packet_flush(ssh_session session, int enforce_blocking); | ||
| 39 | diff --git a/include/libssh/session.h b/include/libssh/session.h | ||
| 40 | index 23633cc2..b8810f54 100644 | ||
| 41 | --- a/include/libssh/session.h | ||
| 42 | +++ b/include/libssh/session.h | ||
| 43 | @@ -69,6 +69,12 @@ enum ssh_pending_call_e { | ||
| 44 | /* Client successfully authenticated */ | ||
| 45 | #define SSH_SESSION_FLAG_AUTHENTICATED 2 | ||
| 46 | |||
| 47 | +/* The current SSH2 session implements the "strict KEX" feature and should behave | ||
| 48 | + * differently on SSH2_MSG_NEWKEYS. */ | ||
| 49 | +#define SSH_SESSION_FLAG_KEX_STRICT 0x0010 | ||
| 50 | +/* Unexpected packets have been sent while the session was still unencrypted */ | ||
| 51 | +#define SSH_SESSION_FLAG_KEX_TAINTED 0x0020 | ||
| 52 | + | ||
| 53 | /* codes to use with ssh_handle_packets*() */ | ||
| 54 | /* Infinite timeout */ | ||
| 55 | #define SSH_TIMEOUT_INFINITE -1 | ||
| 56 | diff --git a/src/curve25519.c b/src/curve25519.c | ||
| 57 | index 167209f4..6eda5feb 100644 | ||
| 58 | --- a/src/curve25519.c | ||
| 59 | +++ b/src/curve25519.c | ||
| 60 | @@ -166,12 +166,7 @@ int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet){ | ||
| 61 | } | ||
| 62 | |||
| 63 | /* Send the MSG_NEWKEYS */ | ||
| 64 | - if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { | ||
| 65 | - goto error; | ||
| 66 | - } | ||
| 67 | - | ||
| 68 | - rc=ssh_packet_send(session); | ||
| 69 | - SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); | ||
| 70 | + rc = ssh_packet_send_newkeys(session); | ||
| 71 | return rc; | ||
| 72 | error: | ||
| 73 | return SSH_ERROR; | ||
| 74 | @@ -297,15 +292,10 @@ int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet){ | ||
| 75 | return SSH_ERROR; | ||
| 76 | } | ||
| 77 | |||
| 78 | - /* Send the MSG_NEWKEYS */ | ||
| 79 | - rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); | ||
| 80 | - if (rc < 0) { | ||
| 81 | - goto error; | ||
| 82 | - } | ||
| 83 | - | ||
| 84 | session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; | ||
| 85 | - rc = ssh_packet_send(session); | ||
| 86 | - SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); | ||
| 87 | + | ||
| 88 | + /* Send the MSG_NEWKEYS */ | ||
| 89 | + rc = ssh_packet_send_newkeys(session); | ||
| 90 | |||
| 91 | return rc; | ||
| 92 | error: | ||
| 93 | diff --git a/src/dh.c b/src/dh.c | ||
| 94 | index cc12fd46..33883f2d 100644 | ||
| 95 | --- a/src/dh.c | ||
| 96 | +++ b/src/dh.c | ||
| 97 | @@ -735,11 +735,7 @@ int ssh_client_dh_reply(ssh_session session, ssh_buffer packet){ | ||
| 98 | } | ||
| 99 | |||
| 100 | /* Send the MSG_NEWKEYS */ | ||
| 101 | - if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { | ||
| 102 | - goto error; | ||
| 103 | - } | ||
| 104 | - | ||
| 105 | - rc=ssh_packet_send(session); | ||
| 106 | + rc = ssh_packet_send_newkeys(session); | ||
| 107 | SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); | ||
| 108 | return rc; | ||
| 109 | error: | ||
| 110 | diff --git a/src/ecdh.c b/src/ecdh.c | ||
| 111 | index f7fcaf13..1fef7ec9 100644 | ||
| 112 | --- a/src/ecdh.c | ||
| 113 | +++ b/src/ecdh.c | ||
| 114 | @@ -72,12 +72,7 @@ int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet){ | ||
| 115 | } | ||
| 116 | |||
| 117 | /* Send the MSG_NEWKEYS */ | ||
| 118 | - if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { | ||
| 119 | - goto error; | ||
| 120 | - } | ||
| 121 | - | ||
| 122 | - rc=ssh_packet_send(session); | ||
| 123 | - SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); | ||
| 124 | + rc = ssh_packet_send_newkeys(session); | ||
| 125 | return rc; | ||
| 126 | error: | ||
| 127 | return SSH_ERROR; | ||
| 128 | diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c | ||
| 129 | index 24f21c03..7e5f0cc7 100644 | ||
| 130 | --- a/src/ecdh_crypto.c | ||
| 131 | +++ b/src/ecdh_crypto.c | ||
| 132 | @@ -318,15 +318,9 @@ int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){ | ||
| 133 | return SSH_ERROR; | ||
| 134 | } | ||
| 135 | |||
| 136 | - /* Send the MSG_NEWKEYS */ | ||
| 137 | - rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); | ||
| 138 | - if (rc < 0) { | ||
| 139 | - return SSH_ERROR;; | ||
| 140 | - } | ||
| 141 | - | ||
| 142 | session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; | ||
| 143 | - rc = ssh_packet_send(session); | ||
| 144 | - SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); | ||
| 145 | + /* Send the MSG_NEWKEYS */ | ||
| 146 | + rc = ssh_packet_send_newkeys(session); | ||
| 147 | |||
| 148 | return rc; | ||
| 149 | } | ||
| 150 | diff --git a/src/ecdh_gcrypt.c b/src/ecdh_gcrypt.c | ||
| 151 | index e43cacea..c1db7f5d 100644 | ||
| 152 | --- a/src/ecdh_gcrypt.c | ||
| 153 | +++ b/src/ecdh_gcrypt.c | ||
| 154 | @@ -362,17 +362,13 @@ int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet) { | ||
| 155 | goto out; | ||
| 156 | } | ||
| 157 | |||
| 158 | - | ||
| 159 | + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; | ||
| 160 | /* Send the MSG_NEWKEYS */ | ||
| 161 | - rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); | ||
| 162 | - if (rc != SSH_OK) { | ||
| 163 | + rc = ssh_packet_send_newkeys(session); | ||
| 164 | + if (rc == SSH_ERROR) { | ||
| 165 | goto out; | ||
| 166 | } | ||
| 167 | |||
| 168 | - session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; | ||
| 169 | - rc = ssh_packet_send(session); | ||
| 170 | - SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); | ||
| 171 | - | ||
| 172 | out: | ||
| 173 | gcry_sexp_release(param); | ||
| 174 | gcry_sexp_release(key); | ||
| 175 | diff --git a/src/ecdh_mbedcrypto.c b/src/ecdh_mbedcrypto.c | ||
| 176 | index fa350028..24924508 100644 | ||
| 177 | --- a/src/ecdh_mbedcrypto.c | ||
| 178 | +++ b/src/ecdh_mbedcrypto.c | ||
| 179 | @@ -293,16 +293,13 @@ int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet) | ||
| 180 | goto out; | ||
| 181 | } | ||
| 182 | |||
| 183 | - rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); | ||
| 184 | - if (rc < 0) { | ||
| 185 | - rc = SSH_ERROR; | ||
| 186 | + session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; | ||
| 187 | + /* Send the MSG_NEWKEYS */ | ||
| 188 | + rc = ssh_packet_send_newkeys(session); | ||
| 189 | + if (rc == SSH_ERROR) { | ||
| 190 | goto out; | ||
| 191 | } | ||
| 192 | |||
| 193 | - session->dh_handshake_state = DH_STATE_NEWKEYS_SENT; | ||
| 194 | - rc = ssh_packet_send(session); | ||
| 195 | - SSH_LOG(SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); | ||
| 196 | - | ||
| 197 | out: | ||
| 198 | mbedtls_ecp_group_free(&grp); | ||
| 199 | return rc; | ||
| 200 | diff --git a/src/kex.c b/src/kex.c | ||
| 201 | index 82686e4b..7f1bb324 100644 | ||
| 202 | --- a/src/kex.c | ||
| 203 | +++ b/src/kex.c | ||
| 204 | @@ -105,6 +105,9 @@ | ||
| 205 | |||
| 206 | /* RFC 8308 */ | ||
| 207 | #define KEX_EXTENSION_CLIENT "ext-info-c" | ||
| 208 | +/* Strict kex mitigation against CVE-2023-48795 */ | ||
| 209 | +#define KEX_STRICT_CLIENT "kex-strict-c-v00@openssh.com" | ||
| 210 | +#define KEX_STRICT_SERVER "kex-strict-s-v00@openssh.com" | ||
| 211 | |||
| 212 | /* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */ | ||
| 213 | static const char *default_methods[] = { | ||
| 214 | @@ -521,6 +524,27 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){ | ||
| 215 | goto error; | ||
| 216 | } | ||
| 217 | |||
| 218 | + /* | ||
| 219 | + * handle the "strict KEX" feature. If supported by peer, then set up the | ||
| 220 | + * flag and verify packet sequence numbers. | ||
| 221 | + */ | ||
| 222 | + if (server_kex) { | ||
| 223 | + ok = ssh_match_group(session->next_crypto->client_kex.methods[SSH_KEX], | ||
| 224 | + KEX_STRICT_CLIENT); | ||
| 225 | + if (ok) { | ||
| 226 | + SSH_LOG(SSH_LOG_DEBUG, "Client supports strict kex, enabling."); | ||
| 227 | + session->flags |= SSH_SESSION_FLAG_KEX_STRICT; | ||
| 228 | + } | ||
| 229 | + } else { | ||
| 230 | + /* client kex */ | ||
| 231 | + ok = ssh_match_group(session->next_crypto->server_kex.methods[SSH_KEX], | ||
| 232 | + KEX_STRICT_SERVER); | ||
| 233 | + if (ok) { | ||
| 234 | + SSH_LOG(SSH_LOG_DEBUG, "Server supports strict kex, enabling."); | ||
| 235 | + session->flags |= SSH_SESSION_FLAG_KEX_STRICT; | ||
| 236 | + } | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | /* | ||
| 240 | * If client sent a ext-info-c message in the kex list, it supports | ||
| 241 | * RFC 8308 extension negotiation. | ||
| 242 | @@ -778,21 +802,21 @@ int ssh_set_client_kex(ssh_session session) | ||
| 243 | return SSH_OK; | ||
| 244 | } | ||
| 245 | |||
| 246 | - /* Here we append ext-info-c to the list of kex algorithms */ | ||
| 247 | + /* Here we append ext-info-c and kex-strict-c-v00@openssh.com to the list of kex algorithms */ | ||
| 248 | kex = client->methods[SSH_KEX]; | ||
| 249 | len = strlen(kex); | ||
| 250 | - if (len + strlen(KEX_EXTENSION_CLIENT) + 2 < len) { | ||
| 251 | + /* Comma, comma, nul byte */ | ||
| 252 | + kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 + strlen(KEX_STRICT_CLIENT ) + 1; | ||
| 253 | + if (kex_len >= MAX_PACKET_LEN) { | ||
| 254 | /* Overflow */ | ||
| 255 | return SSH_ERROR; | ||
| 256 | } | ||
| 257 | - kex_len = len + strlen(KEX_EXTENSION_CLIENT) + 2; /* comma, NULL */ | ||
| 258 | kex_tmp = realloc(kex, kex_len); | ||
| 259 | if (kex_tmp == NULL) { | ||
| 260 | - free(kex); | ||
| 261 | ssh_set_error_oom(session); | ||
| 262 | return SSH_ERROR; | ||
| 263 | } | ||
| 264 | - snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_EXTENSION_CLIENT); | ||
| 265 | + snprintf(kex_tmp + len, kex_len - len, ",%s,%s", KEX_EXTENSION_CLIENT, KEX_STRICT_CLIENT); | ||
| 266 | client->methods[SSH_KEX] = kex_tmp; | ||
| 267 | |||
| 268 | return SSH_OK; | ||
| 269 | diff --git a/src/packet.c b/src/packet.c | ||
| 270 | index 61a44237..8025a7ff 100644 | ||
| 271 | --- a/src/packet.c | ||
| 272 | +++ b/src/packet.c | ||
| 273 | @@ -1126,6 +1126,19 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user) | ||
| 274 | } | ||
| 275 | #endif /* WITH_ZLIB */ | ||
| 276 | payloadsize = ssh_buffer_get_len(session->in_buffer); | ||
| 277 | + if (session->recv_seq == UINT32_MAX) { | ||
| 278 | + /* Overflowing sequence numbers is always fishy */ | ||
| 279 | + if (session->current_crypto == NULL) { | ||
| 280 | + /* don't allow sequence number overflow when unencrypted */ | ||
| 281 | + ssh_set_error(session, | ||
| 282 | + SSH_FATAL, | ||
| 283 | + "Incoming sequence number overflow"); | ||
| 284 | + goto error; | ||
| 285 | + } else { | ||
| 286 | + SSH_LOG(SSH_LOG_WARNING, | ||
| 287 | + "Incoming sequence number overflow"); | ||
| 288 | + } | ||
| 289 | + } | ||
| 290 | session->recv_seq++; | ||
| 291 | if (session->raw_counter != NULL) { | ||
| 292 | session->raw_counter->in_bytes += payloadsize; | ||
| 293 | @@ -1141,7 +1154,19 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user) | ||
| 294 | SSH_LOG(SSH_LOG_PACKET, | ||
| 295 | "packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]", | ||
| 296 | session->in_packet.type, packet_len, padding, compsize, payloadsize); | ||
| 297 | - | ||
| 298 | + if (session->current_crypto == NULL) { | ||
| 299 | + /* In strict kex, only a few packets are allowed. Taint the session | ||
| 300 | + * if we received packets that are normally allowed but to be | ||
| 301 | + * refused if we are in strict kex when KEX is over. | ||
| 302 | + */ | ||
| 303 | + uint8_t type = session->in_packet.type; | ||
| 304 | + | ||
| 305 | + if (type != SSH2_MSG_KEXINIT && type != SSH2_MSG_NEWKEYS && | ||
| 306 | + (type < SSH2_MSG_KEXDH_INIT || | ||
| 307 | + type > SSH2_MSG_KEX_DH_GEX_REQUEST)) { | ||
| 308 | + session->flags |= SSH_SESSION_FLAG_KEX_TAINTED; | ||
| 309 | + } | ||
| 310 | + } | ||
| 311 | /* Check if the packet is expected */ | ||
| 312 | filter_result = ssh_packet_incoming_filter(session); | ||
| 313 | |||
| 314 | @@ -1153,6 +1178,9 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user) | ||
| 315 | case SSH_PACKET_DENIED: | ||
| 316 | goto error; | ||
| 317 | case SSH_PACKET_UNKNOWN: | ||
| 318 | + if (session->current_crypto == NULL) { | ||
| 319 | + session->flags |= SSH_SESSION_FLAG_KEX_TAINTED; | ||
| 320 | + } | ||
| 321 | ssh_packet_send_unimplemented(session, session->recv_seq - 1); | ||
| 322 | break; | ||
| 323 | } | ||
| 324 | @@ -1276,9 +1304,35 @@ void ssh_packet_process(ssh_session session, uint8_t type){ | ||
| 325 | if(r==SSH_PACKET_NOT_USED){ | ||
| 326 | SSH_LOG(SSH_LOG_RARE,"Couldn't do anything with packet type %d",type); | ||
| 327 | ssh_packet_send_unimplemented(session, session->recv_seq-1); | ||
| 328 | + if (session->current_crypto == NULL) { | ||
| 329 | + session->flags |= SSH_SESSION_FLAG_KEX_TAINTED; | ||
| 330 | + } | ||
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 334 | +/** @internal | ||
| 335 | + * @brief sends a SSH_MSG_NEWKEYS when enabling the new negotiated ciphers | ||
| 336 | + * @param session the SSH session | ||
| 337 | + * @return SSH_ERROR on error, else SSH_OK | ||
| 338 | + */ | ||
| 339 | +int ssh_packet_send_newkeys(ssh_session session) | ||
| 340 | +{ | ||
| 341 | + int rc; | ||
| 342 | + | ||
| 343 | + /* Send the MSG_NEWKEYS */ | ||
| 344 | + rc = ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS); | ||
| 345 | + if (rc < 0) { | ||
| 346 | + return rc; | ||
| 347 | + } | ||
| 348 | + | ||
| 349 | + rc = ssh_packet_send(session); | ||
| 350 | + if (rc == SSH_ERROR) { | ||
| 351 | + return rc; | ||
| 352 | + } | ||
| 353 | + SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent"); | ||
| 354 | + return rc; | ||
| 355 | +} | ||
| 356 | + | ||
| 357 | /** @internal | ||
| 358 | * @brief sends a SSH_MSG_UNIMPLEMENTED answer to an unhandled packet | ||
| 359 | * @param session the SSH session | ||
| 360 | diff --git a/src/packet_cb.c b/src/packet_cb.c | ||
| 361 | index 6aa64766..de03fb07 100644 | ||
| 362 | --- a/src/packet_cb.c | ||
| 363 | +++ b/src/packet_cb.c | ||
| 364 | @@ -154,6 +154,18 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){ | ||
| 365 | goto error; | ||
| 366 | } | ||
| 367 | |||
| 368 | + if (session->flags & SSH_SESSION_FLAG_KEX_STRICT) { | ||
| 369 | + /* reset packet sequence number when running in strict kex mode */ | ||
| 370 | + session->recv_seq = 0; | ||
| 371 | + /* Check that we aren't tainted */ | ||
| 372 | + if (session->flags & SSH_SESSION_FLAG_KEX_TAINTED) { | ||
| 373 | + ssh_set_error(session, | ||
| 374 | + SSH_FATAL, | ||
| 375 | + "Received unexpected packets in strict KEX mode."); | ||
| 376 | + goto error; | ||
| 377 | + } | ||
| 378 | +} | ||
| 379 | + | ||
| 380 | if(session->server){ | ||
| 381 | /* server things are done in server.c */ | ||
| 382 | session->dh_handshake_state=DH_STATE_FINISHED; | ||
| 383 | -- | ||
| 384 | 2.25.1 | ||
| 385 | |||
diff --git a/meta-oe/recipes-support/libssh/libssh/CVE-2023-48795-2.patch b/meta-oe/recipes-support/libssh/libssh/CVE-2023-48795-2.patch new file mode 100644 index 0000000000..fe3300503f --- /dev/null +++ b/meta-oe/recipes-support/libssh/libssh/CVE-2023-48795-2.patch | |||
| @@ -0,0 +1,126 @@ | |||
| 1 | From 0870c8db28be9eb457ee3d4f9a168959d9507efd Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Aris Adamantiadis <aris@0xbadc0de.be> | ||
| 3 | Date: Tue, 12 Dec 2023 23:30:26 +0100 | ||
| 4 | Subject: [PATCH] CVE-2023-48795: Server side mitigations | ||
| 5 | |||
| 6 | Signed-off-by: Aris Adamantiadis <aris@0xbadc0de.be> | ||
| 7 | Signed-off-by: Jakub Jelen <jjelen@redhat.com> | ||
| 8 | Reviewed-by: Andreas Schneider <asn@cryptomilk.org> | ||
| 9 | |||
| 10 | Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/0870c8db28be9eb457ee3d4f9a168959d9507efd] | ||
| 11 | CVE: CVE-2023-48795 | ||
| 12 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
| 13 | --- | ||
| 14 | include/libssh/kex.h | 1 + | ||
| 15 | src/kex.c | 46 ++++++++++++++++++++++++++++++++++---------- | ||
| 16 | src/server.c | 8 +++++++- | ||
| 17 | 3 files changed, 44 insertions(+), 11 deletions(-) | ||
| 18 | |||
| 19 | diff --git a/include/libssh/kex.h b/include/libssh/kex.h | ||
| 20 | index a626d105..2b1a74d5 100644 | ||
| 21 | --- a/include/libssh/kex.h | ||
| 22 | +++ b/include/libssh/kex.h | ||
| 23 | @@ -36,6 +36,7 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit); | ||
| 24 | int ssh_send_kex(ssh_session session, int server_kex); | ||
| 25 | void ssh_list_kex(struct ssh_kex_struct *kex); | ||
| 26 | int ssh_set_client_kex(ssh_session session); | ||
| 27 | +int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex); | ||
| 28 | int ssh_kex_select_methods(ssh_session session); | ||
| 29 | int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name); | ||
| 30 | char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list); | ||
| 31 | diff --git a/src/kex.c b/src/kex.c | ||
| 32 | index 2ed90235..b03e6484 100644 | ||
| 33 | --- a/src/kex.c | ||
| 34 | +++ b/src/kex.c | ||
| 35 | @@ -766,11 +766,8 @@ int ssh_set_client_kex(ssh_session session) | ||
| 36 | { | ||
| 37 | struct ssh_kex_struct *client= &session->next_crypto->client_kex; | ||
| 38 | const char *wanted; | ||
| 39 | - char *kex = NULL; | ||
| 40 | - char *kex_tmp = NULL; | ||
| 41 | int ok; | ||
| 42 | int i; | ||
| 43 | - size_t kex_len, len; | ||
| 44 | |||
| 45 | ok = ssh_get_random(client->cookie, 16, 0); | ||
| 46 | if (!ok) { | ||
| 47 | @@ -802,11 +799,33 @@ int ssh_set_client_kex(ssh_session session) | ||
| 48 | return SSH_OK; | ||
| 49 | } | ||
| 50 | |||
| 51 | - /* Here we append ext-info-c and kex-strict-c-v00@openssh.com to the list of kex algorithms */ | ||
| 52 | - kex = client->methods[SSH_KEX]; | ||
| 53 | + ok = ssh_kex_append_extensions(session, client); | ||
| 54 | + if (ok != SSH_OK){ | ||
| 55 | + return ok; | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + return SSH_OK; | ||
| 59 | +} | ||
| 60 | + | ||
| 61 | +int ssh_kex_append_extensions(ssh_session session, struct ssh_kex_struct *pkex) | ||
| 62 | +{ | ||
| 63 | + char *kex = NULL; | ||
| 64 | + char *kex_tmp = NULL; | ||
| 65 | + size_t kex_len, len; | ||
| 66 | + | ||
| 67 | + /* Here we append ext-info-c and kex-strict-c-v00@openssh.com for client | ||
| 68 | + * and kex-strict-s-v00@openssh.com for server to the list of kex algorithms | ||
| 69 | + */ | ||
| 70 | + kex = pkex->methods[SSH_KEX]; | ||
| 71 | len = strlen(kex); | ||
| 72 | - /* Comma, comma, nul byte */ | ||
| 73 | - kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 + strlen(KEX_STRICT_CLIENT ) + 1; | ||
| 74 | + if (session->server) { | ||
| 75 | + /* Comma, nul byte */ | ||
| 76 | + kex_len = len + 1 + strlen(KEX_STRICT_SERVER) + 1; | ||
| 77 | + } else { | ||
| 78 | + /* Comma, comma, nul byte */ | ||
| 79 | + kex_len = len + 1 + strlen(KEX_EXTENSION_CLIENT) + 1 + | ||
| 80 | + strlen(KEX_STRICT_CLIENT) + 1; | ||
| 81 | + } | ||
| 82 | if (kex_len >= MAX_PACKET_LEN) { | ||
| 83 | /* Overflow */ | ||
| 84 | return SSH_ERROR; | ||
| 85 | @@ -816,9 +835,16 @@ int ssh_set_client_kex(ssh_session session) | ||
| 86 | ssh_set_error_oom(session); | ||
| 87 | return SSH_ERROR; | ||
| 88 | } | ||
| 89 | - snprintf(kex_tmp + len, kex_len - len, ",%s,%s", KEX_EXTENSION_CLIENT, KEX_STRICT_CLIENT); | ||
| 90 | - client->methods[SSH_KEX] = kex_tmp; | ||
| 91 | - | ||
| 92 | + if (session->server){ | ||
| 93 | + snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_STRICT_SERVER); | ||
| 94 | + } else { | ||
| 95 | + snprintf(kex_tmp + len, | ||
| 96 | + kex_len - len, | ||
| 97 | + ",%s,%s", | ||
| 98 | + KEX_EXTENSION_CLIENT, | ||
| 99 | + KEX_STRICT_CLIENT); | ||
| 100 | + } | ||
| 101 | + pkex->methods[SSH_KEX] = kex_tmp; | ||
| 102 | return SSH_OK; | ||
| 103 | } | ||
| 104 | |||
| 105 | diff --git a/src/server.c b/src/server.c | ||
| 106 | index bc98da4f..f3d24a7b 100644 | ||
| 107 | --- a/src/server.c | ||
| 108 | +++ b/src/server.c | ||
| 109 | @@ -158,7 +158,13 @@ static int server_set_kex(ssh_session session) { | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | - return 0; | ||
| 114 | + /* Do not append the extensions during rekey */ | ||
| 115 | + if (session->flags & SSH_SESSION_FLAG_AUTHENTICATED) { | ||
| 116 | + return SSH_OK; | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + rc = ssh_kex_append_extensions(session, server); | ||
| 120 | + return rc; | ||
| 121 | } | ||
| 122 | |||
| 123 | int ssh_server_init_kex(ssh_session session) { | ||
| 124 | -- | ||
| 125 | 2.25.1 | ||
| 126 | |||
diff --git a/meta-oe/recipes-support/libssh/libssh/CVE-2023-48795-3.patch b/meta-oe/recipes-support/libssh/libssh/CVE-2023-48795-3.patch new file mode 100644 index 0000000000..1635a4c2dc --- /dev/null +++ b/meta-oe/recipes-support/libssh/libssh/CVE-2023-48795-3.patch | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | From 5846e57538c750c5ce67df887d09fa99861c79c6 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Jakub Jelen <jjelen@redhat.com> | ||
| 3 | Date: Thu, 14 Dec 2023 12:22:01 +0100 | ||
| 4 | Subject: [PATCH] CVE-2023-48795: Strip extensions from both kex lists for | ||
| 5 | matching | ||
| 6 | |||
| 7 | Signed-off-by: Jakub Jelen <jjelen@redhat.com> | ||
| 8 | Reviewed-by: Andreas Schneider <asn@cryptomilk.org> | ||
| 9 | |||
| 10 | Upstream-Status: Backport [https://gitlab.com/libssh/libssh-mirror/-/commit/5846e57538c750c5ce67df887d09fa99861c79c6] | ||
| 11 | CVE: CVE-2023-48795 | ||
| 12 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
| 13 | --- | ||
| 14 | src/kex.c | 16 ++++++++++++---- | ||
| 15 | 1 file changed, 12 insertions(+), 4 deletions(-) | ||
| 16 | |||
| 17 | diff --git a/src/kex.c b/src/kex.c | ||
| 18 | index b03e6484..c100d908 100644 | ||
| 19 | --- a/src/kex.c | ||
| 20 | +++ b/src/kex.c | ||
| 21 | @@ -857,11 +857,19 @@ int ssh_kex_select_methods (ssh_session session){ | ||
| 22 | char *ext_start = NULL; | ||
| 23 | int i; | ||
| 24 | |||
| 25 | - /* Here we should drop the ext-info-c from the list so we avoid matching. | ||
| 26 | + /* Here we should drop the extensions from the list so we avoid matching. | ||
| 27 | * it. We added it to the end, so we can just truncate the string here */ | ||
| 28 | - ext_start = strstr(client->methods[SSH_KEX], ","KEX_EXTENSION_CLIENT); | ||
| 29 | - if (ext_start != NULL) { | ||
| 30 | - ext_start[0] = '\0'; | ||
| 31 | + if (session->client) { | ||
| 32 | + ext_start = strstr(client->methods[SSH_KEX], "," KEX_EXTENSION_CLIENT); | ||
| 33 | + if (ext_start != NULL) { | ||
| 34 | + ext_start[0] = '\0'; | ||
| 35 | + } | ||
| 36 | + } | ||
| 37 | + if (session->server) { | ||
| 38 | + ext_start = strstr(server->methods[SSH_KEX], "," KEX_STRICT_SERVER); | ||
| 39 | + if (ext_start != NULL) { | ||
| 40 | + ext_start[0] = '\0'; | ||
| 41 | + } | ||
| 42 | } | ||
| 43 | |||
| 44 | for (i = 0; i < KEX_METHODS_SIZE; i++) { | ||
| 45 | -- | ||
| 46 | 2.25.1 | ||
| 47 | |||
diff --git a/meta-oe/recipes-support/libssh/libssh_0.8.9.bb b/meta-oe/recipes-support/libssh/libssh_0.8.9.bb index 061f13912f..530dda1f4a 100644 --- a/meta-oe/recipes-support/libssh/libssh_0.8.9.bb +++ b/meta-oe/recipes-support/libssh/libssh_0.8.9.bb | |||
| @@ -8,6 +8,9 @@ DEPENDS = "zlib openssl" | |||
| 8 | 8 | ||
| 9 | SRC_URI = "git://git.libssh.org/projects/libssh.git;protocol=https;branch=stable-0.8 \ | 9 | SRC_URI = "git://git.libssh.org/projects/libssh.git;protocol=https;branch=stable-0.8 \ |
| 10 | file://CVE-2020-16135.patch \ | 10 | file://CVE-2020-16135.patch \ |
| 11 | file://CVE-2023-48795-1.patch \ | ||
| 12 | file://CVE-2023-48795-2.patch \ | ||
| 13 | file://CVE-2023-48795-3.patch \ | ||
| 11 | " | 14 | " |
| 12 | SRCREV = "04685a74df9ce1db1bc116a83a0da78b4f4fa1f8" | 15 | SRCREV = "04685a74df9ce1db1bc116a83a0da78b4f4fa1f8" |
| 13 | 16 | ||
