From a55ed6b67033dace401dc42c312d7b3c0ec740a3 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 5 Aug 2025 18:42:31 +0200 Subject: [PATCH 1/3] CVE-2025-8277: packet: Adjust packet filter to work when DH-GEX is guessed wrongly Signed-off-by: Jakub Jelen Reviewed-by: Andreas Schneider (cherry picked from commit 4310a696f2d632c6742678077d703d9b9ff3bc0e) --- src/packet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/packet.c b/src/packet.c index 891d120c..af9a55da 100644 --- a/src/packet.c +++ b/src/packet.c @@ -294,6 +294,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se * or session_state == SSH_SESSION_STATE_INITIAL_KEX * - dh_handshake_state == DH_STATE_INIT * or dh_handshake_state == DH_STATE_INIT_SENT (re-exchange) + * or dh_handshake_state == DH_STATE_REQUEST_SENT (dh-gex) * or dh_handshake_state == DH_STATE_FINISHED (re-exchange) * * Transitions: @@ -313,6 +314,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se if ((session->dh_handshake_state != DH_STATE_INIT) && (session->dh_handshake_state != DH_STATE_INIT_SENT) && + (session->dh_handshake_state != DH_STATE_REQUEST_SENT) && (session->dh_handshake_state != DH_STATE_FINISHED)) { rc = SSH_PACKET_DENIED; -- 2.53.0 From 00bdcdc96ca6e367a2a2dd05ff56ca9e6e516f45 Mon Sep 17 00:00:00 2001 From: Francesco Rollo Date: Thu, 24 Jul 2025 16:30:07 +0300 Subject: [PATCH 2/3] CVE-2025-8277: Fix memory leak of unused ephemeral key pair after client's wrong KEX guess Signed-off-by: Francesco Rollo Reviewed-by: Andreas Schneider (cherry picked from commit ccff22d3787c1355b3f0dcd09fe54d90acc55bf1) --- src/dh_crypto.c | 5 +++++ src/dh_key.c | 5 +++++ src/ecdh_crypto.c | 5 +++++ src/ecdh_gcrypt.c | 6 ++++++ src/ecdh_mbedcrypto.c | 6 ++++++ 5 files changed, 27 insertions(+) diff --git a/src/dh_crypto.c b/src/dh_crypto.c index 85249bfc..60f35912 100644 --- a/src/dh_crypto.c +++ b/src/dh_crypto.c @@ -407,6 +407,11 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto) struct dh_ctx *ctx = NULL; int rc; + /* Cleanup any previously allocated dh_ctx */ + if (crypto->dh_ctx != NULL) { + ssh_dh_cleanup(crypto); + } + ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { return SSH_ERROR; diff --git a/src/dh_key.c b/src/dh_key.c index bda54b17..637b1b44 100644 --- a/src/dh_key.c +++ b/src/dh_key.c @@ -237,6 +237,11 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto) struct dh_ctx *ctx = NULL; int rc; + /* Cleanup any previously allocated dh_ctx */ + if (crypto->dh_ctx != NULL) { + ssh_dh_cleanup(crypto); + } + ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { return SSH_ERROR; diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c index 178d9060..c61b6ce4 100644 --- a/src/ecdh_crypto.c +++ b/src/ecdh_crypto.c @@ -219,6 +219,11 @@ int ssh_client_ecdh_init(ssh_session session){ return SSH_ERROR; } + if (session->next_crypto->ecdh_privkey != NULL) { + EC_KEY_free(session->next_crypto->ecdh_privkey); + session->next_crypto->ecdh_privkey = NULL; + } + session->next_crypto->ecdh_privkey = key; session->next_crypto->ecdh_client_pubkey = client_pubkey; diff --git a/src/ecdh_gcrypt.c b/src/ecdh_gcrypt.c index 722428c2..f49e8eb2 100644 --- a/src/ecdh_gcrypt.c +++ b/src/ecdh_gcrypt.c @@ -101,6 +101,12 @@ int ssh_client_ecdh_init(ssh_session session) goto out; } + /* Free any previously allocated privkey */ + if (session->next_crypto->ecdh_privkey != NULL) { + gcry_sexp_release(session->next_crypto->ecdh_privkey); + session->next_crypto->ecdh_privkey = NULL; + } + session->next_crypto->ecdh_privkey = key; key = NULL; session->next_crypto->ecdh_client_pubkey = client_pubkey; diff --git a/src/ecdh_mbedcrypto.c b/src/ecdh_mbedcrypto.c index 1d9c8f36..d31bfcc7 100644 --- a/src/ecdh_mbedcrypto.c +++ b/src/ecdh_mbedcrypto.c @@ -70,6 +70,12 @@ int ssh_client_ecdh_init(ssh_session session) return SSH_ERROR; } + /* Free any previously allocated privkey */ + if (session->next_crypto->ecdh_privkey != NULL) { + mbedtls_ecp_keypair_free(session->next_crypto->ecdh_privkey); + SAFE_FREE(session->next_crypto->ecdh_privkey); + } + session->next_crypto->ecdh_privkey = malloc(sizeof(mbedtls_ecp_keypair)); if (session->next_crypto->ecdh_privkey == NULL) { return SSH_ERROR; -- 2.53.0 From 2bdddb2bd34cdd563de9227d74c5a21784c03d3d Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 6 Aug 2025 11:10:38 +0200 Subject: [PATCH 3/3] CVE-2025-8277: ecdh: Free previously allocated pubkeys Signed-off-by: Jakub Jelen Reviewed-by: Andreas Schneider (cherry picked from commit c9d95ab0c7a52b231bcec09afbea71944ed0d852) --- src/ecdh_crypto.c | 1 + src/ecdh_gcrypt.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ecdh_crypto.c b/src/ecdh_crypto.c index c61b6ce4..5694b083 100644 --- a/src/ecdh_crypto.c +++ b/src/ecdh_crypto.c @@ -223,6 +223,7 @@ int ssh_client_ecdh_init(ssh_session session){ EC_KEY_free(session->next_crypto->ecdh_privkey); session->next_crypto->ecdh_privkey = NULL; } + SSH_STRING_FREE(session->next_crypto->ecdh_client_pubkey); session->next_crypto->ecdh_privkey = key; session->next_crypto->ecdh_client_pubkey = client_pubkey; diff --git a/src/ecdh_gcrypt.c b/src/ecdh_gcrypt.c index f49e8eb2..ee5350cd 100644 --- a/src/ecdh_gcrypt.c +++ b/src/ecdh_gcrypt.c @@ -106,9 +106,10 @@ int ssh_client_ecdh_init(ssh_session session) gcry_sexp_release(session->next_crypto->ecdh_privkey); session->next_crypto->ecdh_privkey = NULL; } - session->next_crypto->ecdh_privkey = key; key = NULL; + + SSH_STRING_FREE(session->next_crypto->ecdh_client_pubkey); session->next_crypto->ecdh_client_pubkey = client_pubkey; client_pubkey = NULL; -- 2.53.0