[LWN Logo]
[LWN.net]
From:	 solar@openwall.com
To:	 zenith parsec <zenith_parsec@the-astronaut.com>
Subject: Re: RH7.0: man local gid 15 (man) exploit
Date:	 Tue, 15 May 2001 05:00:28 +0400
Cc:	 bugtraq@securityfocus.com

On Sun, May 13, 2001 at 08:07:34PM -0000, zenith parsec wrote:
> man -S `perl -e 'print ":" x 100'`
> 
> Will cause a seg fault if you are vulnerable.

This and several other man vulnerabilities have been discussed on
security-audit last year.  See:

MARC: thrd 'Multiple man vulnerabilities with Red Hat Linux 6.2'
http://marc.theaimsgroup.com/?t=97096128600001&w=2&r=1

MARC: thrd 'More fun with man 1.5h1'
http://marc.theaimsgroup.com/?t=97135295400001&w=2&r=1

I don't think your analysis of the possibilities to exploit this is
entirely correct.  The buffer is in the bss, not on the heap.  In fact,
the builds of man-1.5h1 I have here won't even segfault on the command
you mention, not even when given 400 colons -- but they do misbehave in
other ways.  (I am willing to believe that this really is exploitable
on the RH 7.0 build, which I don't have.)

Of course, this is just one reason why SGID man is bad.

> GID man allows a race condition for root via
> /etc/cron.daily/makewhatis and /sbin/makwhatis

Yes, due to their security fix.  I haven't seen this mentioned before
(but I'm not using this broken fix, anyway).

-TMPFILE=$HOME/whatis$$
-TMPFILEDIR=/tmp/whatis$$
+TMPFILE=/var/cache/man/whatis$$
+TMPFILEDIR=/var/cache/man/whatis$$

where /var/cache/man is writable by group man. :-(

The makewhatis patch we have in Owl (http://www.openwall.com/Owl/) is
attached.

The section list overflow bug you mention isn't a security problem on
Owl for obvious reasons, but is on my TODO for fixing (has been there
since the security-audit discussion).

-- 
/sd

diff -ur man-1.5h1.orig/src/makewhatis.sh man-1.5h1/src/makewhatis.sh
--- man-1.5h1.orig/src/makewhatis.sh	Tue Jun 29 06:20:59 1999
+++ man-1.5h1/src/makewhatis.sh	Thu Aug 10 02:56:57 2000
@@ -3,6 +3,7 @@
 # Created: Sun Jun 14 10:49:37 1992
 # Revised: Sat Jan  8 14:12:37 1994 by faith@cs.unc.edu
 # Revised: Sat Mar 23 17:56:18 1996 by micheal@actrix.gen.nz
+# Revised: Thu Aug 10 02:17:50 2000 by solar@owl.openwall.com
 # Copyright 1992, 1993, 1994 Rickard E. Faith (faith@cs.unc.edu)
 # May be freely distributed and modified as long as copyright is retained.
 #
@@ -24,6 +25,7 @@
 # 960510 - added fixes by brennan@raven.ca.boeing.com, author of mawk.
 # 971012 - replaced "test -z" - it doesnt work on SunOS 4.1.3_U1.
 # 980710 - be more careful with TMPFILE
+# 000810 - solar: use mktemp, keep whatis files consistent while running.
 #
 # Note for Slackware users: "makewhatis -v -w -c" will work.
 #
@@ -39,23 +41,7 @@
 # AWK=/usr/bin/gawk
 AWK=%gawk%
 
-# Find a place for our temporary files. If security is not a concern, use
-#	TMPFILE=/tmp/whatis$$; TMPFILEDIR=none
-# Of course makewhatis should only have the required permissions
-# (for reading and writing directories like /usr/man).
-# We try here to be careful (and avoid preconstructed symlinks)
-# in case makewhatis is run as root, by creating a subdirectory of /tmp.
-# If that fails we use $HOME.
-# The code below uses  test -O  which doesnt work on all systems.
-TMPFILE=$HOME/whatis$$
-TMPFILEDIR=/tmp/whatis$$
-if [ ! -d $TMPFILEDIR ]; then
-	mkdir $TMPFILEDIR
-	chmod 0700 $TMPFILEDIR
-	if [ -O $TMPFILEDIR ]; then
-		TMPFILE=$TMPFILEDIR/w
-	fi
-fi
+TMPFILE=`mktemp /tmp/$program.XXXXXX` || exit 1
 
 topath=manpath
 
@@ -74,6 +60,7 @@
 case $name in
     --version|-V)
         echo "$program from %version%"
+	rm $TMPFILE
 	exit 0;;
     -c) topath=catpath
 	defmanpath=
@@ -97,12 +84,14 @@
         echo "       [manpath]: man directories (default: $DEFMANPATH)"
 	echo "       [catpath]: cat directories (default: the first existing"
 	echo "           directory in $DEFCATPATH)"
+	rm $TMPFILE
         exit;;
      *) if [ -d $name ]
         then
             eval $topath="\$$topath":$name
         else
             echo "No such directory $name"
+	    rm $TMPFILE
             exit
         fi;;
 esac
@@ -117,7 +106,7 @@
 fi
 catpath=`echo ${catpath} | tr : ' '`
 
-# first truncate all the whatis files that will be created new,
+# first mark all the whatis files that will be created new,
 # then only update - we might visit the same directory twice
 if [ x$update = x ]; then
    for pages in man cat
@@ -125,7 +114,7 @@
       eval path="\$$pages"path
       for mandir in $path
       do
-         cp /dev/null $mandir/whatis
+         touch $mandir/whatis.update
       done
    done
 fi
@@ -139,7 +128,7 @@
      if [ x$verbose != x ]; then
         echo "about to enter $mandir" > /dev/tty
      fi
-     if [ -s ${mandir}/whatis -a $pages = man -a x$update = x ]; then
+     if [ ! -f ${mandir}/whatis.update -a $pages = man -a x$update = x ]; then
         if [ x$verbose != x ]; then
            echo skipping $mandir - we did it already > /dev/tty
         fi
@@ -338,15 +327,12 @@
        then
          cat ${mandir1}/whatis >> $TMPFILE
        fi
-       sed '/^$/d' < $TMPFILE | sort | uniq > ${mandir1}/whatis
+       touch ${mandir1}/whatis.tmp
+       chmod 644 ${mandir1}/whatis.tmp
+       sed '/^$/d' < $TMPFILE | sort -u > ${mandir1}/whatis.tmp
 
-       chmod 644 ${mandir1}/whatis
-       rm $TMPFILE
+       mv -f ${mandir1}/whatis.tmp ${mandir1}/whatis
+       rm $TMPFILE ${mandir1}/whatis.update
      fi
    done
 done
-
-# remove the dir if we created it
-if [ $TMPFILE = $TMPFILEDIR/w ]; then
-	rmdir $TMPFILEDIR
-fi