Package: release.debian.org Severity: normal Tags: bullseye User: release.debian....@packages.debian.org Usertags: pu X-Debbugs-Cc: open...@packages.debian.org Control: affects -1 + src:openssh
[ Reason ] https://bugs.debian.org/1042460 is a security issue affecting bullseye. 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. [ Risks ] The code isn't quite trivial, but it's fairly straightforward once you understand what it's doing. The second 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. I wasn't able to backport the other part of upstream's fix for this (disallowing remote addition of FIDO/PKCS#11 keys by default), because that relies on the mechanism in https://www.openssh.com/agent-restrict.html and bullseye doesn't have that. [ 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) [cjwat...@debian.org]
diff -Nru openssh-8.4p1/debian/.git-dpm openssh-8.4p1/debian/.git-dpm --- openssh-8.4p1/debian/.git-dpm 2022-07-01 23:37:41.000000000 +0100 +++ openssh-8.4p1/debian/.git-dpm 2023-09-17 23:46:46.000000000 +0100 @@ -1,6 +1,6 @@ # see git-dpm(1) from git-dpm package -ed99ef256258d8556dbe39d976c2528ede050f14 -ed99ef256258d8556dbe39d976c2528ede050f14 +fb685ebb9f8391ab2836715c9c347ee50a0c9f48 +fb685ebb9f8391ab2836715c9c347ee50a0c9f48 2b2c99658e3e8ed452e28f88f9cdbcdfb2a461cb 2b2c99658e3e8ed452e28f88f9cdbcdfb2a461cb openssh_8.4p1.orig.tar.gz diff -Nru openssh-8.4p1/debian/changelog openssh-8.4p1/debian/changelog --- openssh-8.4p1/debian/changelog 2022-07-01 23:37:41.000000000 +0100 +++ openssh-8.4p1/debian/changelog 2023-09-17 23:46:46.000000000 +0100 @@ -1,3 +1,12 @@ +openssh (1:8.4p1-5+deb11u2) bullseye; 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 <cjwat...@debian.org> Sun, 17 Sep 2023 23:46:46 +0100 + openssh (1:8.4p1-5+deb11u1) bullseye; urgency=medium * Backport from upstream: diff -Nru openssh-8.4p1/debian/patches/CVE-2023-38408-1.patch openssh-8.4p1/debian/patches/CVE-2023-38408-1.patch --- openssh-8.4p1/debian/patches/CVE-2023-38408-1.patch 1970-01-01 01:00:00.000000000 +0100 +++ openssh-8.4p1/debian/patches/CVE-2023-38408-1.patch 2023-09-17 23:46:46.000000000 +0100 @@ -0,0 +1,30 @@ +From 8175e38eaf5636f45c3f27f4eadee1d583b70d35 Mon Sep 17 00:00:00 2001 +From: Damien Miller <d...@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 f495883d1..d864051c4 100644 +--- a/ssh-pkcs11.c ++++ b/ssh-pkcs11.c +@@ -1519,10 +1519,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-8.4p1/debian/patches/CVE-2023-38408-2.patch openssh-8.4p1/debian/patches/CVE-2023-38408-2.patch --- openssh-8.4p1/debian/patches/CVE-2023-38408-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ openssh-8.4p1/debian/patches/CVE-2023-38408-2.patch 2023-09-17 23:46:46.000000000 +0100 @@ -0,0 +1,171 @@ +From fb685ebb9f8391ab2836715c9c347ee50a0c9f48 Mon Sep 17 00:00:00 2001 +From: "d...@openbsd.org" <d...@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: backport, https://anongit.mindrot.org/openssh.git/commit/?id=29ef8a04866ca14688d5b7fed7b8b9deab851f77 +Last-Update: 2023-09-17 + +Patch-Name: CVE-2023-38408-2.patch +--- + misc.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + misc.h | 1 + + ssh-pkcs11.c | 4 +++ + ssh-sk.c | 6 ++-- + 4 files changed, 88 insertions(+), 2 deletions(-) + +diff --git a/misc.c b/misc.c +index c75a795c2..c6e9e71a3 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> +@@ -2463,3 +2467,78 @@ ssh_signal(int signum, sshsig_t handler) + } + return osa.sa_handler; + } ++ ++/* ++ * 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("%s: nlist failed for %s", __func__, path); ++ goto out; ++ } ++ if (r != 0 || nl[0].n_value == 0 || nl[0].n_type == 0) { ++ error("%s: library %s does not contain symbol %s", ++ __func__, 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("%s: open %s: %s", __func__, path, strerror(errno)); ++ return -1; ++ } ++ if (fstat(fd, &st) != 0) { ++ error("%s: fstat %s: %s", __func__, path, strerror(errno)); ++ goto out; ++ } ++ if (!S_ISREG(st.st_mode)) { ++ error("%s: %s is not a regular file", __func__, path); ++ goto out; ++ } ++ if (st.st_size < 0 || ++ (size_t)st.st_size < strlen(s) || ++ st.st_size >= INT_MAX/2) { ++ error("%s: %s bad size %lld", ++ __func__, 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("%s: mmap %s: %s", __func__, path, strerror(errno)); ++ goto out; ++ } ++ if (memmem(m, sz, s, strlen(s)) == NULL) { ++ error("%s: %s does not contain expected string %s", ++ __func__, 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 b34c798e7..eb30bb454 100644 +--- a/misc.h ++++ b/misc.h +@@ -90,6 +90,7 @@ const char *atoi_err(const char *, int *); + int parse_absolute_time(const char *, uint64_t *); + void format_absolute_time(uint64_t, char *, size_t); + int path_absolute(const char *); ++int lib_contains_symbol(const char *, const char *); + + void sock_set_v6only(int); + +diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c +index d864051c4..df4d53626 100644 +--- a/ssh-pkcs11.c ++++ b/ssh-pkcs11.c +@@ -1514,6 +1514,10 @@ pkcs11_register_provider(char *provider_id, char *pin, + __func__, 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 1455df635..76fee8af2 100644 +--- a/ssh-sk.c ++++ b/ssh-sk.c +@@ -123,10 +123,12 @@ sshsk_open(const char *path) + #endif + return ret; + } +- 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-8.4p1/debian/patches/series openssh-8.4p1/debian/patches/series --- openssh-8.4p1/debian/patches/series 2022-07-01 23:37:41.000000000 +0100 +++ openssh-8.4p1/debian/patches/series 2023-09-17 23:46:46.000000000 +0100 @@ -27,3 +27,5 @@ ssh-copy-id-heredoc-syntax.patch ssh-agent-double-free.patch sandbox-pselect6_time64.patch +CVE-2023-38408-1.patch +CVE-2023-38408-2.patch