[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1052149: bookworm-pu: package openssh/1:9.2p1-2+deb12u1



Package: release.debian.org
Severity: normal
Tags: bookworm
User: release.debian.org@packages.debian.org
Usertags: pu
X-Debbugs-Cc: openssh@packages.debian.org
Control: affects -1 + src:openssh

[ Reason ]
https://bugs.debian.org/1042460 is a security issue affecting bookworm.
The security team doesn't think it warrants a DSA, but thinks it's worth
fixing in a point release.  I agree.

[ Impact ]
Forwarding an SSH agent to a remote system may be exploitable by
administrators of that remote system in complicated conditions.  See
https://www.qualys.com/2023/07/19/cve-2023-38408/rce-openssh-forwarded-ssh-agent.txt.

[ Tests ]
I have tested this manually as far as I'm able to do so.  Essentially,
this shuts down the exploit at the first hurdle by refusing to load
objects that don't appear to be valid FIDO/PKCS#11 modules intended for
use by ssh-agent, and by disallowing remote addition of FIDO/PKCS#11
keys by default.

[ Risks ]
The code isn't quite trivial, but it's fairly straightforward once you
understand what it's doing.

The third upstream patch in the series wasn't in OpenSSH 9.3p2 (the
initial upstream release addressing this vulnerability), but I think
it's worth taking anyway because it shuts down a range of clever attacks
along these same lines without introducing an unreasonable amount of
extra complexity.  Ubuntu did the same thing in their security updates
for this.

[ Checklist ]
  [X] *all* changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in (old)stable
  [X] the issue is verified as fixed in unstable

[ Changes ]
See attached debdiff.

Thanks,

-- 
Colin Watson (he/him)                              [cjwatson@debian.org]
diff -Nru openssh-9.2p1/debian/.git-dpm openssh-9.2p1/debian/.git-dpm
--- openssh-9.2p1/debian/.git-dpm	2023-02-08 10:43:07.000000000 +0000
+++ openssh-9.2p1/debian/.git-dpm	2023-09-17 21:23:50.000000000 +0100
@@ -1,6 +1,6 @@
 # see git-dpm(1) from git-dpm package
-74edce484429249265baaee1e8a5d1785ee7afa7
-74edce484429249265baaee1e8a5d1785ee7afa7
+29c7785a3673101b3af8f6f712795fa128e52ddd
+29c7785a3673101b3af8f6f712795fa128e52ddd
 cf3c3acb2b8f74eeca7fcee269b1d33ac83f1188
 cf3c3acb2b8f74eeca7fcee269b1d33ac83f1188
 openssh_9.2p1.orig.tar.gz
