| From 703418fe9d2e3b1e8d594df5788d8001a8116265 Mon Sep 17 00:00:00 2001 |
| From: Jeffrey Bencteux <jeffbencteux@gmail.com> |
| Date: Fri, 30 Jun 2023 19:02:45 +0200 |
| Subject: [PATCH] CVE-2023-40303: ftpd,rcp,rlogin,rsh,rshd,uucpd: fix: check |
| set*id() return values |
| |
| Several setuid(), setgid(), seteuid() and setguid() return values |
| were not checked in ftpd/rcp/rlogin/rsh/rshd/uucpd code potentially |
| leading to potential security issues. |
| |
| CVE: CVE-2023-40303 |
| Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/inetutils.git/commit/?id=e4e65c03f4c11292a3e40ef72ca3f194c8bffdd6] |
| Signed-off-by: Jeffrey Bencteux <jeffbencteux@gmail.com> |
| Signed-off-by: Simon Josefsson <simon@josefsson.org> |
| Signed-off-by: Khem Raj <raj.khem@gmail.com> |
| --- |
| ftpd/ftpd.c | 10 +++++++--- |
| src/rcp.c | 39 +++++++++++++++++++++++++++++++++------ |
| src/rlogin.c | 11 +++++++++-- |
| src/rsh.c | 25 +++++++++++++++++++++---- |
| src/rshd.c | 20 +++++++++++++++++--- |
| src/uucpd.c | 15 +++++++++++++-- |
| 6 files changed, 100 insertions(+), 20 deletions(-) |
| |
| diff --git a/ftpd/ftpd.c b/ftpd/ftpd.c |
| index 92b2cca5..28dd523f 100644 |
| --- a/ftpd/ftpd.c |
| +++ b/ftpd/ftpd.c |
| @@ -862,7 +862,9 @@ end_login (struct credentials *pcred) |
| char *remotehost = pcred->remotehost; |
| int atype = pcred->auth_type; |
| |
| - seteuid ((uid_t) 0); |
| + if (seteuid ((uid_t) 0) == -1) |
| + _exit (EXIT_FAILURE); |
| + |
| if (pcred->logged_in) |
| { |
| logwtmp_keep_open (ttyline, "", ""); |
| @@ -1151,7 +1153,8 @@ getdatasock (const char *mode) |
| |
| if (data >= 0) |
| return fdopen (data, mode); |
| - seteuid ((uid_t) 0); |
| + if (seteuid ((uid_t) 0) == -1) |
| + _exit (EXIT_FAILURE); |
| s = socket (ctrl_addr.ss_family, SOCK_STREAM, 0); |
| if (s < 0) |
| goto bad; |
| @@ -1978,7 +1981,8 @@ passive (int epsv, int af) |
| else /* !AF_INET6 */ |
| ((struct sockaddr_in *) &pasv_addr)->sin_port = 0; |
| |
| - seteuid ((uid_t) 0); |
| + if (seteuid ((uid_t) 0) == -1) |
| + _exit (EXIT_FAILURE); |
| if (bind (pdata, (struct sockaddr *) &pasv_addr, pasv_addrlen) < 0) |
| { |
| if (seteuid ((uid_t) cred.uid)) |
| diff --git a/src/rcp.c b/src/rcp.c |
| index 75adb253..cdcf8500 100644 |
| --- a/src/rcp.c |
| +++ b/src/rcp.c |
| @@ -345,14 +345,23 @@ main (int argc, char *argv[]) |
| if (from_option) |
| { /* Follow "protocol", send data. */ |
| response (); |
| - setuid (userid); |
| + |
| + if (setuid (userid) == -1) |
| + { |
| + error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)"); |
| + } |
| + |
| source (argc, argv); |
| exit (errs); |
| } |
| |
| if (to_option) |
| { /* Receive data. */ |
| - setuid (userid); |
| + if (setuid (userid) == -1) |
| + { |
| + error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)"); |
| + } |
| + |
| sink (argc, argv); |
| exit (errs); |
| } |
| @@ -537,7 +546,11 @@ toremote (char *targ, int argc, char *argv[]) |
| if (response () < 0) |
| exit (EXIT_FAILURE); |
| free (bp); |
| - setuid (userid); |
| + |
| + if (setuid (userid) == -1) |
| + { |
| + error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)"); |
| + } |
| } |
| source (1, argv + i); |
| close (rem); |
| @@ -630,7 +643,12 @@ tolocal (int argc, char *argv[]) |
| ++errs; |
| continue; |
| } |
| - seteuid (userid); |
| + |
| + if (seteuid (userid) == -1) |
| + { |
| + error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)"); |
| + } |
| + |
| #if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT |
| sslen = sizeof (ss); |
| (void) getpeername (rem, (struct sockaddr *) &ss, &sslen); |
| @@ -643,7 +661,12 @@ tolocal (int argc, char *argv[]) |
| #endif |
| vect[0] = target; |
| sink (1, vect); |
| - seteuid (effuid); |
| + |
| + if (seteuid (effuid) == -1) |
| + { |
| + error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)"); |
| + } |
| + |
| close (rem); |
| rem = -1; |
| #ifdef SHISHI |
| @@ -1441,7 +1464,11 @@ susystem (char *s, int userid) |
| return (127); |
| |
| case 0: |
| - setuid (userid); |
| + if (setuid (userid) == -1) |
| + { |
| + error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)"); |
| + } |
| + |
| execl (PATH_BSHELL, "sh", "-c", s, NULL); |
| _exit (127); |
| } |
| diff --git a/src/rlogin.c b/src/rlogin.c |
| index aa6426fb..c543de0c 100644 |
| --- a/src/rlogin.c |
| +++ b/src/rlogin.c |
| @@ -647,8 +647,15 @@ try_connect: |
| /* Now change to the real user ID. We have to be set-user-ID root |
| to get the privileged port that rcmd () uses. We now want, however, |
| to run as the real user who invoked us. */ |
| - seteuid (uid); |
| - setuid (uid); |
| + if (seteuid (uid) == -1) |
| + { |
| + error (EXIT_FAILURE, 0, "Could not drop privileges (seteuid() failed)"); |
| + } |
| + |
| + if (setuid (uid) == -1) |
| + { |
| + error (EXIT_FAILURE, 0, "Could not drop privileges (setuid() failed)"); |
| + } |
| |
| doit (&osmask); /* The old mask will activate SIGURG and SIGUSR1! */ |
| |
| diff --git a/src/rsh.c b/src/rsh.c |
| index 2d622ca4..6f60667d 100644 |
| --- a/src/rsh.c |
| +++ b/src/rsh.c |
| @@ -276,8 +276,17 @@ main (int argc, char **argv) |
| { |
| if (asrsh) |
| *argv = (char *) "rlogin"; |
| - seteuid (getuid ()); |
| - setuid (getuid ()); |
| + |
| + if (seteuid (getuid ()) == -1) |
| + { |
| + error (EXIT_FAILURE, errno, "seteuid() failed"); |
| + } |
| + |
| + if (setuid (getuid ()) == -1) |
| + { |
| + error (EXIT_FAILURE, errno, "setuid() failed"); |
| + } |
| + |
| execv (PATH_RLOGIN, argv); |
| error (EXIT_FAILURE, errno, "cannot execute %s", PATH_RLOGIN); |
| } |
| @@ -541,8 +550,16 @@ try_connect: |
| error (0, errno, "setsockopt DEBUG (ignored)"); |
| } |
| |
| - seteuid (uid); |
| - setuid (uid); |
| + if (seteuid (uid) == -1) |
| + { |
| + error (EXIT_FAILURE, errno, "seteuid() failed"); |
| + } |
| + |
| + if (setuid (uid) == -1) |
| + { |
| + error (EXIT_FAILURE, errno, "setuid() failed"); |
| + } |
| + |
| #ifdef HAVE_SIGACTION |
| sigemptyset (&sigs); |
| sigaddset (&sigs, SIGINT); |
| diff --git a/src/rshd.c b/src/rshd.c |
| index d1c0d0cd..707790e7 100644 |
| --- a/src/rshd.c |
| +++ b/src/rshd.c |
| @@ -1847,8 +1847,18 @@ doit (int sockfd, struct sockaddr *fromp, socklen_t fromlen) |
| pwd->pw_shell = PATH_BSHELL; |
| |
| /* Set the gid, then uid to become the user specified by "locuser" */ |
| - setegid ((gid_t) pwd->pw_gid); |
| - setgid ((gid_t) pwd->pw_gid); |
| + if (setegid ((gid_t) pwd->pw_gid) == -1) |
| + { |
| + rshd_error ("Cannot drop privileges (setegid() failed)\n"); |
| + exit (EXIT_FAILURE); |
| + } |
| + |
| + if (setgid ((gid_t) pwd->pw_gid) == -1) |
| + { |
| + rshd_error ("Cannot drop privileges (setgid() failed)\n"); |
| + exit (EXIT_FAILURE); |
| + } |
| + |
| #ifdef HAVE_INITGROUPS |
| initgroups (pwd->pw_name, pwd->pw_gid); /* BSD groups */ |
| #endif |
| @@ -1870,7 +1880,11 @@ doit (int sockfd, struct sockaddr *fromp, socklen_t fromlen) |
| } |
| #endif /* WITH_PAM */ |
| |
| - setuid ((uid_t) pwd->pw_uid); |
| + if (setuid ((uid_t) pwd->pw_uid) == -1) |
| + { |
| + rshd_error ("Cannot drop privileges (setuid() failed)\n"); |
| + exit (EXIT_FAILURE); |
| + } |
| |
| /* We'll execute the client's command in the home directory |
| * of locuser. Note, that the chdir must be executed after |
| diff --git a/src/uucpd.c b/src/uucpd.c |
| index 107589e1..29cfce35 100644 |
| --- a/src/uucpd.c |
| +++ b/src/uucpd.c |
| @@ -252,7 +252,12 @@ doit (struct sockaddr *sap, socklen_t salen) |
| snprintf (Username, sizeof (Username), "USER=%s", user); |
| snprintf (Logname, sizeof (Logname), "LOGNAME=%s", user); |
| dologin (pw, sap, salen); |
| - setgid (pw->pw_gid); |
| + |
| + if (setgid (pw->pw_gid) == -1) |
| + { |
| + fprintf (stderr, "setgid() failed"); |
| + return; |
| + } |
| #ifdef HAVE_INITGROUPS |
| initgroups (pw->pw_name, pw->pw_gid); |
| #endif |
| @@ -261,7 +266,13 @@ doit (struct sockaddr *sap, socklen_t salen) |
| fprintf (stderr, "Login incorrect."); |
| return; |
| } |
| - setuid (pw->pw_uid); |
| + |
| + if (setuid (pw->pw_uid) == -1) |
| + { |
| + fprintf (stderr, "setuid() failed"); |
| + return; |
| + } |
| + |
| execl (uucico_location, "uucico", NULL); |
| perror ("uucico server: execl"); |
| } |