Bugtraq mailing list archives

BoS: serious security bug in wu-ftpd v2.4 -- PATCH


From: security () kinch ark com (Dave Kinchlea)
Date: Sun, 5 Jan 1997 22:49:45 -0800


On Sun, 5 Jan 1997, Dave Kinchlea wrote:
[...]
                                              If there is
interest, I can make the patches available.

cheers, kinch

Appearently there is. I note that two people have mentioned that my
simple suspendsigs/resumesigs functions may not be the best solutions.
One person mentioned that some signals may get lost as they are just
being ignored, another mentioned that signal() is unreliable on some
systems. I am not going to change these, however, as to do better
requires more knowledge of all the different flavours of signal than I
have. Others can (and probably will), the patches will still be good
regardless.

First, my simple functions followed by the patches (unified diff
format). Please take note that these patches are against sources that
have been patched for Linux+PAM+RedHat release.

 It goes without saying that I take no responsibility for any
damage done as a result of this yada yada yada ...

/* ######################### sigfix.c ################################# */

/* These two functions are a kludge to try to stop a possible
security problem with stray signals and seteuid(0) calls. I am
taking the idea from Wietse Venema, I don't see how it can harm
anything and ought to stop this particular hole (until a new/better
method is found).
*/
void
#ifdef __STDC__
suspendsigs(void)
#else
suspendsigs()
#endif
{
#ifdef SIGPIPE
    (void) signal(SIGPIPE, SIG_IGN);
#endif

#ifdef SIGURG
    (void) signal(SIGURG, SIG_IGN);
#endif
}

void
#ifdef __STDC__
resumesigs(void)
#else
reseumesigs()
#endif
{
#ifdef SIGPIPE
    (void) signal(SIGPIPE, lostconn);
#endif

#ifdef SIGURG
    if ((int) signal(SIGURG, myoob) < 0)
        syslog(LOG_ERR, "signal: %m");
#endif
}

######################## wu-kinch.patch #############################
--- ./wu-ftpd-2.4.2-beta-11/src/makefiles/Makefile.lnx.kinch    Sun Jan  5 20:29:24 1997
+++ ./wu-ftpd-2.4.2-beta-11/src/makefiles/Makefile.lnx  Sun Jan  5 20:28:28 1997
@@ -16,9 +16,11 @@
 MKDEP    = ../util/mkdep

 SRCS   = ftpd.c ftpcmd.c glob.c logwtmp.c popen.c vers.c access.c extensions.c \
-         realpath.c acl.c private.c authenticate.c conversions.c hostacc.c
+         realpath.c acl.c private.c authenticate.c conversions.c hostacc.c \
+         sigfix.c
 OBJS   = ftpd.o ftpcmd.o glob.o logwtmp.o popen.o vers.o access.o extensions.o \
-         realpath.o acl.o private.o authenticate.o conversions.o hostacc.o
+         realpath.o acl.o private.o authenticate.o conversions.o hostacc.o \
+         sigfix.o

 ifdef USE_PAM
 CFLAGS  += -DUSE_PAM=1
--- ./wu-ftpd-2.4.2-beta-11/src/private.c.kinch Sun Jan  5 12:56:55 1997
+++ ./wu-ftpd-2.4.2-beta-11/src/private.c       Sun Jan  5 14:13:21 1997
@@ -318,9 +318,11 @@
     uid = geteuid();
     gid = grp->gr_gid;

+    suspendsigs(); /* we can't allow any signals while euid==0: kinch */
     seteuid(0);
     setegid(gid);
     seteuid(uid);
+    resumesigs(); /* we can allow signals once again: kinch */

     reply(200, "Group access enabled.");
     group_attempts = 0;
--- ./wu-ftpd-2.4.2-beta-11/src/popen.c.kinch   Mon Dec 11 01:14:43 1995
+++ ./wu-ftpd-2.4.2-beta-11/src/popen.c Sun Jan  5 14:11:44 1997
@@ -168,9 +168,11 @@
        /* begin CERT suggested fixes */
        close(0);
         i = geteuid();
+       suspendsigs(); /* we can't allow any signals while euid==0: kinch */
         seteuid(0);
         setgid(getegid());
         setuid(i);
