The 'Security Digest' Archives (TM)

Archive: About | Browse | Search | Contributions | Feedback
Site: Help | Index | Search | Contact | Notices | Changes

ARCHIVE: Unix 'Security Mailing List' - Archives (1984 - 1987)
DOCUMENT: Unix 'Security Mailing List' #5 1985-03-11 (1 file, 9754 bytes)
SOURCE: http://securitydigest.org/exec/display?f=unix/archive/005.txt&t=text/plain
NOTICE: securitydigest.org recognises the rights of all third-party works.

START OF DOCUMENT


Date: 11 Mar 1985 0020-MST (Monday)
Subject: Security Mail List,  # 5

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        Note: this issue was originally published on February 23. Due to
        lack of tmp space on ihnp4, it was dropped there. This is a reissue
        to those people.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Topics:
                     Admin and New people on the list
                     Nice general article on security
                       Quick fix for 'at' loopholes
                           Lets talk about kmem
                Why is setgid unsafe on some UNIX systems?
              Security of SUID programs (and shell scripts)
                    Re:  setuid shell script security
                      The security of symbolic links
                some security-related stuff in net.sources
                        Re: set-UID shell scripts


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Editor's Corner

        Sorry about the unseemly delay in getting this issue out; sys
        admin tasks apparently never end.  Here it is.
Newcomers to the list since last issue:

        Byron C. Howes (bch@ecsvax)
        Bill Welch (bill@jett)
        Jim Bloom (bloom@ucbvax)
        Jerry Cap (cap@bunker)
        Bill Blue (crash!bblue@ihnp4)
        Dave Eckhardt (dae@psuvax)
        David Grooms (dbg@u1100a)
        David Grossman (dpg@busch)
        George Goebel (ghg@pur-ee)
        Guy Harris (guy@rlgvax)
        Hokey (hokey@gang)
        Jennine (jennine@cithep)
        John Blair (johnb@neoucom)
        Jim Ellis (jte@mcnc)
        John Pierce (jwp@sdchema)
        Kirk Smith (ks@pur-ee)
        Mark J. Aitken (mark@uoregon)
        Barbara Petersen (pbmnms!barb@dual)
        Scott Preece (preece@ccvaxa)
        Richard Foulk (richard@bigtuna)
        Richard Kelly (rpk@ecsvax)
        Rob Warnock (rpw3@redwood)
        Robert W. Henry (rwh@ucbvax)
        Maureen Chew (scirtp!root@rti-sel)
        Scott Orshan (sdo@u1100a)
        Mike Speck (security@cit-vax)
        Craig Good (security@dagobah)
        Seth Alford (setha@teklds)
        Steve M. Kramer (smk@axiom)
        Steve Lazarus (sml@wdl1)
        Mark Starner (starner@psuvax)
        Tim Smith (tim@callan)
        Bob Tomlinson (tomlin@dspo)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Date: Fri, 1 Feb 85 15:45:00 pst
From: ihnp4!ucbvax!ucscc!haynes@ucsce.ucscc.UUCP (00005000)
Subject: Nice general article on security

in IBM Systems Journal, vol 23, no 4, l984

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Date: Mon, 4 Feb 85 12:23:03 pst
From: ihnp4!ucbvax!ucscc!root (00050000)
Subject: Quick fix for 'at' loopholes
        
        We decided it was advisable never to let atrun run a submission by
        root.  The super user can always use crontab for his after hours work.
        
        In /usr/src/usr.lib/atrun.c:
                ...
                if (stat(file, &stbuf) == -1)
                        exit(1);
        #ifdef  UCSC
                        /* don't run any jobs as root */
                if(stbuf.st_uid == 0)
                        exit(2);
        #endif  UCSC
                if (pid = fork()) {
                ...
        
        ucbvax!ucscc!haynes

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Date: Wed, 6 Feb 85 15:39:48 pst
From: ihnp4!uw-beaver!entropy!dataio!bossert (John Bossert)
Subject: Lets talk about kmem

Would someone describe the security hole that exists when /dev/kmem
is readable by the world?  What is the fix?  What programs need to
be chmod'ed to continue to work?

        John Bossert, Data I/O Corporation, Redmond WA
        uw-beaver!entropy!dataio!bossert

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Date: Tue, 29 Jan 85 15:42:00 est
From: Tom Truscott <hao!hplabs!trt%rti-sel@MCNC>
Subject: Why is setgid unsafe on some UNIX systems?

Here is a Usenet article on that subject posted in late 1981:
--------
For security reasons, any set-group-id program should also be set-user-id.

I can think of only two reasons for a SGID-only program:
A) To limit the damage that would result from a security breach.
        For example, ps(I) and df(I) would be SGID and
        the disks and /dev/mem group-readable.
