diff --git a/0013-CVE-2020-14342-mount.cifs-fix-shell-command-injectio.patch b/0013-CVE-2020-14342-mount.cifs-fix-shell-command-injectio.patch new file mode 100644 index 0000000..2d6100a --- /dev/null +++ b/0013-CVE-2020-14342-mount.cifs-fix-shell-command-injectio.patch @@ -0,0 +1,183 @@ +From 610ea2412e2f31fbf3e662bf7dfadf7d73ce2934 Mon Sep 17 00:00:00 2001 +From: Aurelien Aptel +Date: Mon, 27 Jul 2020 10:34:44 +0200 +Subject: [PATCH] CVE-2020-14342: mount.cifs: fix shell command injection + +A bug has been reported recently for the mount.cifs utility which is +part of the cifs-utils package. The tool has a shell injection issue +where one can embed shell commands via the username mount option. Those +commands will be run via popen() in the context of the user calling +mount. + +The bug requires cifs-utils to be built with --with-systemd (enabled +by default if supported). + +A quick test to check if the mount.cifs binary is vulnerable is to look +for popen() calls like so: + + $ nm mount.cifs | grep popen + U popen@@GLIBC_2.2.5 + +If the user is allowed to run mount.cifs via sudo, he can obtain a root +shell. + + sudo mount.cifs -o username='`sh`' //1 /mnt + +If mount.cifs has the setuid bit, the command will still be run as the +calling user (no privilege escalation). + +The bug was introduced in June 2012 with commit 4e264031d0da7d3f2 +("mount.cifs: Use systemd's mechanism for getting password, if +present."). + +Affected versions: + cifs-utils-5.6 + cifs-utils-5.7 + cifs-utils-5.8 + cifs-utils-5.9 + cifs-utils-6.0 + cifs-utils-6.1 + cifs-utils-6.2 + cifs-utils-6.3 + cifs-utils-6.4 + cifs-utils-6.5 + cifs-utils-6.6 + cifs-utils-6.7 + cifs-utils-6.8 + cifs-utils-6.9 + cifs-utils-6.10 + +Bug: https://bugzilla.samba.org/show_bug.cgi?id=14442 +Reported-by: Vadim Lebedev + +Signed-off-by: Paulo Alcantara (SUSE) +Signed-off-by: Aurelien Aptel +--- + mount.cifs.c | 96 ++++++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 75 insertions(+), 21 deletions(-) + +diff --git a/mount.cifs.c b/mount.cifs.c +index 40918c1..4feb397 100644 +--- a/mount.cifs.c ++++ b/mount.cifs.c +@@ -1695,6 +1695,73 @@ drop_child_privs(void) + return 0; + } + ++#ifdef ENABLE_SYSTEMD ++static int get_passwd_by_systemd(const char *prompt, char *input, int capacity) ++{ ++ int fd[2]; ++ pid_t pid; ++ int offs = 0; ++ int rc = 1; ++ ++ if (pipe(fd) == -1) { ++ fprintf(stderr, "Failed to create pipe: %s\n", strerror(errno)); ++ return 1; ++ } ++ ++ pid = fork(); ++ if (pid == -1) { ++ fprintf(stderr, "Unable to fork: %s\n", strerror(errno)); ++ close(fd[0]); ++ close(fd[1]); ++ return 1; ++ } ++ if (pid == 0) { ++ close(fd[0]); ++ dup2(fd[1], STDOUT_FILENO); ++ if (execlp("systemd-ask-password", "systemd-ask-password", prompt, NULL) == -1) { ++ fprintf(stderr, "Failed to execute systemd-ask-password: %s\n", ++ strerror(errno)); ++ } ++ exit(1); ++ } ++ ++ close(fd[1]); ++ for (;;) { ++ if (offs+1 >= capacity) { ++ fprintf(stderr, "Password too long.\n"); ++ kill(pid, SIGTERM); ++ rc = 1; ++ break; ++ } ++ rc = read(fd[0], input + offs, capacity - offs); ++ if (rc == -1) { ++ fprintf(stderr, "Failed to read from pipe: %s\n", strerror(errno)); ++ rc = 1; ++ break; ++ } ++ if (!rc) ++ break; ++ offs += rc; ++ input[offs] = '\0'; ++ } ++ if (wait(&rc) == -1) { ++ fprintf(stderr, "Failed to wait child: %s\n", strerror(errno)); ++ rc = 1; ++ goto out; ++ } ++ if (!WIFEXITED(rc) || WEXITSTATUS(rc)) { ++ rc = 1; ++ goto out; ++ } ++ ++ rc = 0; ++ ++out: ++ close(fd[0]); ++ return rc; ++} ++#endif ++ + /* + * If systemd is running and systemd-ask-password -- + * is available, then use that else fallback on getpass(..) +@@ -1708,35 +1775,22 @@ get_password(const char *prompt, char *input, int capacity) + int is_systemd_running; + struct stat a, b; + ++ memset(input, 0, capacity); ++ + /* We simply test whether the systemd cgroup hierarchy is + * mounted */ + is_systemd_running = (lstat("/sys/fs/cgroup", &a) == 0) + && (lstat("/sys/fs/cgroup/systemd", &b) == 0) + && (a.st_dev != b.st_dev); + +- if (is_systemd_running) { +- char *cmd, *ret; +- FILE *ask_pass_fp = NULL; +- +- cmd = ret = NULL; +- if (asprintf(&cmd, "systemd-ask-password \"%s\"", prompt) >= 0) { +- ask_pass_fp = popen (cmd, "re"); +- free (cmd); +- } +- +- if (ask_pass_fp) { +- ret = fgets(input, capacity, ask_pass_fp); +- pclose(ask_pass_fp); +- } +- +- if (ret) { +- int len = strlen(input); +- if (input[len - 1] == '\n') +- input[len - 1] = '\0'; +- return input; +- } ++ if (is_systemd_running && !get_passwd_by_systemd(prompt, input, capacity)) { ++ int len = strlen(input); ++ if (input[len - 1] == '\n') ++ input[len - 1] = '\0'; ++ return input; + } + #endif ++ memset(input, 0, capacity); + + /* + * Falling back to getpass(..) +-- +2.27.0 + diff --git a/cifs-utils.changes b/cifs-utils.changes index 89faee6..a6e955b 100644 --- a/cifs-utils.changes +++ b/cifs-utils.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Mon Aug 10 06:56:11 UTC 2020 - Aurelien Aptel + +- CVE-2020-14342: Shell command injection vulnerability in mount.cifs; + (bsc#1174477); (bso#14442); CVE-2020-14342. + * add 0013-CVE-2020-14342-mount.cifs-fix-shell-command-injectio.patch + ------------------------------------------------------------------- Wed Apr 8 10:36:15 UTC 2020 - Aurelien Aptel diff --git a/cifs-utils.spec b/cifs-utils.spec index 710c39a..7b42ab8 100644 --- a/cifs-utils.spec +++ b/cifs-utils.spec @@ -44,11 +44,12 @@ Patch8: 0009-Zero-fill-the-allocated-memory-for-new-struct-cifs_n.patch Patch9: 0010-Zero-fill-the-allocated-memory-for-a-new-ACE.patch Patch10: 0011-fix-doublefree.patch Patch11: 0012-mount.cifs-Fix-invalid-free.patch +Patch12: 0013-CVE-2020-14342-mount.cifs-fix-shell-command-injectio.patch # cifs-utils 6.8 switched to python for man page generation # we need to require either py2 or py3 package # some products do not have a py2/py3 versions -%if 0%{?suse_version} > 1500 || 0%{?sle_version} >= 120000 +%if 0%{?suse_version} >= 1500 BuildRequires: python3-docutils %else BuildRequires: python-docutils @@ -132,6 +133,7 @@ cp -a ${RPM_SOURCE_DIR}/README.cifstab.migration . %patch9 -p1 %patch10 -p1 %patch11 -p1 +%patch12 -p1 %build export CFLAGS="%{optflags} -D_GNU_SOURCE -fpie"