CVE-2023-25136 (published 2023-02-03T06:15Z)

OpenSSH server (sshd) 9.1 introduced a double-free vulnerability during options.kex_algorithms handling. This is fixed in OpenSSH 9.2. The double free can be leveraged, by an unauthenticated remote attacker in the default configuration, to jump to any location in the sshd address space. One third-party report states "remote code execution is theoretically possible."

CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:H)

Weakness information:
cwe_id: CWE-415
cwe_name: Double Free
description: The product calls free() twice on the same memory address, potentially leading to modification of unexpected memory locations.
extended_description: When a program calls free() twice with the same argument, the program's memory management data structures become corrupted. This corruption can cause the program to crash or, in some circumstances, cause two later calls to malloc() to return the same pointer. If malloc() returns the same value twice and the program later gives the attacker control over the data that is written into this doubly-allocated memory, the program becomes vulnerable to a buffer overflow attack.
         

Fix information:
repo_url: https://github.com/openssh/openssh-portable
commit_details: repo_url: https://github.com/openssh/openssh-portable
author: dtucker@openbsd.org
author_date: 2022-07-01 03:35:45+00:00
msg: upstream: Always return allocated strings from the kex filtering so

that we can free them later.  Fix one leak in compat_kex_proposal.  Based on
github PR#324 from ZoltanFridrich with some simplications by me. ok djm@

OpenBSD-Commit-ID: 9171616da3307612d0ede086fd511142f91246e4
repository: repo_url: https://github.com/openssh/openssh-portable
repo_name: openssh/openssh-portable
description: Portable OpenSSH
repo_language: C
owner: openssh
file_changes: filename: compat.c
change_type: ModificationType.MODIFY
diff: @@ -1,4 +1,4 @@
-/* $OpenBSD: compat.c,v 1.119 2021/09/10 05:46:09 djm Exp $ */
+/* $OpenBSD: compat.c,v 1.120 2022/07/01 03:35:45 dtucker Exp $ */
 /*
  * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl.  All rights reserved.
  *
@@ -156,11 +156,12 @@ compat_banner(struct ssh *ssh, const char *version)
 	debug_f("no match: %s", version);
 }
 
+/* Always returns pointer to allocated memory, caller must free. */
 char *
 compat_cipher_proposal(struct ssh *ssh, char *cipher_prop)
 {
 	if (!(ssh->compat & SSH_BUG_BIGENDIANAES))
-		return cipher_prop;
+		return xstrdup(cipher_prop);
 	debug2_f("original cipher proposal: %s", cipher_prop);
 	if ((cipher_prop = match_filter_denylist(cipher_prop, "aes*")) == NULL)
 		fatal("match_filter_denylist failed");
@@ -170,11 +171,12 @@ compat_cipher_proposal(struct ssh *ssh, char *cipher_prop)
 	return cipher_prop;
 }
 
+/* Always returns pointer to allocated memory, caller must free. */
 char *
 compat_pkalg_proposal(struct ssh *ssh, char *pkalg_prop)
 {
 	if (!(ssh->compat & SSH_BUG_RSASIGMD5))
-		return pkalg_prop;
+		return xstrdup(pkalg_prop);
 	debug2_f("original public key proposal: %s", pkalg_prop);
 	if ((pkalg_prop = match_filter_denylist(pkalg_prop, "ssh-rsa")) == NULL)
 		fatal("match_filter_denylist failed");
@@ -184,21 +186,26 @@ compat_pkalg_proposal(struct ssh *ssh, char *pkalg_prop)
 	return pkalg_prop;
 }
 
+/* Always returns pointer to allocated memory, caller must free. */
 char *
 compat_kex_proposal(struct ssh *ssh, char *p)
 {
+	char *cp = NULL;
+
 	if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0)
-		return p;
+		return xstrdup(p);
 	debug2_f("original KEX proposal: %s", p);
 	if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0)
 		if ((p = match_filter_denylist(p,
 		    "curve25519-sha256@libssh.org")) == NULL)
 			fatal("match_filter_denylist failed");
 	if ((ssh->compat & SSH_OLD_DHGEX) != 0) {
+		cp = p;
 		if ((p = match_filter_denylist(p,
 		    "diffie-hellman-group-exchange-sha256,"
 		    "diffie-hellman-group-exchange-sha1")) == NULL)
 			fatal("match_filter_denylist failed");
+		free(cp);
 	}
 	debug2_f("compat KEX proposal: %s", p);
 	if (*p == '\0')

programming_language: C