B) To access a restricted file by programs having different uids.
        uucp(I) and cu(I) could be owned by different uids
        but both have the same gid as /dev/acu so calls can be made.

Unfortunately, SGID-only programs are a security hole in UNIX-V7 & 4.1BSD.
Simply run such a program and cause it to core dump.
The core file will be owned by you but the group will be the SGID.
(James Ellis (mcnc!jte) says this is one of several core dump bugs.)
Then "cp /bin/sh core; chown +x core; chown g+s core".
(I consider the success of the second chown to be a bug.)
The result is a SGID shell.

Consider the empire game, which if SUID "is not able to redirect output
of a command to a [user] file." [sri-unix.1410]
Indeed, the users are "limited" to writing on the game score files,
the empire program itself, and other files owned by the empire uid.
Some view this state of affairs as a annoying misfeature.
I consider it a security hole,
and one which cannot be fixed by making empire SGID instead.
All too often a SGID program is just a buggy SUID program
that was "corrected" with chmod.

File I/O or program execution which is requested by the RUID
*should be done as the RUID*, which usually means fork(II)ing
a child which reverts permissions and then does the I/O or execution.
It is surprisingly difficult to write secure SUID programs.
A paper on how to write SUID programs, with assisting library routines,
would be a great help.
        Tom Truscott (duke!trt)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Date: Tue, 29 Jan 85 16:18:13 est
From: Tom Truscott <hao!hplabs!trt%rti-sel@MCNC>
Subject: Security of SUID programs (and shell scripts)

What follows is a three-year-old Usenet article (late 1981, I think).
It covers many of the SUID issues that have been raised recently,
so I thought it would be of interest.

---------

           On the Correctness of Set-User-ID programs
                     Tom Truscott (duke!trt)
                     James Ellis  (duke!jte)

The set-user-id (SUID) capability is a patented feature of UN*X,
and is used by many programs (including Duke's Usenet news
program), yet we know of no document which describes how to write
secure SUID programs.  This is not intended to be such a
document; rather, we want to discuss some of the pitfalls that
await designers of such programs.  This is partially motivated by
the recent interest in unix-wizards about SUID programs and shell
scripts.

SUID programs require particular attention to make sure that they
work correctly.  This is partly due to their nature: they often
control access to a database shared by many users, so a foul-up
affects many people, not just one.  It is also partly due to the
danger of subverting the powers of the SUID.

The SUID given a program should be as restricted as possible.  If
Duke news ran as "root", and a security hole were found, the
entire system could be compromised.  Ideally news should have a
SUID used by no other processes or files.

                           SUID glitch
Most UNIX systems do not honor the SUID bit of a process when it
is invoked by root.  We consider this to be a bug.  In such
cases, creat(II)ed files will be owned by root, not the SUID, so
chown(II) should be used as necessary.

                             Locking
Many SUID programs need mutually exclusive access to a resource.
The UNIX manual suggests that creat(II) with mode 0 be used to
provide locking, but that technique fails when the effective uid
is root.  We recommend link(II)ing the file ".lock" (e.g.) to
some permanently allocated file.  The link(II) will fail if
".lock" already exists, in which case the program can retry the
link(II) every few seconds until it succeeds.  After the resource
has been used, unlink(II)ing ".lock" frees it.  The UNIX-V7
passwd(I) program does not lock writing on /etc/passwd, which is
why that file can be scrambled if two passwd(I)s run at the same
time.

                   Recovering from Dead Locks
The locking method described above can be improved somewhat.  If
the link(II) fails, the program should determine the cause.  If
"errno" is not EEXIST (".lock" exists) then something is wrong
with the locking system, such as the program not actually being
SUID.  If ".lock" does exist it is still possible that the
resource is no longer being used but the last user failed to free
it.  Suppose it is known that the resource will never be in use
for longer than N seconds.  Then if the st_ctime of stat(II)
shows that ".lock" was last touched more than N seconds ago it
can be assumed that the resource is going unused.  The program
can then free the resource (unlink(II) ".lock"), wait a few
seconds (to avoid a race), and then retry locking the resource.

Needless to say, this is not the last word in locking!  It should
be kept in mind that the complexity is not in locking per se but
rather in recovering from a breakdown in the protocol.  The
breakdown may be symptomatic of far worse problems which cannot
be solved by deleting some lock.

                      Insecurity in General
One way to subvert a SUID program is to take advantage of a
common programming error, such as failure to check an array
bound.  The famous UNIX-V6 login(I) bug is an example of this.
Also, the user profile program provided in Amdahl's Unix (UTS)
permits users to change their comment field to a (unchecked)
character string.  Since this information is in /etc/passwd, one
can add bogus user-ids with any desired permissions.  Obviously,
SUID programs must be "suspicious" and have complete error
checking of user-supplied arguments and input data.

A more direct danger is that the program might perform file I/O
or execution for the user (RUID) without first resetting the
effective id.  Some versions of the empire, snake, and adventure
games have this problem.  (For example, run adventure and type
"!sh".) We recommend that the program fork(II) and the child do
setgid(II) and setuid(II) to the RUID before doing any I/O or
program execution.  The child should also restore umask(II) and
environ(V) to their original values--see below.  The parent,
which retains SUID permission, can wait for the child to finish.
This could be a standard library routine.

Steve Bellovin has pointed out the danger of an RUID child
process inheriting sensitive open files.  Such files should be
closed before an exec(II), either via close(II) or the UNIX-V7
FIOCLEX parameter of ioctl(II).

The signal(II) system call causes another kind of problem.  If a
program fails to catch or ignore a user-causable signal such as
SIGINT then it might be terminated in a way that leaves files in
an unintended state.  Actually, in most versions of UNIX,
catching ANY user-causable signal allows the user to terminate
the program at will since caught signals are reset (at least
temporarily).  For example, Duke news fails to catch SIGPIPE, and
it *does* catch SIGINT (equally wrong).

                       Resource Exhaustion
SUID programs can often be subverted if a needed resource is
unavailable.  For example, UNIX-V6 su(I) provided a super-user
shell if it was unable to open /etc/passwd.  It is easy to invoke
su(I) with all available file descriptors taken.  We recommend
that programs use close(II) to ensure there are free file
descriptors.  Other resources include file storage space and
process limits.  Even the program's address space can be adjusted
through the size of the argument list and the environment.

                      Insecurity in UNIX-V7
UNIX-V7 added several features which complicate SUID programs.
First, the program should disable a pending alarm(II), which
might otherwise cause undesired program termination.  Second, it
should set umask(II) to an appropriate value.  Third, the
exec[lv]p(II) calls are convenient, but should never be executed
as the SUID without first restricting the environ variable PATH
as necessary.  Fourth, any exec(II) call is potentially dangerous
as it may pass along the inherited environment.  This will be
considered in detail later.  We recommend changing environ to
just PATH=/bin:/usr/bin.  Both the old umask and environ values
should be saved so they can be restored for file I/O or execution
as the RUID.

Programs should not depend upon the distributed getlogin(III) or
ttyslot(III), which can be misled by rearranging file
descriptors.  There is no reliable way to determine the
controlling terminal or the login name, yet some SUID programs
try anyway.  UNIX-V7 mail(I) uses getlogin(III), making it
possible to fake the origin of a letter.  UNIX-V7 login(I) uses
ttyname(III) to approximate the controlling terminal, so:
        /bin/login ken 0> /dev/tty45
logs "ken" onto tty45 if it is writable.  The super-user might
have been on tty45 but will probably be unaware that someone else
now owns the terminal.  (A shell bug prevents 0> from working,
but a C program will prove the theory.) Duke avoids this problem
since users cannot run login(I) directly; instead, they must log
off and back on.  Thus login(I) is invoked only by /etc/getty and
need not be SUID.

Publicly writable directories such as /tmp are almost totally
insecure and should be avoided.  The UNIX-V7 mail(I) program
suffers, at least in theory, due to this.  The distributed
at(I)/atrun program suffers totally:
        cd /usr/spool/at
        umask 0
        passwd
        : Type ctrl-\, producing a 666 core file owned by root.
        cp bad.deed core
        mv core 81.229.000.57;  : works since directory is writable