diff -Nru openssh-9.2p1/debian/changelog openssh-9.2p1/debian/changelog
--- openssh-9.2p1/debian/changelog	2023-02-08 10:43:07.000000000 +0000
+++ openssh-9.2p1/debian/changelog	2023-09-17 21:23:50.000000000 +0100
@@ -1,3 +1,12 @@
+openssh (1:9.2p1-2+deb12u1) UNRELEASED; urgency=medium
+
+  * Cherry-pick from OpenSSH 9.3p2:
+    - [CVE-2023-38408] Fix a condition where specific libraries loaded via
+      ssh-agent(1)'s PKCS#11 support could be abused to achieve remote code
+      execution via a forwarded agent socket (closes: #1042460).
+
+ -- Colin Watson <cjwatson@debian.org>  Sun, 17 Sep 2023 21:23:50 +0100
+
 openssh (1:9.2p1-2) unstable; urgency=medium
 
   * Fix mistakenly-unreleased entry for 1:9.2p1-1 in debian/NEWS.
diff -Nru openssh-9.2p1/debian/patches/CVE-2023-38408-1.patch openssh-9.2p1/debian/patches/CVE-2023-38408-1.patch
--- openssh-9.2p1/debian/patches/CVE-2023-38408-1.patch	1970-01-01 01:00:00.000000000 +0100
+++ openssh-9.2p1/debian/patches/CVE-2023-38408-1.patch	2023-09-17 21:23:50.000000000 +0100
@@ -0,0 +1,30 @@
+From dee3878689aef5365955442869be02d420b65ea6 Mon Sep 17 00:00:00 2001
+From: Damien Miller <djm@mindrot.org>
+Date: Thu, 13 Jul 2023 12:09:34 +1000
+Subject: terminate pkcs11 process for bad libraries
+
+Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=b23fe83f06ee7e721033769cfa03ae840476d280
+Last-Update: 2023-09-17
+
+Patch-Name: CVE-2023-38408-1.patch
+---
+ ssh-pkcs11.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
+index b2e2b32a5..9e48c134e 100644
+--- a/ssh-pkcs11.c
++++ b/ssh-pkcs11.c
+@@ -1537,10 +1537,8 @@ pkcs11_register_provider(char *provider_id, char *pin,
+ 		error("dlopen %s failed: %s", provider_id, dlerror());
+ 		goto fail;
+ 	}
+-	if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) {
+-		error("dlsym(C_GetFunctionList) failed: %s", dlerror());
+-		goto fail;
+-	}
++	if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL)
++		fatal("dlsym(C_GetFunctionList) failed: %s", dlerror());
+ 	p = xcalloc(1, sizeof(*p));
+ 	p->name = xstrdup(provider_id);
+ 	p->handle = handle;
diff -Nru openssh-9.2p1/debian/patches/CVE-2023-38408-2.patch openssh-9.2p1/debian/patches/CVE-2023-38408-2.patch
--- openssh-9.2p1/debian/patches/CVE-2023-38408-2.patch	1970-01-01 01:00:00.000000000 +0100
+++ openssh-9.2p1/debian/patches/CVE-2023-38408-2.patch	2023-09-17 21:23:50.000000000 +0100
@@ -0,0 +1,104 @@
+From 5c06b89189eb27f692b900526d60bf744918511e Mon Sep 17 00:00:00 2001
+From: Damien Miller <djm@mindrot.org>
+Date: Fri, 7 Jul 2023 13:30:15 +1000
+Subject: disallow remote addition of FIDO/PKCS11 keys
+
+Depends on the local client performing the session-bind@openssh.com
+operation, so non-OpenSSH local client may circumvent this.
+
+Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=d7790cdce72a1b6982795baa2b4d6f0bdbb0100d
+Last-Update: 2023-09-17
+
+Patch-Name: CVE-2023-38408-2.patch
+---
+ ssh-agent.1 | 22 ++++++++++++++++++++--
+ ssh-agent.c | 21 ++++++++++++++++++++-
+ 2 files changed, 40 insertions(+), 3 deletions(-)
+
+diff --git a/ssh-agent.1 b/ssh-agent.1
+index ba418bb41..0e5b6c15c 100644
+--- a/ssh-agent.1
++++ b/ssh-agent.1
+@@ -107,9 +107,27 @@ environment variable).
+ .It Fl O Ar option
+ Specify an option when starting
+ .Nm .
+-Currently only one option is supported:
++Currently two options are supported:
++.Cm allow-remote-pkcs11
++and
+ .Cm no-restrict-websafe .
+-This instructs
++.Pp
++The
++.Cm allow-remote-pkcs11
++option allows clients of a forwarded
++.Nm
++to load PKCS#11 or FIDO provider libraries.
++By default only local clients may perform this operation.
++Note that signalling that a
++.Nm
++client remote is performed by
++.Xr ssh 1 ,
++and use of other tools to forward access to the agent socket may circumvent
++this restriction.
++.Pp
++The
++.Cm no-restrict-websafe ,
++instructs
+ .Nm
+ to permit signatures using FIDO keys that might be web authentication
+ requests.
+diff --git a/ssh-agent.c b/ssh-agent.c
+index 63e1137bc..dce2849d8 100644
+--- a/ssh-agent.c
++++ b/ssh-agent.c
+@@ -170,6 +170,12 @@ char socket_dir[PATH_MAX];
+ /* Pattern-list of allowed PKCS#11/Security key paths */
+ static char *allowed_providers;
+ 
++/*
++ * Allows PKCS11 providers or SK keys that use non-internal providers to
++ * be added over a remote connection (identified by session-bind@openssh.com).
++ */
++static int remote_add_provider;
++
+ /* locking */
+ #define LOCK_SIZE	32
+ #define LOCK_SALT_SIZE	16
+@@ -1229,6 +1235,12 @@ process_add_identity(SocketEntry *e)
+ 		if (strcasecmp(sk_provider, "internal") == 0) {
+ 			debug_f("internal provider");
+ 		} else {
++			if (e->nsession_ids != 0 && !remote_add_provider) {
++				verbose("failed add of SK provider \"%.100s\": "
++				    "remote addition of providers is disabled",
++				    sk_provider);
++				goto out;
++			}
+ 			if (realpath(sk_provider, canonical_provider) == NULL) {
+ 				verbose("failed provider \"%.100s\": "
+ 				    "realpath: %s", sk_provider,
+@@ -1392,6 +1404,11 @@ process_add_smartcard_key(SocketEntry *e)
+ 		error_f("failed to parse constraints");
+ 		goto send;
+ 	}
++	if (e->nsession_ids != 0 && !remote_add_provider) {
++		verbose("failed PKCS#11 add of \"%.100s\": remote addition of "
++		    "providers is disabled", provider);
++		goto send;
++	}
+ 	if (realpath(provider, canonical_provider) == NULL) {
+ 		verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
+ 		    provider, strerror(errno));
+@@ -2052,7 +2069,9 @@ main(int ac, char **av)
+ 			break;
+ 		case 'O':
+ 			if (strcmp(optarg, "no-restrict-websafe") == 0)
+-				restrict_websafe  = 0;
++				restrict_websafe = 0;
++			else if (strcmp(optarg, "allow-remote-pkcs11") == 0)
++				remote_add_provider = 1;
+ 			else
+ 				fatal("Unknown -O option");
+ 			break;
diff -Nru openssh-9.2p1/debian/patches/CVE-2023-38408-3.patch openssh-9.2p1/debian/patches/CVE-2023-38408-3.patch
--- openssh-9.2p1/debian/patches/CVE-2023-38408-3.patch	1970-01-01 01:00:00.000000000 +0100
+++ openssh-9.2p1/debian/patches/CVE-2023-38408-3.patch	2023-09-17 21:23:50.000000000 +0100
@@ -0,0 +1,174 @@
+From 29c7785a3673101b3af8f6f712795fa128e52ddd Mon Sep 17 00:00:00 2001
+From: "djm@openbsd.org" <djm@openbsd.org>
+Date: Wed, 19 Jul 2023 14:02:27 +0000
+Subject: upstream: Ensure FIDO/PKCS11 libraries contain expected symbols
+
+This checks via nlist(3) that candidate provider libraries contain one
+of the symbols that we will require prior to dlopen(), which can cause
+a number of side effects, including execution of constructors.
+
+Feedback deraadt; ok markus
+
+OpenBSD-Commit-ID: 1508a5fbd74e329e69a55b56c453c292029aefbe
+
+Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=29ef8a04866ca14688d5b7fed7b8b9deab851f77
+Last-Update: 2023-09-17
+
+Patch-Name: CVE-2023-38408-3.patch
+---
+ misc.c       | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ misc.h       |  1 +
+ ssh-pkcs11.c |  4 +++
+ ssh-sk.c     |  8 +++---
+ 4 files changed, 86 insertions(+), 3 deletions(-)
+
+diff --git a/misc.c b/misc.c
+index 2268d8875..36e72f5b5 100644
+--- a/misc.c
++++ b/misc.c
+@@ -22,6 +22,7 @@
+ 
+ #include <sys/types.h>
+ #include <sys/ioctl.h>
++#include <sys/mman.h>
+ #include <sys/socket.h>
+ #include <sys/stat.h>
+ #include <sys/time.h>
+@@ -35,6 +36,9 @@
+ #ifdef HAVE_POLL_H
+ #include <poll.h>
+ #endif
++#ifdef HAVE_NLIST_H
++#include <nlist.h>
++#endif
+ #include <signal.h>
+ #include <stdarg.h>
+ #include <stdio.h>
+@@ -2962,3 +2966,75 @@ ptimeout_isset(struct timespec *pt)
+ {
+ 	return pt->tv_sec != -1;
+ }
++
++/*
++ * Returns zero if the library at 'path' contains symbol 's', nonzero
++ * otherwise.
++ */
++int
++lib_contains_symbol(const char *path, const char *s)
++{
++#ifdef HAVE_NLIST_H
++	struct nlist nl[2];
++	int ret = -1, r;
++
++	memset(nl, 0, sizeof(nl));
++	nl[0].n_name = xstrdup(s);
++	nl[1].n_name = NULL;
++	if ((r = nlist(path, nl)) == -1) {
++		error_f("nlist failed for %s", path);
++		goto out;
++	}
++	if (r != 0 || nl[0].n_value == 0 || nl[0].n_type == 0) {
++		error_f("library %s does not contain symbol %s", path, s);
++		goto out;
++	}
++	/* success */
++	ret = 0;
++ out:
++	free(nl[0].n_name);
++	return ret;
++#else /* HAVE_NLIST_H */
++	int fd, ret = -1;
++	struct stat st;
++	void *m = NULL;
++	size_t sz = 0;
++
++	memset(&st, 0, sizeof(st));
++	if ((fd = open(path, O_RDONLY)) < 0) {
++		error_f("open %s: %s", path, strerror(errno));
++		return -1;
++	}
++	if (fstat(fd, &st) != 0) {
++		error_f("fstat %s: %s", path, strerror(errno));
++		goto out;
++	}
++	if (!S_ISREG(st.st_mode)) {
++		error_f("%s is not a regular file", path);
++		goto out;
++	}
++	if (st.st_size < 0 ||
++	    (size_t)st.st_size < strlen(s) ||
++	    st.st_size >= INT_MAX/2) {
++		error_f("%s bad size %lld", path, (long long)st.st_size);
++		goto out;
++	}
++	sz = (size_t)st.st_size;
++	if ((m = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED ||
++	    m == NULL) {
++		error_f("mmap %s: %s", path, strerror(errno));
++		goto out;
++	}
++	if (memmem(m, sz, s, strlen(s)) == NULL) {
++		error_f("%s does not contain expected string %s", path, s);
++		goto out;
++	}
++	/* success */
++	ret = 0;
++ out:
++	if (m != NULL && m != MAP_FAILED)
++		munmap(m, sz);
++	close(fd);
++	return ret;
++#endif /* HAVE_NLIST_H */
++}
+diff --git a/misc.h b/misc.h
+index 31b6557c6..1a49e7cec 100644
+--- a/misc.h
++++ b/misc.h
+@@ -96,6 +96,7 @@ int	 parse_absolute_time(const char *, uint64_t *);
+ void	 format_absolute_time(uint64_t, char *, size_t);
+ int	 path_absolute(const char *);
+ int	 stdfd_devnull(int, int, int);
++int	 lib_contains_symbol(const char *, const char *);
+ 
+ void	 sock_set_v6only(int);
+ 
+diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
+index 9e48c134e..0aef37934 100644
+--- a/ssh-pkcs11.c
++++ b/ssh-pkcs11.c
+@@ -1532,6 +1532,10 @@ pkcs11_register_provider(char *provider_id, char *pin,
+ 		debug_f("provider already registered: %s", provider_id);
+ 		goto fail;
+ 	}
++	if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) {
++		error("provider %s is not a PKCS11 library", provider_id);
++		goto fail;
++	}
+ 	/* open shared pkcs11-library */
+ 	if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
+ 		error("dlopen %s failed: %s", provider_id, dlerror());
+diff --git a/ssh-sk.c b/ssh-sk.c
+index fbeb39320..d1c18803f 100644
+--- a/ssh-sk.c
++++ b/ssh-sk.c
+@@ -1,4 +1,4 @@
+-/* $OpenBSD: ssh-sk.c,v 1.39 2022/07/20 03:29:14 djm Exp $ */
++/* $OpenBSD: ssh-sk.c,v 1.40 2023/07/19 14:02:27 djm Exp $ */
+ /*
+  * Copyright (c) 2019 Google LLC
+  *
+@@ -133,10 +133,12 @@ sshsk_open(const char *path)
+ 		goto fail;
+ #endif
+ 	}
+-	if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL) {
+-		error("Provider \"%s\" dlopen failed: %s", path, dlerror());
++	if (lib_contains_symbol(path, "sk_api_version") != 0) {
++		error("provider %s is not an OpenSSH FIDO library", path);
+ 		goto fail;
+ 	}
++	if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL)
++		fatal("Provider \"%s\" dlopen failed: %s", path, dlerror());
+ 	if ((ret->sk_api_version = dlsym(ret->dlhandle,
+ 	    "sk_api_version")) == NULL) {
+ 		error("Provider \"%s\" dlsym(sk_api_version) failed: %s",
diff -Nru openssh-9.2p1/debian/patches/series openssh-9.2p1/debian/patches/series
--- openssh-9.2p1/debian/patches/series	2023-02-08 10:43:07.000000000 +0000
+++ openssh-9.2p1/debian/patches/series	2023-09-17 21:23:50.000000000 +0100
@@ -26,3 +26,6 @@
 conch-ssh-rsa.patch
 systemd-socket-activation.patch
 remove-spurious-ssh-agent-options.patch
+CVE-2023-38408-1.patch
+CVE-2023-38408-2.patch
+CVE-2023-38408-3.patch

Reply to: