[287] in linux-security and linux-alert archive

home help back first fref pref prev next nref lref last post

lpr(1) bug

daemon@ATHENA.MIT.EDU (Aleph One)
Thu Jul 13 19:28:22 1995

Date: Thu, 13 Jul 1995 17:09:18 -0500 (CDT)
From: Aleph One <aleph1@dfw.net>
To: linux-security@tarsier.cv.nrao.edu
Cc: eugene%pspdpc114@wal.ab.com, linuxisp@lightning.com, bugtraq@crimelab.com,
        biglinux@netspace.org, volkerdi@wcarchive.cdrom.com,
        volkerdi@mhd1.moorhead.msus.edu

Problem: lpr(1) can be fooled into removing any file in the system by 
means of the -r flag.

lpr(1) uses the access system call to determine if the parent directory
of the file is writable by the real uid. If it is, it assumes the file
can be unlinked. The problem arises in that lpr(1) does not check for
directories with the sticky bit set (eg. /tmp).

What fallows is a small (and damm ugly) hack to fix it. All credit goes 
to Zygo Blaxell for pointing this out in the linuxisp maling list. A 
patched version will be uploaded to sunsite later today. The MD5 
signature fallows:

MD5 (lpr-secure) = d41d8cd98f00b204e9800998ecf8427e

The patch fallows:

diff -u --recursive lpr/lpr/lpr/lpr.c lpr-secure/lpr/lpr/lpr.c
--- lpr/lpr/lpr/lpr.c   Mon May 23 02:05:02 1994
+++ lpr-secure/lpr/lpr/lpr.c    Thu Jul 13 14:26:08 1995
@@ -548,6 +548,7 @@
        char *file;
 {
        struct exec execb;
+       struct stat stats;
        register int fd;
        register char *cp;

@@ -604,14 +605,32 @@
        (void) close(fd);
        if (rflag) {
                if ((cp = rindex(file, '/')) == NULL) {
-                       if (access(".", 2) == 0)
-                               return(1);
+                       if (access(".", 2) == 0)  {
+                               stat(".", &stats);
+                               if (stats.st_mode & S_ISVTX) { /* Sticky 
bit */
+                                       stat(file, &stats);
+                                       if (stats.st_uid == userid) {
+                                               return(1);
+                                       }
+                               } else {
+                                       return(1);
+                               }
+                       }
                } else {
                        *cp = '\0';
-                       fd = access(file, 2);
+                       if (access(file,2) == 0) {
+                                stat(file, &stats);
+                               *cp = '/';
+                                if (stats.st_mode & S_ISVTX) { /* Sticky 
bit */+                                       stat(file, &stats);
+                                       if (stats.st_uid == userid) {
+                                               return(1);
+                                       }
+                                } else { /* Sticky bit is set */
+                                        return(1);
+                               }
+                        }
                        *cp = '/';
-                       if (fd == 0)
-                               return(1);
                }
                printf("%s: %s: is not removable by you\n", name, file);
        }



Aleph One / aleph1@dfw.net
http://underground.org/

home help back first fref pref prev next nref lref last post