Bugtraq mailing list archives

Re: sperl 5.00503 (and newer ;) exploit


From: "Francis J. Lacoste" <francis.lacoste () INSU COM>
Date: Mon, 7 Aug 2000 14:58:08 -0400


Regarding the suidperl / mailx security problem, here are
two patches which closes the hole in perl and in mailx.

The perl bug is closed by using syslog rather than /bin/mail

The mailx patch (against 8.1.1 + redhat/debian patches) does
the following :

        - Do not lookup options in the environment.
        - Do not read rc files when running with uid != euid
        - Unset interactive when sending mail with uid != euid
          or when stdin is not a tty.


-- 
Francis J. Lacoste                   iNsu Innovations Inc.      
CTA                                   Tél.: (514) 336-5544
francis.lacoste () iNsu COM           Fax.: (514) 336-8128
--- perl5.005_03/perl.c.dont-try-to-be-clever   Mon Aug  7 09:46:06 2000
+++ perl5.005_03/perl.c Mon Aug  7 09:52:27 2000
@@ -20,6 +20,9 @@
 #include <unistd.h>
 #endif

+/* Use syslog rather than /bin/mail to notify of tricky perl behavior  */
+#include <syslog.h>
+
 #if !defined(STANDARD_C) && !defined(HAS_GETENV_PROTOTYPE)
 char *getenv _((char *)); /* Usually in <stdlib.h> */
 #endif
@@ -2220,16 +2223,17 @@
            if (tmpstatbuf.st_dev != PL_statbuf.st_dev ||
                tmpstatbuf.st_ino != PL_statbuf.st_ino) {
                (void)PerlIO_close(PL_rsfp);
-               if (PL_rsfp = PerlProc_popen("/bin/mail root","w")) {   /* heh, heh */
-                   PerlIO_printf(PL_rsfp,
-"User %ld tried to run dev %ld ino %ld in place of dev %ld ino %ld!\n\
-(Filename of set-id script was %s, uid %ld gid %ld.)\n\nSincerely,\nperl\n",
+               openlog( "suidperl", LOG_NDELAY|LOG_PID, LOG_AUTHPRIV);
+               syslog( LOG_ALERT,
+                       "User %ld tried to run dev %ld ino %ld in"
+                       " place  of dev %ld ino %ld!\n"
+                       "(Filename of set-id script was %s, uid %ld "
+                       "gid %ld.)\n\nSincerely,\nperl\n",
                        (long)PL_uid,(long)tmpstatbuf.st_dev, (long)tmpstatbuf.st_ino,
                        (long)PL_statbuf.st_dev, (long)PL_statbuf.st_ino,
                        SvPVX(GvSV(PL_curcop->cop_filegv)),
                        (long)PL_statbuf.st_uid, (long)PL_statbuf.st_gid);
-                   (void)PerlProc_pclose(PL_rsfp);
-               }
+               closelog();
                croak("Permission denied\n");
            }
            if (
--- mailx-8.1.1/main.c.setuid   Mon Aug  7 14:27:56 2000
+++ mailx-8.1.1/main.c  Mon Aug  7 14:33:12 2000
@@ -233,14 +233,30 @@
        input = stdin;
        rcvmode = !to;
        spreserve();
-       if (!nosrc)
-               load(_PATH_MASTER_RC);
-       /*
-        * Expand returns a savestr, but load only uses the file name
-        * for fopen, so it's safe to do this.
-        */
-       load(expand("~/.mailrc"));
+
+       /* Only load command file if we are not running setuid
+          - From under a setuid program or something */
+       if ( getuid() == geteuid() ) {
+               if (!nosrc)
+                       load(_PATH_MASTER_RC);
+               /*
+                * Expand returns a savestr, but load only uses the file name
+                * for fopen, so it's safe to do this.
+                */
+               load(expand("~/.mailrc"));
+       }
+       
        if (!rcvmode) {
+               /* In send mode, turn off interactive if
+                  we are setuid or not running from
+                  a terminal */
+               if ( value( "interactive" ) != NOSTR &&
+                    ( getuid() != geteuid() || !isatty(0)) )
+               {
+                       char *interactive[] = { "interactive", NULL };
+                       unset( interactive );
+               }       
+               
                mail(to, cc, bcc, smopts, subject);
                /*
                 * why wait?
--- mailx-8.1.1/vars.c.setuid   Mon Aug  7 14:28:00 2000
+++ mailx-8.1.1/vars.c  Mon Aug  7 14:28:15 2000
@@ -110,7 +110,6 @@

 /*
  * Get the value of a variable and return it.
- * Look in the environment if its not available locally.
  */

 char *
@@ -120,7 +119,7 @@
        register struct var *vp;

        if ((vp = lookup(name)) == NOVAR)
-               return(getenv(name));
+               return NULL;
        return(vp->v_value);
 }


Current thread: