diff -Nru open-vm-tools-12.1.5/debian/changelog open-vm-tools-12.1.5/debian/changelog --- open-vm-tools-12.1.5/debian/changelog 2023-09-11 18:45:11.000000000 +0000 +++ open-vm-tools-12.1.5/debian/changelog 2023-10-27 11:37:42.000000000 +0000 @@ -1,3 +1,20 @@ +open-vm-tools (2:12.1.5-3ubuntu0.23.04.3) lunar-security; urgency=medium + + * SECURITY UPDATE: SAML Bypass + - debian/patches/CVE-2023-34058.patch: don't accept tokens with + unrelated certs in open-vm-tools/vgauth/common/certverify.c, + open-vm-tools/vgauth/common/certverify.h, + open-vm-tools/vgauth/common/prefs.h, + open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c. + - CVE-2023-34058 + * SECURITY UPDATE: file descriptor hijack + - debian/patches/CVE-2023-34059.patch: change privilege dropping order + in open-vm-tools/services/vmtoolsd/mainPosix.c, + open-vm-tools/vmware-user-suid-wrapper/main.c. + - CVE-2023-34059 + + -- Marc Deslauriers Fri, 27 Oct 2023 07:37:42 -0400 + open-vm-tools (2:12.1.5-3ubuntu0.23.04.2) lunar-security; urgency=medium * SECURITY UPDATE: SAML token signature bypass vulnerability diff -Nru open-vm-tools-12.1.5/debian/patches/CVE-2023-34058.patch open-vm-tools-12.1.5/debian/patches/CVE-2023-34058.patch --- open-vm-tools-12.1.5/debian/patches/CVE-2023-34058.patch 1970-01-01 00:00:00.000000000 +0000 +++ open-vm-tools-12.1.5/debian/patches/CVE-2023-34058.patch 2023-10-27 11:37:24.000000000 +0000 @@ -0,0 +1,226 @@ +From 6822b5a84f8cfa60d46479d6b8f1c63eb85eac87 Mon Sep 17 00:00:00 2001 +From: John Wolfe +Date: Wed, 18 Oct 2023 09:04:07 -0700 +Subject: [PATCH] Address CVE-2023-34058 + +VGAuth: don't accept tokens with unrelated certs. + +--- + open-vm-tools/vgauth/common/certverify.c | 145 ++++++++++++++++++++++++ + open-vm-tools/vgauth/common/certverify.h | 4 + + open-vm-tools/vgauth/common/prefs.h | 2 + + open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c | 14 +++ + 4 files changed, 165 insertions(+) + +--- a/open-vm-tools/vgauth/common/certverify.c ++++ b/open-vm-tools/vgauth/common/certverify.c +@@ -914,3 +914,148 @@ done: + + return err; + } ++ ++ ++/* ++ * Finds a cert with a subject (if checkSubj is set) or issuer (if ++ * checkSUbj is unset), matching 'val' in the list ++ * of certs. Returns a match or NULL. ++ */ ++ ++static X509 * ++FindCert(GList *cList, ++ X509_NAME *val, ++ int checkSubj) ++{ ++ GList *l; ++ X509 *c; ++ X509_NAME *v; ++ ++ l = cList; ++ while (l != NULL) { ++ c = (X509 *) l->data; ++ if (checkSubj) { ++ v = X509_get_subject_name(c); ++ } else { ++ v = X509_get_issuer_name(c); ++ } ++ if (X509_NAME_cmp(val, v) == 0) { ++ return c; ++ } ++ l = l->next; ++ } ++ return NULL; ++} ++ ++ ++/* ++ ****************************************************************************** ++ * CertVerify_CheckForUnrelatedCerts -- */ /** ++ * ++ * Looks over a list of certs. If it finds that they are not all ++ * part of the same chain, returns failure. ++ * ++ * @param[in] numCerts The number of certs in the chain. ++ * @param[in] pemCerts The chain of certificates to verify. ++ * ++ * @return VGAUTH_E_OK on success, VGAUTH_E_FAIL if unrelated certs are found. ++ * ++ ****************************************************************************** ++ */ ++ ++VGAuthError ++CertVerify_CheckForUnrelatedCerts(int numCerts, ++ const char **pemCerts) ++{ ++ VGAuthError err = VGAUTH_E_FAIL; ++ int chainLen = 0; ++ int i; ++ X509 **certs = NULL; ++ GList *rawList = NULL; ++ X509 *baseCert; ++ X509 *curCert; ++ X509_NAME *subject; ++ X509_NAME *issuer; ++ ++ /* common single cert case; nothing to do */ ++ if (numCerts == 1) { ++ return VGAUTH_E_OK; ++ } ++ ++ /* convert all PEM to X509 objects */ ++ certs = g_malloc0(numCerts * sizeof(X509 *)); ++ for (i = 0; i < numCerts; i++) { ++ certs[i] = CertStringToX509(pemCerts[i]); ++ if (NULL == certs[i]) { ++ g_warning("%s: failed to convert cert to X509\n", __FUNCTION__); ++ goto done; ++ } ++ } ++ ++ /* choose the cert to start the chain. shouldn't matter which */ ++ baseCert = certs[0]; ++ ++ /* put the rest into a list */ ++ for (i = 1; i < numCerts; i++) { ++ rawList = g_list_append(rawList, certs[i]); ++ } ++ ++ /* now chase down to a leaf, looking for certs the baseCert issued */ ++ subject = X509_get_subject_name(baseCert); ++ while ((curCert = FindCert(rawList, subject, 0)) != NULL) { ++ /* pull it from the list */ ++ rawList = g_list_remove(rawList, curCert); ++ /* set up the next find */ ++ subject = X509_get_subject_name(curCert); ++ } ++ ++ /* ++ * walk up to the root cert, by finding a cert where the ++ * issuer equals the subject of the current ++ */ ++ issuer = X509_get_issuer_name(baseCert); ++ while ((curCert = FindCert(rawList, issuer, 1)) != NULL) { ++ /* pull it from the list */ ++ rawList = g_list_remove(rawList, curCert); ++ /* set up the next find */ ++ issuer = X509_get_issuer_name(curCert); ++ } ++ ++ /* ++ * At this point, anything on the list should be certs that are not part ++ * of the chain that includes the original 'baseCert'. ++ * ++ * For a valid token, the list should be empty. ++ */ ++ chainLen = g_list_length(rawList); ++ if (chainLen != 0 ) { ++ GList *l; ++ ++ g_warning("%s: %d unrelated certs found in list\n", ++ __FUNCTION__, chainLen); ++ ++ /* debug helper */ ++ l = rawList; ++ while (l != NULL) { ++ X509* c = (X509 *) l->data; ++ char *s = X509_NAME_oneline(X509_get_subject_name(c), NULL, 0); ++ ++ g_debug("%s: unrelated cert subject: %s\n", __FUNCTION__, s); ++ free(s); ++ l = l->next; ++ } ++ ++ goto done; ++ } ++ ++ g_debug("%s: Success! no unrelated certs found\n", __FUNCTION__); ++ err = VGAUTH_E_OK; ++ ++done: ++ g_list_free(rawList); ++ for (i = 0; i < numCerts; i++) { ++ X509_free(certs[i]); ++ } ++ g_free(certs); ++ return err; ++} +--- a/open-vm-tools/vgauth/common/certverify.h ++++ b/open-vm-tools/vgauth/common/certverify.h +@@ -67,6 +67,10 @@ VGAuthError CertVerify_CheckSignatureUsi + size_t signatureLen, + const unsigned char *signature); + ++ ++VGAuthError CertVerify_CheckForUnrelatedCerts(int numCerts, ++ const char **pemCerts); ++ + gchar * CertVerify_StripPEMCert(const gchar *pemCert); + + gchar * CertVerify_CertToX509String(const gchar *pemCert); +--- a/open-vm-tools/vgauth/common/prefs.h ++++ b/open-vm-tools/vgauth/common/prefs.h +@@ -136,6 +136,8 @@ msgCatalog = /etc/vmware-tools/vgauth/me + #define VGAUTH_PREF_ALIASSTORE_DIR "aliasStoreDir" + /** The number of seconds slack allowed in either direction in SAML token date checks. */ + #define VGAUTH_PREF_CLOCK_SKEW_SECS "clockSkewAdjustment" ++/** If unrelated certificates are allowed in a SAML token */ ++#define VGAUTH_PREF_ALLOW_UNRELATED_CERTS "allowUnrelatedCerts" + + /** Ticket group name. */ + #define VGAUTH_PREF_GROUP_NAME_TICKET "ticket" +--- a/open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c ++++ b/open-vm-tools/vgauth/serviceImpl/saml-xmlsec1.c +@@ -49,6 +49,7 @@ + #include "vmxlog.h" + + static int gClockSkewAdjustment = VGAUTH_PREF_DEFAULT_CLOCK_SKEW_SECS; ++static gboolean gAllowUnrelatedCerts = FALSE; + static xmlSchemaPtr gParsedSchemas = NULL; + static xmlSchemaValidCtxtPtr gSchemaValidateCtx = NULL; + +@@ -369,6 +370,10 @@ LoadPrefs(void) + VGAUTH_PREF_DEFAULT_CLOCK_SKEW_SECS); + Log("%s: Allowing %d of clock skew for SAML date validation\n", + __FUNCTION__, gClockSkewAdjustment); ++ gAllowUnrelatedCerts = Pref_GetBool(gPrefs, ++ VGAUTH_PREF_ALLOW_UNRELATED_CERTS, ++ VGAUTH_PREF_GROUP_NAME_SERVICE, ++ FALSE); + } + + +@@ -1596,6 +1601,15 @@ SAML_VerifyBearerTokenAndChain(const cha + return VGAUTH_E_AUTHENTICATION_DENIED; + } + ++ if (!gAllowUnrelatedCerts) { ++ err = CertVerify_CheckForUnrelatedCerts(num, (const char **) certChain); ++ if (err != VGAUTH_E_OK) { ++ VMXLog_Log(VMXLOG_LEVEL_WARNING, ++ "Unrelated certs found in SAML token, failing\n"); ++ return VGAUTH_E_AUTHENTICATION_DENIED; ++ } ++ } ++ + subj.type = SUBJECT_TYPE_NAMED; + subj.name = *subjNameOut; + err = ServiceVerifyAndCheckTrustCertChainForSubject(num, diff -Nru open-vm-tools-12.1.5/debian/patches/CVE-2023-34059.patch open-vm-tools-12.1.5/debian/patches/CVE-2023-34059.patch --- open-vm-tools-12.1.5/debian/patches/CVE-2023-34059.patch 1970-01-01 00:00:00.000000000 +0000 +++ open-vm-tools-12.1.5/debian/patches/CVE-2023-34059.patch 2023-10-27 11:37:27.000000000 +0000 @@ -0,0 +1,182 @@ +From 2011181cbe60b256ced8d28daf7b704e8613467c Mon Sep 17 00:00:00 2001 +From: John Wolfe +Date: Wed, 18 Oct 2023 09:11:54 -0700 +Subject: [PATCH] Address CVE-2023-34059 + +Fix file descriptor vulnerability in the open-vm-tools + vmware-user-suid-wrapper on Linux. + - Moving the privilege drop logic (dropping privilege to the real uid + and gid of the process for the vmusr service) from suidWrapper to + vmtoolsd code. + +--- + open-vm-tools/services/vmtoolsd/mainPosix.c | 76 +++++++++++++++++++++++++++ + open-vm-tools/vmware-user-suid-wrapper/main.c | 26 ++------- + 2 files changed, 79 insertions(+), 23 deletions(-) + +diff --git a/open-vm-tools/services/vmtoolsd/mainPosix.c b/open-vm-tools/services/vmtoolsd/mainPosix.c +index fd2667c..8b46979 100644 +--- a/open-vm-tools/services/vmtoolsd/mainPosix.c ++++ b/open-vm-tools/services/vmtoolsd/mainPosix.c +@@ -28,10 +28,12 @@ + #include + #include + #include ++#include + #include + #include "file.h" + #include "guestApp.h" + #include "hostinfo.h" ++#include "su.h" + #include "system.h" + #include "unicode.h" + #include "util.h" +@@ -155,6 +157,59 @@ ToolsCoreWorkAroundLoop(ToolsServiceState *state, + + + /** ++ * Tools function to set close-on-exec flg for the fd. ++ * ++ * @param[in] fd open file descriptor. ++ * ++ * @return TRUE on success, FALSE otherwise. ++ */ ++ ++static gboolean ++ToolsSetCloexecFlag(int fd) ++{ ++ int flags; ++ ++ if (fd == -1) { ++ /* fd is not present, no need to manipulate */ ++ return TRUE; ++ } ++ ++ flags = fcntl(fd, F_GETFD, 0); ++ if (flags < 0) { ++ g_printerr("Couldn't get the flags set for fd %d, error %u.", fd, errno); ++ return FALSE; ++ } ++ flags |= FD_CLOEXEC; ++ if (fcntl(fd, F_SETFD, flags) < 0) { ++ g_printerr("Couldn't set close-on-exec for fd %d, error %u.", fd, errno); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++ ++/** ++ * Tools function to close the fds. ++ */ ++ ++static void ++ToolsCloseFds(void) ++{ ++ if (gState.ctx.blockFD != -1) { ++ close(gState.ctx.blockFD); ++ } ++ ++ /* ++ * uinputFD will be available only for wayland. ++ */ ++ if (gState.ctx.uinputFD != -1) { ++ close(gState.ctx.uinputFD); ++ } ++} ++ ++ ++/** + * Tools daemon entry function. + * + * @param[in] argc Argument count. +@@ -210,6 +265,27 @@ main(int argc, + g_free(argvCopy); + argvCopy = NULL; + ++ /* ++ * Drops privilege to the real uid and gid of the process ++ * for the "vmusr" service. ++ */ ++ if (TOOLS_IS_USER_SERVICE(&gState)) { ++ uid_t uid = getuid(); ++ gid_t gid = getgid(); ++ ++ if ((Id_SetREUid(uid, uid) != 0) || ++ (Id_SetREGid(gid, gid) != 0)) { ++ g_printerr("could not drop privileges: %s", strerror(errno)); ++ ToolsCloseFds(); ++ goto exit; ++ } ++ if (!ToolsSetCloexecFlag(gState.ctx.blockFD) || ++ !ToolsSetCloexecFlag(gState.ctx.uinputFD)) { ++ ToolsCloseFds(); ++ goto exit; ++ } ++ } ++ + if (gState.pidFile != NULL) { + /* + * If argv[0] is not an absolute path, make it so; all other path +diff --git a/open-vm-tools/vmware-user-suid-wrapper/main.c b/open-vm-tools/vmware-user-suid-wrapper/main.c +index e9d7e50..a19af53 100644 +--- a/open-vm-tools/vmware-user-suid-wrapper/main.c ++++ b/open-vm-tools/vmware-user-suid-wrapper/main.c +@@ -156,8 +156,7 @@ MaskSignals(void) + * + * Obtains the library directory from the Tools locations database, then + * opens a file descriptor (while still root) to add and remove blocks, +- * drops privilege to the real uid of this process, and finally starts +- * vmware-user. ++ * and finally starts vmware-user. + * + * Results: + * Parent: TRUE on success, FALSE on failure. +@@ -173,8 +172,6 @@ static Bool + StartVMwareUser(char *const envp[]) + { + pid_t pid; +- uid_t uid; +- gid_t gid; + int blockFd = -1; + char blockFdStr[8]; + int uinputFd = -1; +@@ -191,8 +188,8 @@ StartVMwareUser(char *const envp[]) + } + + /* +- * Now create a child process, obtain a file descriptor as root, downgrade +- * privilege, and run vmware-user. ++ * Now create a child process, obtain a file descriptor as root and ++ * run vmware-user. + */ + pid = fork(); + if (pid == -1) { +@@ -229,23 +226,6 @@ StartVMwareUser(char *const envp[]) + } + } + +- uid = getuid(); +- gid = getgid(); +- +- if ((setreuid(uid, uid) != 0) || +- (setregid(gid, gid) != 0)) { +- Error("could not drop privileges: %s\n", strerror(errno)); +- if (blockFd != -1) { +- close(blockFd); +- } +- if (useWayland) { +- if (uinputFd != -1) { +- close(uinputFd); +- } +- } +- return FALSE; +- } +- + /* + * Since vmware-user provides features that don't depend on vmblock, we + * invoke vmware-user even if we couldn't obtain a file descriptor or we +-- +2.6.2 + diff -Nru open-vm-tools-12.1.5/debian/patches/series open-vm-tools-12.1.5/debian/patches/series --- open-vm-tools-12.1.5/debian/patches/series 2023-09-11 18:45:06.000000000 +0000 +++ open-vm-tools-12.1.5/debian/patches/series 2023-10-27 11:37:27.000000000 +0000 @@ -3,3 +3,5 @@ debian/grpc_1.51 CVE-2023-20867.patch CVE-2023-20900.patch +CVE-2023-34058.patch +CVE-2023-34059.patch