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

Reply via email to