The resulting file will be executed with root permissions.  To
avoid this problem /usr/spool/at must not be generally writable
and at(I) must be slightly modified so it can be (safely) run
SUID to root.

                     Insecurity in the Shell
The shell(I) is particularly vulnerable when SUID since it
derives much of its power from information that was inherited or
passed via the environment.  For example, the umask value must be
reset if secure files are to be created.  Also, since there is no
direct way for a shell script to close files or reduce the
environment, this burden is placed on every command it execs.  If
the environment is almost full and the shell adds say, PATH, then
it will be unable to exec any programs at all.

Obviously, PATH should be reset in every SUID shell script.
Careful examination must also be made of other variables used by
the shell such as HOME, MAIL, and arguments ($1, ...).  Filename
expansion and blank interpretation can open security holes.  Much
worse is the shell variable IFS (which we recommend be
eliminated).  Unless this variable is reset, it is easy to change
the innocuous
                echo "Enter Password"
into a SUID editor command!

More serious still is the shell's understanding of login
procedures.  Simply exec your favorite SUID shell script with the
name "-" and it will blithely execute commands from ".profile" in
the current directory.  Having the shell use HOME/.profile is no
help at all.  Even using the effective user's login_dir/.profile
is not much better unless that file is written very carefully.

It is important to note that the problems we have discussed can
apply to non-SUID programs as well.  Not only must SUID programs
and scripts be carefully written, but also any otherwise
unprivileged programs which they run.  A SUID program which execs
some shell script by a full path name has not avoided the PATH
pitfalls!

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

From: hpda!ucbvax!sdcsvax!sdchema!jwp
Date: Sat, 19 Jan 85 13:34:51 pst
Subject: Re:  setuid shell script security

[My apologies for the length of this.  Since I didn't know the experience level
of everyone who would receive it, I thought it best to be fairly explicit.]

The problem recently under discussion in net.unix involves links to set[ug]id
scripts.  For a demonstration, become root and use the following commands:

        cp /usr/pub/ascii /tmp/JUNK
        chmod 600 /tmp/JUNK
        ( echo \#\! /bin/sh ; echo date ) > /tmp/sh.script
        ( echo \#\! /bin/csh ; echo date ) > /tmp/csh.script
        chmod 4755 sh.script csh.script

Now login as, for example, guest and use the following commands:

        cd /tmp
        ln sh.script -
        -
        cat /tmp/JUNK

and note that you've now got a super-user shell.  "sh" and "csh" assume that
they're a login shell, and take input from the terminal, if argv[0][0] == '-'.
This is particularly insidious in 4.2 where you can do, e.g.,

        ln -s /tmp/csh.script ~/-

Since this is a logical consequence of the documented behavior of execve(2),
the shells, and the setuid/setgid modes it's probably incorrect to call it a
"bug", but it's behavior that I don't want.  It's a problem not only for root
users, but also (perhaps worse?) for the "semi-neophyte" who is earnestly
trying to solve her/his own problems without bugging the system programmers.
My boss is a good example:  he made a script setuid to himself to allow his
secretary to print out certain specific files for him, thus blowing away any
possible security on his other files as well.

This is easy to fix in the shells' source, but I know of no binary-only fix.
Some work is being done in an effort to find one, but I do not expect it to be
successful.

For csh, in src/bin/csh/sh.c, near the top, there is a line that reads:

        loginsh = **v == '-';

This is where you need to take action, and any number of things will do:

        if(loginsh)
                {
                setuid(uid);
                setgid(getgid());
                }
---------------
        if(loginsh && (uid != geteuid() || getgid() != getegid()))
                {
                /* reset uid/gid, blow this shell away, whatever ... */
                }
---------------
        if(loginsh && c != 1)
                {
                /* Do whatever you want.  The test is clever but obscure. */
                }
---------------
For sh, the fix is analogous.  At the top of src/bin/sh/main.c, before any
other code is executed, insert something like:

        if(v[0][0] == '-')
                {
                /* test uid/gid, reset them, whatever you want */
                }

If you're going to fix the shells, you might want to also get the hole that
lets "#! /bin/csh" files read the user's .cshrc with the owner's permissions.
I realize that can be avoided with "!# /bin/csh -f" but I'm trying to protect
neophytes here.  In src/bin/csh/sh.c look for code that says

        setexit();
        haderr = 0;             /* In case second time through */
        if (!fast && reenter == 0) {
                reenter++;
                /* Will have value("home") here because set fast if don't */
                srccat(value("home"), "/.cshrc");
                if (!fast && !arginp && !onelflg)
                        dohash();

It'll be around line 300 in the original (it's difficult for me to tell with
all the code we've already added).  The problem is caused by the unprotected
"srccat(value..." line.  I changed that to

                if(getuid() == geteuid() && getgid() == getegid())
                        srccat(value("home"), "/.cshrc");

I've been unable to create a similar problem with sh and .profile files, but I
may have missed something.

One person I know of has patched the kernel to fix this problem.  I didn't
ask exactly what he did; I presume he forbade either set-id scripts or links
to them.  In my environment, at least, that seems unnecessary (and I prefer
philosophically to fix user-level program problems without hacking the kernel).
The former is easy enough, but eliminates a possible feature.  The latter would
seem to be difficult on 4.2 without changing the semantics of symbolic links
(since there's currently no requirement that the target of a symbolic link
exist).  [And there may be some other way I haven't thought of yet.]

Fixing these holes *should not* be taken imply that set-uid scripts are now
safe.  They are not, and they should only be used with caution, if at all.
Firm control of $PATH, $IFS, other variables, and aliases, should be exercised.
There are probably other holes in them that I don't know about.

Also, I would like to encourage people to join Lyle McElhaney's security
mailing list.  He can be contacted as ihnp4!denelcor!security.  That sort
of information sharing benefits us all.

                                -- John Pierce, Chemistry, UC San Diego
                                   {sdcsvax,decvax}!sdchema!jwp

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Date: Thu, 7 Feb 85 18:58:04 est
From: Tom Truscott <hao!hplabs!trt%rti-sel@MCNC>
Subject: The security of symbolic links

>This problem with symbolic links is even more detrimental to the
>security and health of the O/S.   ...
[The examples given involved renaming files in /tmp (or elsewhere)
to fool SUID (or in general not-your-ID) programs.]

I think symbolic links have had a lot of bad press concerning security.
In this case, the real problem is that a not-your-ID program
places trust in something (the names/contents of files in some directory)
that you can control.
The link(II) system call can replace symlink(II) in every given example
except of course links cannot cross filesystems
(and please don't tell me that is a security feature!).
Also, there are plenty of ways to subvert users of /tmp without
resorting to linking at all.

My pat answer to problems of this type has been
"Generally writable files are inherently insecure."
But the problem with 4.1 mkdir suggests a more general rule:
"Do not trust what others can alter" (hum, doesn't have a good ring to it).

There may be security problems with symbolic links, but this one is not.
Symbolic links just make existing security problems more evident.
I guess that means symbolic links are a security feature!
        Tom Truscott

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Date: Wed, 13 Feb 85 12:36:16 mst
From: denelcor!lmc
Subject: some security-related stuff in net.sources


There have been some rather handy things passed through net.sources
in the last 6 months. The first was an addition to login.c which used
a trigram analysis to eliminate words that "look" like english
words (I'm sorry, I incorporated the change and lost the header; I
donn't know who sent it out). Two more things showed up in the last
two weeks; joetest (<215@pyramid.UUCP>) and genp (<325@lsuc.UUCP>).
Joetest is a shell script which examines the assword file to find those
who have used their own login id as their password. It is a little
simple minded, but it could serve as the basis for something a little
more substantial. Genp is a password generator, which generates
pronouncible nonsence words for passwords. With a little tweaking, it
could be made to work in conjunction with the trigram analysis above
to generate good passwords.

I have them; if there are many requests I will insert them in the list.

Lyle

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

From: denelcor!brl-bmd!gwyn@brl-vld.arpa
Date:     Wed, 13 Feb 85 20:20:20 EST
Subject:  Re: set-UID shell scripts

I had some correspondence that has convinced me that there is no way
to make set-UID shell scripts "safe" without reworking major portions
of the shell.  The root of the trouble is that the shell was not
designed to be paranoid about security, so it has too many loopholes.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

                    The UNIX security issues mail list

               Ignore the headers on this list and mail to:
           ...denelcor!security            (mail for the list).
            ...denelcor!sec-request         (administrativia).

END OF DOCUMENT