mailing list archives
Re: Security problems on SCO's lp subsystem
From: belal () SCO COM (Bela Lubkin)
Date: Fri, 19 Jun 1998 12:42:46 -0700
Thanks to Marco Paganini & Michael L. Wilkerson Jr. for this report.
I've verified these two problems. Note that both of them require
special enabling conditions, which I describe below.
SCO OpenServer includes two spooling subsystems: the System V spooler
and the Berkeley spooler. Berkeley spooler support is split into client
and server support. By default, only SysV client support is active.
Berkeley client support is activated by root running `mkdev rlp`; or
through `scoadmin printer manager` (I haven't tested, but I believe the
option is "Printer -> Add Remote -> UNIX...").
Activating Berkeley client support causes certain binaries to change;
for instance, /usr/bin/lp changes from:
---x--s--x 1 bin lp 91044 Dec 16 1997 /usr/bin/lp
---x--x--x 1 bin lp 2472 Jun 19 11:09 /usr/bin/lp
Exact dates and sizes will vary by release, but the general pattern will
be the same. The Berkeley client version is a simple wrapper program
which actually execs /usr/lpd/remote/lp:
-rws--s--x 1 root daemon 36116 Dec 16 1997 /usr/lpd/remote/lp
If a Berkeley client destination hasn't been specified, that in turn
execs the original SysV lp client, which has been saved aside in
---x--s--x 1 bin lp 91044 Jun 19 11:09 /usr/lpd/local/lp
Also, in general, /etc/printcap will exist if and only if Berkeley
client support has ever been activated.
Both of these exploits require Berkeley client support to be active,
although the details are different.
SCO 5.0.4 Enterprise
(also) Plain Vanilla Intel
echo "test" > /tmp/rootfile
and the perms thereof are...
drwxrwxrwt 2 sys sys 1024 Jun 18 20:26 tmp
-rw-rw-r-- 1 root sys 5 Jun 18 20:26 rootfile
okay. now as a normal, unprivileged user, I run...
lpr -d lp -R /tmp/rootfile
...and to my displeasure, but as expected, the root-owned tempfile is
removed. (BTW, this normal user is NOT a member of the group, sys --of course).
This exploit only works if the destination is a Berkeley lpd client. In
practice this means that (1) /etc/printcap must exist, (2) it must have
an entry for the destination ("-d lp"), and (3) the spool directory
mentioned in the printcap entry must exist. These conditions normally
exist only if Berkeley client support has deliberately been activated by
This is even better, but only works if your lp subsystem has a file named
/var/spool/lpd/lock. With this file in place, the lp command will enable
the "-L live" option. With this, you can write to *any* file in the system.
And even better, the file will be mode 600, owned by root...
$ lp -L live=/any_file_in_the_system
And that's it. You can type anything you want/need.
One more time!
running "touch /var/spool/lpd/lock"
-rw-rw-r-- 1 root sys 0 Jun 18 20:41 /var/spool/lpd/lock
...now as the same normal user I run (with rootfile being an as of yet
lp -L live=/tmp/rootfile
Okay, then I enter whatever text I choose...and a ^D and bingo!
now "ls -l /tmp/rootfile" yields:
-rw------- 1 root lp 21 Jun 18 20:45 rootfile
Of course, the same normal user which created the file can now not even read it.
Again, this depends on the Berkeley client support being enabled.
The actual "-L=live" support is in the SysV client. However, it looks
for a file (/usr/spool/lpd/lock -- /var/spool is a symlink to
/usr/spool) which exists only when the Berkeley client is enabled.
Specifically, the directory /usr/spool/lpd is created by the Berkeley
client install; and /usr/spool/lpd/lock is created temporarily by
Berkeley client actions. The permissions on /usr/spool don't allow
users to create subdirectories; and /usr/spool/lpd's permissions do not
allow users to create the lock file, except as a temporary byproduct of
Even if you deliberately create /usr/spool/lpd/lock while the Berkeley
client isn't enabled:
# mkdir /usr/spool/lpd
# touch /usr/spool/lpd/lock
`lp -L live=filename` can only attack files writable by group "lp". The
root attack works because of the changed flow of control when Berkeley
client support is enabled. /usr/bin/lp execs /usr/lpd/remote/lp,
gaining setuid-root privileges. That then execs /usr/lpd/local/lp,
which is the original SysV lp client.
I would summarize these bugs as:
1. Berkeley `lp` client doesn't give up setuid/setgid privileges when
removing a file according to "-R" flag.
2. Berkeley `lp` client passes on setuid/setgid privileges to SysV
`lp` client, when a Berkeley lpd destination hasn't been specified.
3. SysV `lp` client doesn't give up setuid/setgid privileges before
opening target file for "-L live=file" flag.
4. "-L live=file" flag appears to be archaic, perhaps shouldn't exist
Not a pretty picture. I'll look into getting these fixed, and checking
for other related issues in these subsystems.