+       resumesigs(); /* we can allow signals once again: kinch */
        /* end CERT suggested fixes */
        execv(gargv[0], gargv);
         _exit(1);
--- ./wu-ftpd-2.4.2-beta-11/src/ftpd.c.kinch    Sun Jan  5 13:53:03 1997
+++ ./wu-ftpd-2.4.2-beta-11/src/ftpd.c  Sun Jan  5 20:37:58 1997
@@ -1234,6 +1234,7 @@
 #endif
 {

+    suspendsigs(); /* we can't allow any signals while euid==0: kinch */
     (void) seteuid((uid_t) 0);
     if (logged_in)
         logwtmp(ttyline, "", "");
@@ -1578,6 +1579,7 @@
       return 0;
     }
 #endif
+    resumesigs(); /* we can allow signals once again: kinch */

     if (*home_dir != '\0') {
       if (chdir(home_dir) < 0) {
@@ -2062,13 +2064,16 @@

     if (valid > 0) {
         oldid = geteuid();
+        suspendsigs(); /* we can't allow any signals while euid==0: kinch */
         (void) seteuid((uid_t) 0);
         if ((fchown(fdout, uid, gid)) < 0) {
             (void) seteuid(oldid);
+            resumesigs(); /* we can allow signals once again: kinch */
             perror_reply(550, "fchown");
             return;
         }
         (void) seteuid(oldid);
+        resumesigs(); /* we can allow signals once again: kinch */
     }
 #endif /* UPLOAD */

@@ -2206,6 +2211,7 @@

     if (data >= 0)
         return (fdopen(data, mode));
+    suspendsigs(); /* we can't allow any signals while euid==0: kinch */
     (void) seteuid((uid_t) 0);
     s = socket(AF_INET, SOCK_STREAM, 0);
     if (s < 0)
@@ -2237,6 +2243,7 @@
     }
 #endif
     (void) seteuid((uid_t) pw->pw_uid);
+    resumesigs(); /* we can allow signals once again: kinch */

 #ifdef IPTOS_THROUGHPUT
     on = IPTOS_THROUGHPUT;
@@ -2258,6 +2265,7 @@
     return (fdopen(s, mode));
   bad:
     (void) seteuid((uid_t) pw->pw_uid);
+    resumesigs(); /* we can allow signals once again: kinch */
     (void) close(s);
     return (NULL);
 }
@@ -3157,6 +3165,7 @@
 #endif
 {
     if (logged_in) {
+        suspendsigs(); /* we can't allow any signals while euid==0: kinch */
         (void) seteuid((uid_t) 0);
         logwtmp(ttyline, "", "");
     }
@@ -3233,12 +3242,15 @@
     }
     pasv_addr = ctrl_addr;
     pasv_addr.sin_port = 0;
+    suspendsigs(); /* we can't allow any signals while euid==0: kinch */
     (void) seteuid((uid_t) 0);         /* XXX: not needed if > 1024 */
     if (bind(pdata, (struct sockaddr *) &pasv_addr, sizeof(pasv_addr)) < 0) {
         (void) seteuid((uid_t) pw->pw_uid);
+        resumesigs(); /* we can allow signals once again: kinch */
         goto pasv_error;
     }
     (void) seteuid((uid_t) pw->pw_uid);
+    resumesigs(); /* we can allow signals once again: kinch */
     len = sizeof(pasv_addr);
     if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
         goto pasv_error;
--- ./wu-ftpd-2.4.2-beta-11/src/realpath.c.kinch        Sun Apr 14 22:51:15 1996
+++ ./wu-ftpd-2.4.2-beta-11/src/realpath.c      Sun Jan  5 14:12:39 1997
@@ -86,6 +86,7 @@
         if (!getwd(workpath)) {
 #endif
                userid = geteuid();
+               suspendsigs(); /* we can't allow any signals while euid==0: kinch */
                seteuid(0);
 #ifdef HAVE_GETCWD
                if (!getcwd(workpath,MAXPATHLEN)) {
@@ -94,9 +95,11 @@
 #endif
                    strcpy(result, ".");
                    seteuid(userid);
+                   resumesigs(); /* we can allow signals once again: kinch */
                    return (NULL);
                }
                seteuid(userid);
+               resumesigs(); /* we can allow signals once again: kinch */
        }
     } else
         *workpath = '\0';



Current thread: