cops_104/ 755 313 12 0 5156725451 5354 cops_104/MANIFEST 755 313 12 6234 5156725205 6577 File Name
==================
MANIFEST # this file
README.1 # README.{1,2,3} are various docs for the package
README.2.pl
README.2.sh
README.3
README.FIRST # absolutely read this one first!
XTRA_CREDIT # contributors, etc.
bug.chk
bug.chk.aix
bug.chk.apollo
bug.chk.dec
bug.chk.next
bug.chk.sgi
bug.chk.sun
bug.chk.svr4
bug_cmp
checkacct
chk_strings
cops # the main thingee, head honcho, etc.
cops_filter
cover_letter # overview of changes, etc.
crc.chk
crc_list
cron.chk
dev.chk
disclaimer # don't sue me
ftp.chk
group.chk
init_kuang
is_able.chk
is_able.lst
kuang
kuang.pl.shar
makefile
misc.chk
pass.words
pass_diff.chk
passwd.chk
patchlevel.h
platform
quick_start
rc.chk
reconfig
res_diff
root.chk
suid.chk
suid.stop
yp_pass.chk
carp/How2Change
carp/README
carp/carp
carp/carp.1
carp/carp.anlz
carp/carp.anlz.1
carp/carp.awk
carp/carp.table
carp/carp2ps
carp/carp2ps.1
checkacct/Article
checkacct/Intro
checkacct/Makefile
checkacct/README.FIRST
checkacct/bsd.m4
checkacct/ca.src
checkacct/chkacct.1l
checkacct/dotwrite
checkacct/effect.dotwrit
checkacct/effect.owners
checkacct/effect.read
checkacct/effect.rhosts
checkacct/effect.setuid
checkacct/effect.write
checkacct/owners
checkacct/prm.mm
checkacct/prompt.help
checkacct/readable
checkacct/rhosts
checkacct/rhosts.pl
checkacct/setuid
checkacct/sysV.m4
checkacct/write
docs/COPS.report
docs/COPS.tex
docs/CRC.README
docs/KUANG.README
docs/SUID.README
docs/bug.chk.1
docs/cops
docs/cron.chk
docs/dev.chk
docs/ftp.chk
docs/group.chk
docs/home.chk
docs/is_able
docs/is_able.chk
docs/is_writable
docs/kuang.1
docs/kuang.man
docs/makefile
docs/misc.chk
docs/obligitory.album
docs/obligitory.joke
docs/pass.chk
docs/pass_diff.chk
docs/passwd.chk
docs/rc.chk
docs/readme.C2
docs/readme.apollo
docs/readme.filter
docs/readme.ibm
docs/readme.sequent
docs/readme.shadow
docs/readme.svr4
docs/readme.xenix
docs/readme.yp
docs/release.notes
docs/root.chk
docs/suid.man
docs/tilde
docs/user.chk
docs/warnings
extensions/THINGS_2_DO
extensions/YAR
extensions/crypto-stuff
extensions/netstuff
extensions/passwords
extensions/questions
extensions/uucp.hardening
extensions/writing.suid
extra_src/README
extra_src/bad_dir.pl
extra_src/diff_last.sh
extra_src/mail.chk
extra_src/pass.mail
extra_src/rhosts_sweeper
extra_src/stop.make
extra_src/trust.pl
extra_src/uucp_1.shar
extra_src/uucp_2.shar
extra_src/uucp_quick.chk
perl/README.kuang
perl/README.sgi
perl/chk_strings
perl/chk_strings.pl
perl/cops
perl/cops.cf
perl/cops.cf.orig
perl/cron.chk
perl/dev.chk
perl/fgrep.pl
perl/file_mode.pl
perl/file_owner.pl
perl/ftp.chk
perl/get-cf
perl/getopts.pl
perl/glob.pl
perl/group.chk
perl/hostname.pl
perl/is_able.chk
perl/is_able.lst
perl/is_able.pl
perl/kuang
perl/kuang.1
perl/misc.chk
perl/pass.cache.pl
perl/pass.chk
perl/passwd.chk
perl/pathconf.pl
perl/pathconf.sh
perl/prl.patch
perl/rc.chk
perl/reconfig.pl
perl/root.chk
perl/rules.pl
perl/shadow.sh
perl/stat.pl
perl/suckline.pl
perl/suid.chk
perl/suid.stop
perl/user.chk
perl/yagrip.pl
src/addto.c
src/clearfiles.c
src/conf.h
src/crack-fcrypt.c
src/crack-lib.c
src/crack.h
src/crc.c
src/crc_check.c
src/filewriters.c
src/home.chk.c
src/is_able.c
src/is_something.c
src/members.c
src/pass.c
src/tilde.c
src/user.chk.c
cops_104/bug.chk 700 313 12 6713 5156725206 6703 #!/bin/sh
#
# bug.chk [arch]
#
# This uses publically available (available via anon-ftp from
# cert.sei.cmu.edu) data to determine if a security bug is present. It
# checks the date of the program in question against the cert advisory
# date, and, if it is older than that, it flags it as a potential
# bug/vulnerability.
#
# Right now, it either uses your argument as an archetecture type, or
# tries to figure out what kind of platform you're running
# on, and then looks at the bugs known for your host, in a file named
# "bug.chk.arch_type".
#
ECHO=/bin/echo
TEST=/bin/test
GREP=/bin/grep
LS=/bin/ls
LS_OPTS="-slagL"
AWK=/bin/awk
SH=/bin/sh
DATE=/bin/date
# the bug comparison module; current vs. bug date
BUG="$AWK -f ./bug_cmp"
# Do you decend from 4.3 BSD?
bsd43=yes
platform="./platform"
if $TEST ! -f ./bug_cmp ; then
$ECHO "Must have bug compare module, ./bug_cmp, to run..."
exit 2
fi
# what is the date? We just need the month and year...
# Format: Fri Feb 7 14:16:55 PST 1992
real_date=`$DATE | $AWK '{print $2, $NF}'`
# what kind of machine are we on?
#
if $TEST "$1" != "" ; then
host_type=$1
else
host_type=`$platform`
fi
#
# Do a few (old) generic checks, then go to machine specific drek...
#
#
# Generic sendmail problem -- worm used this...
sendmail="/usr/lib/sendmail"
fix_date="1 Dec 1988"
cert_advis="CA-88:01"
if $TEST -f "$sendmail" ; then
cur_date=`$LS $LS_OPTS $sendmail | $AWK '{print $8, $7, $9}'`
$ECHO $sendmail $fix_date $cur_date $cert_advis $real_date | $BUG
fi
#
# If running BSD based stuff, check login, fingerd, and ftpd,
# plus the more recent rdist hole.
login="/bin/login"
all_locations="/etc /bin /usr/bin /usr/etc /usr/ucb"
if $TEST "$bsd43" -eq "yes" -a -f "$login" ; then
fix_date="21 Dec 1988"
cert_advis="CA-89:01"
cur_date=`$LS $LS_OPTS $login | $AWK '{print $8, $7, $9}'`
$ECHO $login $fix_date $cur_date $cert_advis $real_date | $BUG
for location in $all_locations ; do
# have to check for sun's naming schema also...
if $TEST -f "$location/ftpd" ; then
ftp="$location/ftpd"
elif $TEST -f "$location/in.ftpd" ; then
ftp="$location/in.ftpd"
fi
if $TEST -f "$location/fingerd" ; then
finger="$location/fingerd"
elif $TEST -f "$location/in.fingerd" ; then
finger="$location/in.fingerd"
fi
if $TEST -f "$location/rdist" ; then
rdist="$location/rdist"
fi
done
cur_date=`$LS $LS_OPTS $ftp | $AWK '{print $8, $7, $9}'`
$ECHO $ftp $fix_date $cur_date $cert_advis $real_date | $BUG
cur_date=`$LS $LS_OPTS $finger | $AWK '{print $8, $7, $9}'`
$ECHO $finger $fix_date $cur_date $cert_advis $real_date | $BUG
#
# rdist is special
#
# These vendors are *not* affected: Amdahl, AT&T System V,
# Data General DG/UX for AViiON Systems, Sequent Computer Systems
# (note they will begin to ship rdist in February 1992, but
# it will be the corrected version)
#
fix_date="22 Oct 1991"
# Sun put out another one after that date... you probably want
# this date instead...
fix_date="23 Oct 1991"
cert_advis="CA-91:20"
cur_date=`$LS $LS_OPTS $rdist | $AWK '{print $8, $7, $9}'`
$ECHO $rdist $fix_date $cur_date $cert_advis $real_date | $BUG
fi
# host specific ones....
if $TEST -n "$host_type" ; then
if $TEST -f "./bug.chk.$host_type" ; then
$SH ./bug.chk.$host_type $real_date
else
# check to see if I'm a sun...
$ECHO $host_type | $GREP "sun" > /dev/null
if $TEST $? -eq "0" ; then
./bug.chk.sun $real_date
else
:
# $ECHO Bug list for $host_type not found...
fi
fi
fi
# finis
# on, and then looks at the bugs known for your host,cops_104/README.1 600 313 12 26707 5156725206 6502
Welcome! You now hold in your hands (terminal?) a collection of
security tools that are designed specifically to aid the typical UNIX
systems administrator, programmer, operator, or consultant in the
oft-neglected area of computer security.
If you're the kind of boy/girl/rock who thinks "man pages are for
weenies, let's type 'make' and run the damn thing," then you might read
one file, "quickstart", for a lightning-fast intro. Otherwise, reading
this now might prove enlightening.
The package, which will henceforth be referred to as COPS (Computer
Oracle and Password System), can be broken down into three key parts.
The first is the actual set of programs that attempt to automate
security checks that are often performed manually (or perhaps with self-
written short shell scripts or programs) by a systems administrator.
The second part is the documentation, which details how to set up,
operate, and interpret the results of the programs. It also includes a
paper or two on COPS itself. Third, COPS is an evolving beast, so it
includes a list of possible extensions that might appear in future
releases. In addition, it includes some short papers on various topics
in UNIX security and pointers to other works in UNIX security that could
not be included at this time, due to space or other restrictions.
This document contains four sections:
1) What is COPS?
2) What is COPS _not_?
3) Installation, Execution, and Continuing Use of COPS
4) Disclaimer and End Notes
1) What is COPS?
-----------------
The heart of COPS is a collection of about a dozen (actually, a few
more, but a dozen sounds so good) programs that each attempt to tackle
a different problem area of UNIX security. Here is what the programs
currently check, more or less (they might check more, but never less,
actually):
o file, directory, and device permissions/modes.
o poor passwords.
o content, format, and security of password and group files.
o the programs and files run in /etc/rc* and cron(tab) files.
o existance of root-SUID files, their writeability, and whether or not
they are shell scripts.
o a CRC check against important binaries or key files to report any
changes therein.
o writability of users home directories and startup files (.profile,
.cshrc, etc.)
o anonymous ftp setup.
o unrestricted tftp, decode alias in sendmail, SUID uudecode problems,
hidden shells inside inetd.conf, rexd running in inetd.conf.
o miscellaneous root checks -- current directory in the search path,
a "+" in /etc/host.equiv, unrestricted NFS mounts, ensuring root is
in /etc/ftpusers, etc.
o dates of CERT advisories vs. key files. This checks the dates that
various bugs and security holes were reported by CERT against the
actual date on the file in question. A positive result doesn't
always mean that a bug was found, but it is a good indication that
you should look at the advisory and file for further clues. A
negative result, obviously, does not mean that your software has no
holes, merely that it has been modified in SOME way (perhaps merely
"touch"'ed) since the advisory was sent out.
o the Kuang expert system. This takes a set of rules and tries to
determine if your system can be compromised (for a more complete list
of all of the checks, look at the file "release.notes" or
"cops.report"; for more on Kuang, look at at "kuang.man".)
All of the programs merely warn the user of a potential problem --
COPS DOES NOT ATTEMPT TO CORRECT OR EXPLOIT ANY OF THE POTENTIAL
PROBLEMS IT FINDS! COPS either mails or creates a file (user
selectable) of any of the problems it finds while running on your
system. Because COPS does not correct potential hazards it finds, it
does _not_ have to be run by a privileged account (i.e. root or
whomever.) The only security check that should be run by root to get
maximum results is the SUID checker: although it can be run as an
unprivileged user, it should be run as root so that it can find all the
SUID files in a system. In addition, if key binaries are not
world-readable, only executable, the CRC checking program ("crc.chk")
needs to be run as a privileged user to read the files in question to
get the result.) Also note that COPS cannot used to probe a host
remotely; all the tests and checks made require a shell that is on the
host being tested.
The programs that make up COPS were originally written primarily in
Bourne shell (using awk, sed, grep, etc.) for (hopefully) maximum
portability, with a few written in C for speed (most notably parts of
the Kuang expert system and the implementation of fast user home
directory searching), but the entire system should run on most BSD and
System V machines with a minimum of tweaking. In addition, a perl
version is included that, while perhaps not as portable as the shell/C
version, has some advantages.
COPS includes various support programs as well. The primary one is
CARP (COPS Analysis and Report Program). CARP is a results interpreter
that is designed to analyze and generate a summary on various COPS reports
from a complete network or set of hosts.
2) What is COPS _not_?
-----------------------
COPS mostly provides a method of checking for common procedural
errors. It is not meant to be used as a replacement for common sense or
user/operator/administrative alertness! Think of it as an aid, a first
line of defense, not as an impenetrable shield against security woes.
An experienced wrong-doer could easily circumvent *any* protection that
COPS can give. However, COPS *can* aid a system in protecting its users
from (their own?) ignorance, carelessness, and the occasional malcontent
user.
Once again, COPS does not correct any errors found. There are
several reasons for this: first and foremost, computer security is a
slippery beast. What is a major breach in security at one site may be a
standard policy of openness at another site. Additionally, in order to
correct all problems it finds, it would have to be run as a privileged
user; I'm not going to go into the myriad problems of running SUID shell
scripts (see the bibliography at the end of the technical report
"cops.report" for pointer to a good paper on this subject by Matt
Bishop; look at the included paper "SU" for pointers on how to write a
SUID program) -- suffice to say it's a bad idea that can give an
attacker privileges equal to whatever account the shell is SUID to.
3) Installation, Execution, and Continuing Use of COPS
-------------------------------------------------------
There are two versions of COPS that can be run. The original ("COPS
classic"?) needs nothing more than a C compiler and the standard shell
tools that any (or most any) UNIX system should have: awk, sed, grep,
etc. For information on how to configure and run this version, look at
the file "README.2.sh". The most important thing to do is to run the
shell program "reconfig" if you have a system V or a non-standard
Berkeley UNIX system -- the paths to the programs that COPS uses are
hard-coded, and this will reconfigure the paths so that COPS can find
these programs.
If you have installed perl on your system (I think it works with perl
versions > 3.18) and would like to try the perl version, look at the
file "README.2.pl" for details on how to use that. There are several
advantages and disadvantages to using the perl version, so if you have
perl, I would advise trying both packages to see which one better suits
your environment.
If you need help to interpret the results of COPS, look in the file
"warnings", in the "doc" directory. All of the individual programs in
the COPS package have a man page there as well.
For continuing use, multiple architecture sites, or other advanced
COPS topics, check out "README.3".
There are additional "readme" files for the following topics: Apollo
and Xenix machines, C2 and other shadow passord files, NIS/Yellow Pages,
and the COPS filter. Look at the corresponding readme (note lower case)
file for these in the "docs" directory -- e.g. "docs/readme.apollo."
4) Disclaimer and End Notes
----------------------------
COPS is meant to be a tool to aid in the tightening of security, not
as a weapon to be used by an enemy to find security flaws in a system.
It may be argued that allowing anyone to have access to such a tool may
be dangerous, but hopefully the overall benefit for systems that use
this package will outweigh any negative impact. To me it is akin to a
law enforcement problem -- although telling the public how to break into
a house may foster a slight rise in break-in attempts, the overall rise
in public awareness of what to defend themselves against would actually
result in a drop in break-ins. The crackers with black hats already
know how to crush system defenses and have similar tools, I'm sure.
It's time we fought back.
COPS is not the final answer to anyone's security woes. You can use
the system as long as you realize that COPS has no warranty, implied or
otherwise, and that any problems that you may have with it are not my or
any of the other authors' fault. I will certainly attempt to help you
solve them, if I am able. If you have ideas for additional programs or
a better implementation of any of the programs here, I would be very
interested in seeing them. COPS was the work of a LOT of people, both
in writing code and in the testing phase (thanks, beta testers!). For a
complete list of contributors, look at the file "XTRA_CREDIT".
So, good luck, and I hope you find COPS useful as we plunge into UNIX
of the 1990's.
dan farmer
January 31, 1989
(Now January 31, 1990)
(Now November 17, 1991... how time goes on...)
# include "./disclaimer"
p.s. Just for snix, here are some of the machine/OS's I know this
sucker works on; far and away the most common problem was getting that
stupid password cracking program to compile, followed by systems without
the -ms package to nroff. Some minor problems with config files -- I
*think* these are all ok:
DECstation 2100, 3100, 5000, Ultrix 2.x, 3.x, 4.x (Ultrix is braindead.)
Sun 3's, 4's (incl. Solbourne and clones) -- 3.x, 4.x
Gould 9080 Powernode, hacked up Gould OS (whatever it is)
sequent S-87 symmetry, dynix V3.x (both att & bsd universes; att required
"BRAINDEADFLAGS = -lcrypt" to be uncommented.
ETA-10P, Sys V R3 based
Convex boxes, all types, OS's (up to 9.x, the most recent)
Apollo dn3000 & dsp90, Domain SR 9.7, 10.x (see "readme.apollo")
Vax 11/780, 4.x BSD (Mt. Xinu, tahoe and stock)
Vaxstation, MicroVax, Vax 6320 & 8800, Ultrix 2.x, 3.x, 4.x
HP900/370, HP-UX 6.x, 7.x
Cray 2 & Y-MP, UNICOS 5.x, 6.x
Amdahl 5880, UTS 580-1.2.3
SGI 2500's, IRIX GL 3.6
SGI 4D's, IRIX System V Release 3.x
'286 & '386 Boxes, running Xenix (see "readme.xenix")
AT&T 3B2 & 3B1, SysVR[3-4]
CADMUS box (R3000 & 68020 cpu), SysVR3.2
Pyramid, running 4.4c and 5.1a
Apple Mac IIci, running AUX 2.x. The "test -z" seemed broken on this,
but I only had a brief chance to test it out, but kuang didn't like it
as a result. I'll get a working version soon; everything seemed ok
(change the /etc/servers line in "misc.chk").
NeXT, 1.x
(password stuff is different on this machine, though; cracking is
strange. Diffs anyone? Also, /bin/test vs. shell builtin "test" is
*weird*.)
Multimax 320, 12 Processors, 64Mb Memory, Encore Mach Version B1.0c (Beta)
(no crypt(3) on this machine. Sigh.)
IBM rs6000, AIX 3.1 (DEADBEEF about sums it up.)
I've lost track of the others. If you have some bizzare piece of
hardware that you've run it on, I'd like to hear about it...
lly) maximum
portability, with a few written in C for specops_104/README.3 600 313 12 21103 5156725207 6466
Continued Use and Installing COPS
----------------------------------
Once you are satisfied that COPS indeed does something useful
(hopefully this will occur :-)), a good way to use it is to run it on at
least a semi-regular basis. Even if it doesn't find any problems
immediately, the problems and holes it detects are of the sort that can
pop up at any given time. One way of running COPS might be to run it as
an "at" job or by cron (if you run suid.chk via cron, use the "-s" flag
to tell cron where the rest of the COPS programs are, or it will chmod
"/" to mode 700, among other things).
I strongly advise that whatever directory COPS is placed in be
readable, writable, and executable only by the owner (typing "chmod 700
/usr/foo/bar" or whatever the name is will do this) of the directory.
This is to prevent prying eyes from seeing any security problems your
site may have. Even if you don't think of them as important, someone
else might come around and change your mind. Since COPS is fairly
configurable, an intruder could easily change the paths and files that
COPS checks for, hence making it fairly worthless. Again, this comes
back to the point that COPS is only a tool -- don't put down your
defensive shields merely because COPS says "all clear". If this sounds
paranoid, it is! Security people are traditionally paranoid, for a
reason... In any case, it is probably not a good idea to advertise any
(even) potential weaknesses.
If you use the shell/C version, typing "make install" will create (if
necessary) a subdirectory with the name you put in $INSTALL_DIR (found
on line 7 of "makefile"); if you run a network with multiple
architectures, you can have several executable versions of COPS in the
same NFS-mounted directory structure.
You can run COPS with "cops -a archtype", and it will cd into the
archtype directory, use the binaries or config files in that directory
(placed there by a "make install"), and put any results in a
subdirectory of the archtype directory with the appropriate host name.
You can set the secure directory (the directory that COPS finds all of
the programs in and places the results in) by either invoking COPS with
the -s flag (both shell and perl versions), or by setting the $SECURE
variable in the "cops" shell script (line 93.)
For example, assume you have the following setup, and run COPS with:
machine architecture hostname If run COPS with:
===================== ======== ==================
cray ribcage cops -s /usr/secure
vax bar cops -a vax -s /usr/secure
vax foo cops -a vax -s /usr/secure
sun earth cops -a sun3 -s /usr/secure
sun mars cops -a sun3 -s /usr/secure
sun venus cops -a sun4 -s /usr/secure
mips hades cops -s /usr/secure
The resulting directory/reporting structure would be (all reports
would be placed in a file named "year_month_day"):
/usr/secure/cops/ribcage
/usr/secure/cops/vax/bar
/usr/secure/cops/vax/foo
/usr/secure/cops/sun3/earth
/usr/secure/cops/sun3/mars
/usr/secure/cops/sun4/venus
/usr/secure/cops/hades
Sometimes you will get the same report over and over again, everytime
you run COPS; for instance, with Ultrix 3.x, /dev/kmem is world
readable. This is a security hole, but many utilities in Ultrix need
this to function. If you wish to only see reports that are _different_
than the old reports, you first need to have an older report saved in a
file (in $SECURE/hostname, or wherever you usually save the reports).
In the shell version, you can either do:
cops -m user
or:
set "MMAIL=YES" (line 55)
set "ONLY_DIFF=YES" (line 66)
in "cops". In the perl version, do:
set "$ONLY_DIFF=1" (line 11 of the config file)
Every time COPS is run after that, it will compare the report it
generated for the current check with the old report; if it detects any
differences, it will mail you a report. If not, it will simply discard
it. This can be a real boon for a site with a lot of machines running
COPS every night.
Alternately, you can use a "filter_file" to filter out repetative
messages. There is an example filter file, "cops_filter", that is
included in the package. It is used by simply typing "cops -f cops_filter",
and can be both very useful and very dangerous. Useful for obvious
reasons, dangerous because it can cause valid warning messages to be
thrown away before you get to see them.
There are a couple of further options you may wish to explore. First
of all, since so many breakins are because of poor password selection by
users, it would be a wise idea to add options to your password checking
program (line 200 in "cops", or line 72 in "cops.cf" for perl users).
You may wish to try some words from a dictionary; you may use either
your system dictionary (usually found in /usr/dict/words), or you may
use the same dictionary that the internet worm found so lucrative when
hitting all those thousands of hosts; that dictionary is in the file
"pass.words". For example, the way to include the worm dictionary (e.g.
the dictionary r.t.m. used in his Internet Worm) is:
pass.chk -w pass.words
Also, try some of the options in the password program, such as "-b",
"-g", "-s", and "-c", which add checks for backward, gecos, single
letter & number, and upper and lower case guesses, respectively. Of
course, each option will increase the time needed to crack the
passwords, so experiment! See what is reasonable for your hardware
capabilities and resources.
I've included the fast crypt functions that are used in Crack; if you
want to try those (highly recommended!), uncomment lines 96-97 in the
makefile, and comment out the normal compile line (95). Better yet,
get the full Crack package from uunet.uu.net or somewhere else. It
does a great job at cracking passwords. I might try to integrate the
whole package at some later time, but it might just be wasted work;
they work well separately.
By using the "pass_diff.chk" program, you can check only accounts
that have _changed_ their password since the last time you've checked --
this can save enormous amounts of time with large systems. This way,
you can check your users thoroughly once, then only check them when
their passwords change (possibly to something less secure). Be careful,
though, if you use this and then later expand your checks and/or the
dictionary you use to search for passwords, since the earlier accounts
that were already checked with an inferior method will not be checked
again until they change their password. See the file "passwords" in the
"extensions" directory for a replacement "passwd" program that can
disallow poor passwords to begin with.
The file "is_able.lst" contains a list of files that are to be
checked for world readability and/or writability. You should look at
this file and add or delete any files you feel are important to your
system.
After running COPS, if any warnings are given that compromise any
individual user's account (such as a world writable .profile or home
directory, a guessed password, etc.), and the problem is not corrected
immediately (or you are not sure whether or not it is worth hassling the
user to change it), try this:
If you are using the shell version, edit the file "init_kuang", and
add the compromised user(s) uids and groups in their respective target
lines (below lines 20 and 26, respectively). If you are running the
perl version, create a file with the compromised users listed in it (see
kuang.1 in the perl distribution). Now run kuang again to see if the
users can compromise the entire system. You may change your mind about
not thinking they are a problem! In addition, kuang does not have to
have "root" as a target (the last line). Try putting in system
administrators or other powerful figures to see if they are in danger as
well. If you have "perl" installed on your system, try the perl version
of kuang -- "kuang.pl" (you'll have to unpack the shar file this is
inside -- "kuang.pl.shar", and you may have to edit the first line of the
file "kuang.pl", to reflect where the location that perl is on your system),
because it is a more powerful, faster, and more versitile version.
That's it! Congratulations for reading this far :-) Browse around
the COPS directories for more goodies; the "extra_src", "docs", and
"extensions" directories all have interesting things in them. Don't
forget to try CARP to analyze your network's data (*ONLY USABLE WITH
"cops -v" RESULT FILES*) , and let me know how it goes. Finally, good
luck. Send me ideas, flames, kudos, whatever.
-- dan
cops_104/passwd.chk 755 313 12 14666 5156725210 7462 :
#
# passswd.chk
#
# Check passsword file -- /etc/passswd -- for incorrect number of fields,
# duplicate uid's, non-alphanumeric uids, and non-numeric group id's.
#
# Awk part from _The AWK Programming Language_, page 78
#
# Mechanism: Passwd.check uses awk to ensure that each line of the file
# has 7 fields, as well as examining the file for any duplicate users
# by using "sort -u". It also checks to make sure that the password
# field (the second one) is either a "*", meaning the group has no password,
# or a non-null field (which would mean that the account has a null
# password.) It then checks to ensure that all uids are alphanumeric,
# and that all user id numbers are indeed numeric. For yellow pages
# passwords, it does the same checking, but in order to get a listing of
# all members of the password file, it does a "ypcat passwd > ./$$" and
# uses that temporary file for a passfile. It removes the tmp file after
# using it, of course.
# The /etc/passwd file has a very specific format, making the task
# fairly simple. Normally it has lines with 7 fields, each field
# separated by a colon (:). The first field is the user id, the second
# field is the encrypted password (an asterix (*) means the group has no
# password, otherwise the first two characters are the salt), the third
# field is the user id number, the fourth field is the group id number,
# the fifth field is the GECOS field (basically holds miscellaneous
# information, varying from site to site), the sixth field is the home
# directory of the user, and lastly the seventh field is the login shell
# of the user. No blank lines should be present. Uid's will be flagged
# if over 8 chars, unless the $OVER_8 variable (line 50) is set to "YES".
# If a line begins with a plus sign (+), it is a yellow pages entry.
# See passwd(5) for more information, if this applies to your site.
#
AWK=/bin/awk
TEST=/bin/test
ECHO=/bin/echo
SORT=/usr/bin/sort
UNIQ=/usr/bin/uniq
RM=/bin/rm
YPCAT=/usr/bin/ypcat
# Used for Sun C2 security group file. FALSE (default) will flag
# valid C2 passwd syntax as an error, TRUE attempts to validate it.
# Thanks to Pete Troxell for pointing this out.
C2=FALSE
# Some systems allow long uids; set this to "YES", if so (thanks
# to Pete Shipley (lot of petes around here, eh?)):
OVER_8=NO
#
# Important files:
etc_passwd=/etc/passwd
yp_passwd=./$$
yp=false
# Testing $etc_passwd for potential problems....
if $TEST -s $YPCAT ; then
# thanks to brent chapman!
$YPCAT passwd | sort -t: +2n -3 +0 -1 > $yp_passwd
if $TEST $? -eq 0 ; then
yp=true
fi
fi
result=`$AWK -F: '{print $1}' $etc_passwd | $SORT |$UNIQ -d`
if $TEST "$result" ; then
$ECHO "Warning! Duplicate uid(s) found in $etc_passwd:"
$ECHO $result
fi
# First line is for a yellow pages entry in the password file.
# It really should check for correct yellow pages syntax....
$AWK 'BEGIN {FS = ":" }
{
if (substr($1,1,1) != "+") {
if ($0 ~ /^[ ]*$/) {
printf("Warning! Password file, line %d, is blank\n", NR)
}
else {
if (NF != 7) {
printf("Warning! Password file, line %d, does not have 7 fields: \n\t%s\n", NR, $0)
}
if ($1 !~ /[A-Za-z0-9]/) {
printf("Warning! Password file, line %d, nonalphanumeric login: \n\t%s\n", NR, $0)
}
if (length($1) > 8 && "'$OVER_8'" != "YES") {
printf("Warning! Password file, line %d, uid > 8 chars\n\t%s\n", NR, $0)
}
if ($2 == "") {
printf("Warning! Password file, line %d, no password: \n\t%s\n", NR, $0)
}
if ("'$C2'" == "TRUE" && $2 ~ /^##/ && "##"$1 != $2) {
printf("Warning! Password file, line %d, invalid password field for C2: \n\t%s\n", NR, $0)
}
if ($3 !~ /^[0-9]/) {
if ($3 < 0) {
printf("Warning! Password file, line %d, negative user id: \n\t%s\n", NR, $0)
}
else {
printf("Warning! Password file, line %d, nonnumeric user id: \n\t%s\n", NR, $0)
}
}
if ($3 == "0" && $1 != "root") {
printf("Warning! Password file, line %d, user %s has uid = 0 and is not root\n\t%s\n", NR, $1, $0)
}
if ($4 !~ /[0-9]/) {
printf("Warning! Password file, line %d, nonnumeric group id: \n\t%s\n", NR, $0)
}
if ($6 !~ /^\//) {
printf("Warning! Password file, line %d, invalid login directory: \n\t%s\n", NR, $0)
}
}
}
}' $etc_passwd
#
# Test yellow pages passwords as well
if $TEST "$yp" = "true"
then
yresult=`$AWK -F: '{print $1}' $yp_passwd | $SORT |$UNIQ -d`
if $TEST "$yresult"
then
$ECHO "Warning! Duplicate uid(s) found in yellow page passwords:"
$ECHO $yresult
fi
$AWK 'BEGIN {FS = ":" }
{
if ($0 ~ /^[ ]*$/) {
printf("Warning! YPassword file, line %d, is blank\n", NR)
}
else {
if (NF != 7) {
printf("Warning! YPassword file, line %d, does not have 7 fields: \n\t%s\n", NR, $0)
}
if ($1 !~ /[A-Za-z0-9]/) {
printf("Warning! YPassword file, line %d, nonalphanumeric login: \n\t%s\n", NR, $0)
}
if (length($1) > 8 && "'$OVER_8'" != "YES") {
printf("Warning! YPassword file, line %d, uid > 8 chars\n\t%s\n", NR, $0)
}
if ($2 == "") {
printf("Warning! YPassword file, line %d, no password: \n\t%s\n", NR, $0)
}
if ($3 !~ /^[0-9]/) {
if ($3 < 0) {
printf("Warning! YPassword file, line %d, negative user id: \n\t%s\n", NR, $0)
}
else {
printf("Warning! YPassword file, line %d, nonnumeric user id: \n\t%s\n", NR, $0)
}
}
if ($3 == "0" && $1 != "root") {
printf("Warning! YPassword file, line %d, user %s has uid = 0 and is not root\n\t%s\n", NR, $1, $0)
}
if ($4 !~ /[0-9]/) {
printf("Warning! YPassword file, line %d, nonnumeric group id: \n\t%s\n", NR, $0)
}
if ($6 !~ /^\//) {
printf("Warning! YPassword file, line %d, invalid login directory: \n\t%s\n", NR, $0)
}
}
}' $yp_passwd
fi
$RM -f $yp_passwd
# end
cops_104/XTRA_CREDIT 755 313 12 10772 5156725211 7220
Code credits are where code credits are due. If I miss anyone, please
forgive (and notify) me!
Gene Spafford -- overall design help and good guy.
Robert Baldwin and Steve Romig -- the original kuang package/design, and
the perl rewrite, respectively.
Craig Leres, Jef Poskanzer, Seth Alford, Roger Southwick, Steve Dum,
and Rick Lindsley all get credit for the password guessing program.
Prentiss Riddle -- the suid checker and lots of new bits and suggestions
to go into the rest of the cops package.
Mark Mendel and Jon Zeef -- the crc generator.
Muffy Barkocy -- cleaned up and helped rewrite lots of my ill designed
documentation.
Alec Muffett -- letting me use the fcrypt stuff he wrote (get his full
Crack package, folks!)
Shabbir Safdar and Phil Moyer -- writing chkacct and the help/text files
for the same, respectively.
Chip Rosenthal and Bill Davidsen for all the uucp stuff, which I've
stuffed temporarily in the extra_src directory, until I can integrate
it with the rest of the stuff.
The GNU folks, for making the ultimate interactive shell (bash) --
probably saves me a good 10% of keystrokes over other shells, as
well as saving (and probably wasting, since I could read more) lots of
time by making a more efficient news reader.
Round IV (this release) -- lots of people again -- the perl crew, of
course; Ethan Lish with the Xenix stuff. Wolfgang Denk and Jerry Carlin
did massive work to wipe out more SysV problems. Bud Bowman with the
pass.mail thingee, Ole H. Nielsen with the C2 stuff, Wietse Venema for
help debugging the bug stuff, the uucp_quick.chk thing, and other useful
comments, lots of others, etc.
In round III (second patch), Muffy Barkocy and Michelle Crabb both gave me
good ideas to use. Pete Shipley fixed up some code (is_able) and generally
helped my motivation to get things out the door. Gandalph suggested ftp.chk,
Jay Batson made me fix root.chk, Shelley Shostak fixed and added features
to pass.chk, and Brian Moore gave me the shell script checking --> SUID
concept. Jim W Lai pointed out some other pass.chk things (what a buggy
program :-)). Rob Kolstad told me about some bugs in the ftp checker, and
gently pointed out that some stuff wasn't using the YP passwd files when
they should be, and Jim Ellis helped get this to work on a Cray. There
are probably more that I've forgotten (sorry, if so!) Thanks, people...
In round II (the first patch), Mark Plumbly fixed rc.chk so it would
work like I said it would, as well as pointing out a few problems with
the password guesser.
And of course lots of credit goes to my great Beta-release sweatshop team;
especially Adri Verhoef for tightening up lots of my crummy code (cops,
group.chk, root.chk, is_writable, dev.chk, dir.chk & file.chk among others),
Steve Romig for good ideas _and_ letting me use a system V machine to test
on (how many people do you know that would let you test a security
system on their system with no strings attached!) Jason Levitt, Jim
Kimble, Jim Rowan, Stefan Vorkoetter, Judy Scheltema, Pete Troxell (all
the Sun C2 stuff....), Dennis Conley, and of course John Sechrest.
Tony Petrost pointed out some of my incorrect assumptions and helped
fix cron.chk. Kudos also to Bruce Spence for giving me some good
implementation ideas at LISA III.
If strings is not available to you, a version is available on uunet;
also a nifty install program written by Kevin Braunsdorf that can be used
as a super directory/file mode checker/security device might be available
soon in comp.unix.sources (these programs large sizes preculudes their
inclusion in COPS, but I recommend looking into them.) Both can be gotten
via anonymous ftp. Strings is in comp.unix.sources directory, install,
should be in j.cc.purdue.edu, methinks.
Everything else not explicitely mentioned in the COPS.report.ms paper
or here was written by me. Not mentioned execpt in the source code are
some small changes made by myself to make everything fit in as a cohesive
whole; I tried to make comments in the source code if I changed it (never
to drastic in any case.)
For a good story on the subject, you might want to read _The Cuckoo's
Egg_, by Clifford Stoll. This is a true tale of a sysadmin's fight
against beaurocracy and a system cracker. Good stuff.
For a a good read on Unix security in general, look at Dave Curry's now
infamous "white paper", via anon-ftp, SPAM.ITSTD.SRI.COM (128.18.4.3) as
the file "pub/security-doc.tar.Z. But don't believe him when he says Yellow
Pages is secure. It's not. Not much is, these days... good luck, tho!
-- dan
W Laicops_104/chk_strings 755 313 12 3747 5156725212 7713 :
#
# Usage: chk_strings filename
#
# This will check pathnames inside executable files for writability,
# using the "strings" command and egrep.
#
# I have identified three basic types of strings containing paths to files:
# 1)
# /path1/path2/file /* standard */
# 2)
# '/path1/path2/file' /* standard, in single quotes */
# 3)
# :/path1/file1:/path2/file2 /* a path for searching */
#
# For the first two, I simply test the writability; for the last, I
# parse it into seperate paths and check each one in turn.
#
AWK=/bin/awk
SED=/bin/sed
EGREP=/usr/bin/egrep
TEST=/bin/test
ECHO=/bin/echo
SORT=/usr/bin/sort
STRINGS=/usr/ucb/strings
if test ! -s $STRINGS
then
exit 0
fi
if test $# -eq 0
then
$ECHO "Usage: $0 file"
exit 2
fi
while test 0 -ne $#
do
# $ECHO Checking $1...
if ./is_writable $1 ; then
$ECHO "Warning! Root executed File $1 is _World_ writable!"
fi
# get the first two types:
# /path1/path2/file /* standard */
# '/path1/path2/file' /* standard, in single quotes */
# :/path1/file1:/path2/file2 /* a path for searching */
# test_files=`$STRINGS $1 | $EGREP "/.*/" | $AWK '{for (i=1;i<=NF;i++)
test_files=`$STRINGS $1|$SED -n -e 's/^.*[pP][aA][tT][hH]=//' -e '/\/.*\//p' |
$AWK '{for (i=1;i<=NF;i++)
if ((res = substr($i,1,1))=="/")
printf("%s\n",$i)
else if ((res != ":") && (res2=substr($i,2,1))=="/")
printf("%s\n",substr($i,2,length($i)-2))}
/:/ {
resk=substr($0, index($0,"=")+1, length($0) - index($0,"=")) \
split($0, path, ":"); \
for (j in path) printf("%s\n",path[j])}' | $SORT -u`
shift
done
for i in $test_files
do
if $TEST ! -d "$i" -o ! -f "$i" ; then
i=`$ECHO $i | $SED -e 's/[:;"]//g' -e "s/[']//g"`
if $TEST ! -f "$i" ; then
continue
fi
fi
if $TEST -n "`$ECHO $i | $EGREP /tmp\|/dev/null\|/dev/tty\|/dev/printer\|/dev/console`" ; then
continue
fi
if ./is_writable "$i" ; then
$ECHO "Warning! File $i (inside root executed file $1) is _World_ writable!"
fi
done
# end of script
cops_104/bug.chk.aix 700 313 12 2264 5156725213 7456 #!/bin/sh
#
# IBM/AIX module for bug/vulnerability checking
#
ECHO=/bin/echo
TEST=/bin/test
LS=/bin/ls
LS_OPTS="-slagL"
ARCH=/bin/arch
GREP=/bin/grep
AWK=/bin/awk
BUG="$AWK -f ./bug_cmp"
if $TEST ! -f ./bug_cmp ; then
$ECHO "Must have bug compare module, ./bug_cmp, to run..."
exit 2
fi
# what is the date? We just need the month and year...
# Format: Fri Feb 7 14:16:55 PST 1992
if $TEST $# -eq "2" ; then
real_date="$1 $2"
else
real_date=`$DATE | $AWK '{print $2, $NF}'`
fi
# tftpd
#
#
# Fixed in version "1.13.1.3" (do a "what /etc/tftpd")
tftpd="/etc/tftpd"
fix_date="17 Oct 1991"
cert_advis="CA-91:19"
# IBM says to do this; I'm going to go by date, because if I search
# for a specific version, I'll be screwed when they change it.
# `what /etc/tftpd`
if $TEST -f "$tftpd" ; then
cur_date=`$LS $LS_OPTS $tftpd | $AWK '{print $8, $7, $9}'`
$ECHO $tftpd $fix_date $cur_date $cert_advis $real_date | $BUG
fi
# /usr/etc/rpc.rexd
#
#
rexd="/usr/etc/rcp.rexd"
fix_date="5 Mar 1992"
cert_advis="CA-92:5"
#
if $TEST -f "$rexd" ; then
cur_date=`$LS $LS_OPTS $rexd | $AWK '{print $8, $7, $9}'`
$ECHO $rexd $fix_date $cur_date $cert_advis $real_date | $BUG
fi
# finis
cops_104/cops 755 313 12 23423 5156725214 6354 :
#
# Usage cops [-a architecture] [-b bit_bucket] [-s secure_dir] \
# [-m user] [-f filter_file] [-dxvV]
#
# -a specifies the architecure subdirectory you want to run in; you
# must run "make install" to install the appropriate binaries there
#
# -b specifies the "bit bucket", where all the error messages go to.
#
# -d will mail a report only if there have been changes since the
# last one. Only makes sense with the -m flag or by setting the
# MMAIL var below.
#
# -f specifies the cops filter file, which is used for filtering out
# extraneous warning message.
#
# -m tells cops to mail the output to the user specified
#
# -s tells cops where the secure directory is; mostly this is used by
# cops itself, when it is run with the -a flag; it will rerun itself
# with the -a flag's argument as an argument to this.
#
# -x prints out the version number (running out of letters! :-))
#
# -[vV] are the verbose flags. Small "v" says print whatever program
# is running, when it is executed, in the output file; capital
# "V" says print everything to the screen.
#
# Warning! COPS will get confused if you use a command line arg that
# expects an argument and you don't give it one. Don't say I didn't
# warn you :-)
#
# Overall --
#
# Cops will change into the $SECURE/architecture directory, ensure all
# the security programs (listed below) indeed do exist, and run all of the
# security programs. If any of the programs find any security problems, it
# either sends mail to everyone in the $SECURE_USERS list, or saves the results
# in a file $SECURE/architecture/hostname. It then destroys all temporary
# files, and exits the program. Programs that are run (besides this one):
#
# root.chk dev.chk group.chk
# home.chk rc.chk passwd.chk
# is_able.chk pass.chk user.chk
# cron.chk misc.chk ftp.chk
#
# The U-kuang system runs these additional programs:
# init_kuang kuang addto
# clearfiles filewriters members
#
# If this is changed to "NO", the report that cops creates
# will not be deleted and the results will not be mailed to anyone.
MMAIL=NO
#
# Foreign language users can change this (thanks to Wolfgang Denk!):
LANGUAGE=english
export LANGUAGE
#
# If this is changed to "YES", then the report will only be mailed
# if it detects a difference between the last report and this one.
# Note that this makes no sense unless the mail is set to "YES" as well.
ONLY_DIFF=YES
#
# Do you want to run suid.chk within cops?
RUN_SUID=NO
# Where is everyone?
ECHO=/bin/echo
TEST=/bin/test
RM=/bin/rm
CAT=/bin/cat
MAIL=/bin/mail
DATE=/bin/date
CHMOD=/bin/chmod
AWK=/bin/awk
SED=/bin/sed
MV=/bin/mv
MKDIR=/bin/mkdir
# send errors and verbosity to...
BIT_BUCKET=/dev/null
# send verbose messages to...
VERBUCKET=/dev/null
######################
# Change these lines!
######################
SECURE=/usr/foo/bar
SECURE_USERS="foo@bar.edu"
######################
# arg stuff:
while $TEST $# != 0
do case "$1" in
-a) arch=$2 ; SECURE=$SECURE"/"$arch ; shift ;;
-b) BIT_BUCKET=$2 ; flags=$flags" -b $2" ; shift ;;
-d) ONLY_DIFF=YES ;;
-f) filter=yes ; cops_filter=$2 ; shift ;;
-m) SECURE_USERS=$2 ; flags=$flags" -m $2" ; MMAIL=YES ; shift ;;
-s) SECURE=$2 ; shift ;;
-v) verbose=yes ; v="-v" ; flags=$flags" -v" ;;
-V) verbose=yes ; VERBUCKET="/dev/tty" ; RESULT="/dev/tty" ; flags=$flags" -V" ;;
-x) $AWK '{print "Version 1.0" $NF}' ./patchlevel.h ; exit 0 ;;
*) $ECHO Usage $0 [-a arch] [-b bit_bucket] [-s sec_dir] [-f filter] [-m user] [-dvVx] ; exit ;;
esac
shift
done
if $TEST "$filter" = "yes" -a ! -s "$cops_filter" ; then
$ECHO "Can't open filter: $cops_filter"
exit 1
fi
# architecture? change to that dir, and execute cops there:
if $TEST -n "$arch" ; then
if $TEST ! -d "$SECURE" ; then
$ECHO Architecture directory $1 does not exist
exit 1
fi
$CHMOD 700 $SECURE
cd $SECURE
./cops -s "." $flags
exit
fi
SECURE_PROGRAMS="root.chk dev.chk is_able.chk group.chk \
home.chk rc.chk passwd.chk pass.chk misc.chk ftp.chk \
cron.chk user.chk init_kuang kuang addto \
clearfiles filewriters members is_able bug.chk"
if $TEST ! -d "$SECURE" ; then
$ECHO "Error -- Security directory $SECURE doesn't exist"
exit 1
fi
$CHMOD 700 $SECURE
cd $SECURE
for i in $SECURE_PROGRAMS
do
if $TEST ! -s "$i" ; then
$ECHO "Error -- Security program $SECURE/$i doesn't exist"
exit 1
fi
done
# results go:
if $TEST -z "$RESULT" ; then
RESULT=$SECURE/result.$$
fi
if $TEST x"-v" = "x$v" ; then
VERBUCKET=$RESULT
fi
if $TEST -n "$verbose" ; then
$ECHO "**** root.chk ****" > $VERBUCKET ; fi
$SECURE/root.chk >> $RESULT 2> $BIT_BUCKET
if $TEST -n "$verbose" ; then
$ECHO "**** dev.chk ****" >> $VERBUCKET ; fi
$SECURE/dev.chk >> $RESULT 2>> $BIT_BUCKET
if $TEST -n "$verbose" ; then
$ECHO "**** is_able.chk ****" >> $VERBUCKET ; fi
$SECURE/is_able.chk >> $RESULT 2>> $BIT_BUCKET
if $TEST -n "$verbose" ; then
$ECHO "**** rc.chk ****" >> $VERBUCKET ; fi
$SECURE/rc.chk >> $RESULT 2>> $BIT_BUCKET
if $TEST -n "$verbose" ; then
$ECHO "**** cron.chk ****" >> $VERBUCKET ; fi
$SECURE/cron.chk >> $RESULT 2>> $BIT_BUCKET
if $TEST -n "$verbose" ; then
$ECHO "**** group.chk ****" >> $VERBUCKET ; fi
$SECURE/group.chk >> $RESULT 2>> $BIT_BUCKET
if $TEST -n "$verbose" ; then
$ECHO "**** home.chk ****" >> $VERBUCKET ; fi
$SECURE/home.chk >> $RESULT 2>> $BIT_BUCKET
if $TEST -n "$verbose" ; then
$ECHO "**** passwd.chk ****" >> $VERBUCKET ; fi
$SECURE/passwd.chk >> $RESULT 2>> $BIT_BUCKET
if $TEST -n "$verbose" ; then
$ECHO "**** user.chk ****" >> $VERBUCKET ; fi
$SECURE/user.chk >> $RESULT 2>> $BIT_BUCKET
if $TEST -n "$verbose" ; then
$ECHO "**** misc.chk ****" >> $VERBUCKET ; fi
$SECURE/misc.chk >> $RESULT 2>> $BIT_BUCKET
# use the -a option for checking anon-ftp; e.g., "$SECURE/ftp.chk -a"
if $TEST -n "$verbose" ; then
$ECHO "**** ftp.chk ****" >> $VERBUCKET ; fi
$SECURE/ftp.chk >> $RESULT 2>> $BIT_BUCKET
# Optional -- use "pass_diff.chk", instead of "pass.chk" to make your
# life easier!
if $TEST -n "$verbose" ; then
$ECHO "**** pass.chk ****" >> $VERBUCKET ; fi
$SECURE/pass.chk -w ./pass.words -b -g -s -c -d -n >> $RESULT 2>> $BIT_BUCKET
# $SECURE/pass_diff.chk >> $RESULT 2>> $BIT_BUCKET
# try it with "-w ./pass.words -b -g -s -c -d -n" flags....
if $TEST -n "$verbose" ; then
$ECHO "**** kuang ****" >> $VERBUCKET ; fi
# Optional -- use "kuang.pl", instead of "kuang", if you have perl
# installed on your system, for extra speed and functionality:
$SECURE/kuang >> $BIT_BUCKET 2>> $BIT_BUCKET
# $SECURE/kuang.pl >> $BIT_BUCKET 2>> $BIT_BUCKET
# kuang puts it's results in a file called "Success"; check it out:
# if $TEST -s "$SECURE/Success" ; then
# $CAT $SECURE/Success >> $RESULT
# fi
# $RM -f $SECURE/Success
# Optional! Should use this interactively, with a secret key!
# if $TEST -n "$verbose" ; then
# $ECHO "**** crc.chk ****" >> $VERBUCKET ; fi
# $SECURE/crc.chk 2>> $BIT_BUCKET
# crc.chk puts it's results in a file called crc.results; uncomment
# this as well:
# if $TEST -s "$SECURE/crc_results" ; then
# $CAT $SECURE/crc_results >> $RESULT
# fi
# $RM -f $SECURE/crc_results
#
# Want to run suid check from within cops? (Results get mailed separately)
# if $TEST "$RUN_SUID" = "YES" ; then
# $SECURE/suid.chk > /dev/null 2>&1
# fi
#
# Bug.chk? New stuff...
if $TEST -n "$verbose" ; then
$ECHO "**** bug.chk ****" >> $VERBUCKET ; fi
$SECURE/bug.chk >> $RESULT 2>> $BIT_BUCKET
#
#
# Filter results, if used
if $TEST "$filter" = "yes" ; then
$AWK -f $cops_filter $RESULT > $RESULT".FILT"
# if no results are there, don't worry about printing a report...
if $TEST ! -s $RESULT".FILT" ; then
$RM -f $RESULT
exit 0
fi
# else, move the filtered results in the old result location:
$MV $RESULT".FILT" $RESULT
fi
#
# Save or Mail the final report to $SECURE_USERS and remove the evidence.
#
# (Thanks to Ian Darwin for the next nifty idea!)
# If the result is not mailed, it will be saved in a directory with the
# same name as the host, in a file with the name:
#
# Year_Month_Day (for example: $SECURE/ucbvax/1999_Dec_31 )
#
if $TEST -s "$RESULT" ; then
# want to put the date and hostname at top; use tmp file: report.$$
REPORT=$SECURE/report.$$
# name of final resting place:
NAME=`$DATE | $AWK '{print $NF"_"$2"_"$3}'`
#
if $TEST -s /bin/hostname ; then
HOSTNAME=`/bin/hostname`
elif $TEST -s /bin/uname ; then
HOSTNAME=`/bin/uname -n`
elif $TEST -s /usr/bin/uuname ; then
HOSTNAME=`/usr/bin/uuname -l`
fi
if $TEST -z "$HOSTNAME" ; then
HOSTNAME="foobar"
fi
HOST=`$ECHO $HOSTNAME | $SED 's/[.].*$//'`
$ECHO > $REPORT
$ECHO ATTENTION: >> $REPORT
$ECHO "Security Report for "`$DATE` >> $REPORT
$ECHO "from host $HOSTNAME" >> $REPORT
$ECHO >> $REPORT
$ECHO >> $REPORT
$CAT $SECURE/result.$$ >> $REPORT
# figure out where all the old reports are kept, or where the new
# one should be kept; make directories if needed...
if $TEST -d "$SECURE/$HOST" -a "$MMAIL" = "YES" ; then
if $TEST "$ONLY_DIFF" = "YES" ; then
if $TEST -n "`./res_diff $SECURE/$HOST $REPORT`" ; then
$MAIL $SECURE_USERS < $REPORT
$MV $REPORT $SECURE/$HOST/$NAME
fi
else
$MAIL $SECURE_USERS < $REPORT
fi
$RM -f $REPORT
elif $TEST ! -d "$SECURE/$HOST" -a "$MMAIL" = "YES" ; then
$MAIL $SECURE_USERS < $REPORT
if $TEST -n "$HOST" ; then
$MKDIR $SECURE/$HOST 2> /dev/null
$MV $REPORT $SECURE/$HOST/$NAME
else
$MV $REPORT $NAME
fi
else
# Either saving it to a hostname, in which case move to
# the hostname directory, or just move result to
# the current dir
if $TEST -n "$HOST" ; then
$MKDIR $SECURE/$HOST 2> /dev/null
$MV $REPORT $SECURE/$HOST/$NAME
else
$MV $REPORT $NAME
fi
fi
fi
$RM -f $SECURE/result.$$
# end it all....
exit 0
is_able.chk pass.chk user.chk
# cron.chk misc.chk ftp.chk
#
# The U-kuang system runs these additional programs:
# init_kuang kuang addto
# clearfiles filewriters members
#
# If this is changed to "NO", the report that cops creates
cops_104/bug_cmp 700 313 12 2524 5156725215 6772 #
# $0 "bug_name" "fix_date" "cur_date" "cert_advisory_number" \
# "real_date" "greater_than_date"
#
# Dates are like "day month year"; e.g. "6 Dec 1991"
#
{
word_smithing="could have a hole/bug"
month["Jan"] = 1;
month["Feb"] = 2;
month["Mar"] = 3;
month["Apr"] = 4;
month["May"] = 5;
month["Jun"] = 6;
month["Jul"] = 7;
month["Aug"] = 8;
month["Sep"] = 9;
month["Oct"] = 10;
month["Nov"] = 11;
month["Dec"] = 12;
bug_name = $1
fix_day = $2
fix_month = month[$3]
fix_year = $4
# want to accept YY or YYYY. breaks in 2088. Thanks, wietse!
if (fix_year < 88) fix_year += 2000
else if (fix_year < 100) fix_year += 1900
cur_day = $5
cur_month = month[$6]
cur_year = $7
cert_advis = $8
real_month = month[$9]
real_year = $10
great_day = $11
great_month = month[$12]
great_year = $13
if (index(cur_year, ":")) {
if (cur_month > real_month)
cur_year = real_year - 1
else
cur_year = real_year
}
# print "bug-in-question", bug_name
# print "fix-DATES", fix_month, fix_day, fix_year
# print "cur-DATES", cur_month, cur_day, cur_year
# print "real-DATE", real_month, real_year
if ((cur_year < fix_year) || ((cur_year==fix_year) && (cur_month < fix_month)) || ((cur_year==fix_year) && (cur_month==fix_month) && cur_day < fix_day))
printf("Warning! %s %s! (%s)\n", bug_name, word_smithing, cert_advis)
}
cops_104/cover_letter 755 313 12 17077 5156725216 10117
Women and men of the net, greetings...
Gone are the days when COPS was sleek, trim, and new. It has joined
the ranks of modern software -- bloated, overladen with potentially
useless features, overhyped and underloved. Here are the latest changes,
additions, and bug fixes to COPS -- this brings it up to version 1.04, for
those who care. I skipped version 1.03 because the beta copy that I put
out is so hopelessly out of date that it didn't make a lot of sense to
continue with 1.03. Anyway, my personal stash (the latest copy) should
be available via anon-ftp at archive.cis.ohio-state.edu (128.146.8.52),
in ~pub/cops/1.04. In this header, I'll go through some thoughts,
background notes, then finally get to the changes made, so if you don't
want to listen to me, just unpack the shar files, read the README file,
follow instructions, and you should be ready to roll.
For those who don't know, COPS is a static security checking tool that
checks common (mostly) procedural problems of a Un*x system. It basically
takes a snapshot of a system, and then generates a report of it's findings.
On a purely empirical basis, over the years it has successfully discovered
problems that could compromise root on more than 3/4 or more of the systems
I've run it on; of course, the idea here is not to break root, but to let
someone fix the problems it shows. Note, of course, that it gives info
indiscriminately, to whoever runs it. Decide if you do or don't want to
learn about the information it can give about your system, but remember --
someone else probably already has it.
After writing COPS, I started working for CERT. I had always suspected,
but didn't know, that most breakins were caused by pretty trivial problems...
now I *know* it's true (or at least the ones we've found out about :-)).
In the breakins I've seen while working for CERT, using COPS probably could
have prevented 60-75% of them. The most common problems? Poor passwords,
guest accounts, accounts with no passwords, and improperly managed systems
(+ in host.equiv, poorly set up remote daemons, etc.) Interestingly, to
me at least, I wrote the original intro to COPS over two years ago.
How times don't change... I was worried this would be fairly obsolete soon,
but it looks like it'll be good at least for another few years.
The kit is broken into modules, each one driven by a master shell script;
you can usually get it running within 30 minutes or less if you've never used
it before (5 or 10 if you only scan the README); if you've used it in the
past, you can set it up on a new machine in a minute or two. With no
modifications, it usually takes somewhere 2 to 30 minutes to generate a
report; however, the password cracking program can add lots of time to this,
depending on the options. There is also a SUID finder, which can also take
a long time (hours) to run, since it does a "find" on "/". There's a new
option that tells it not to mail a report if the results are the same as
the last report, so you can just stuff it into cron and wait until a report
comes around. Of course, if someone breaks in, changes cron, and you just
rely on COPS, then you're f*cked anyway. Use it as a tool, not as a crutch.
Ok, changes... The main thing is that the whole thing (more or less)
has been ported to perl; both shell and perl versions are included and
will probably be supported in the future. They have various differences,
some intentional, some not, but I have attempted to keep them as similar
as possible. Tom Christiansen did a large part of the work on this part
(thanks again, tom!), but there were several people involved in the perl
work... see "README.perl" and the perl subdirectory for more info. Warning;
the perl version, for a variety of reasons (mostly detailed in "README.2.pl"
is not as robust as the shell version.
There is one new major module here -- "bug.chk" (all of this is
in the subdirectory "bugs"). This takes most of the CERT security
announcements (those relating to bugs and vulnerabilities, at least) and
attempts to see if your host might have the problem. Some problems come
up with a good way to check for these problems, not the least of which is
that I am taking a very conservative route (i.e. probably not a very good
way of handling it) to see if a host has bugs. See the man page for
"bug.chk" for more details.
In addition, there is a new program, a kind of "personal-cops",
called "checkacct" (found in the directory of the same name.) This
interactive program does a variety of checks, some done in cops, some not
(searching for individual S[UG]ID files, writable user directories,
.rhosts parsing/checking) that can be run by an individual to check
their account security. This was done by some friends at purdue,
most notably shabbir safdar.
Here are the rest of the major changes I can think of:
-- a new program, "carp" (look in the "carp" subdirectory), looks at
COPS output from several machines (presumably from your network) and
attempts to give a kind of scoresheet of what it found wrong with your
system, with weighted values. It outputs either standard text, postscript,
and has an X (as in windows, not that you'll have to be 18 to look at)
previewer. Like all new features, I'm not sure if this is particularily
useful (perhaps more for impressing management with pretty pictures, but
it might be good for seeing trends or interesting tidbits not otherwise
discernable), but time (or, rather, you, the users) will tell. Let me
know what you think. This is *ONLY* useable with "cops -v" output!
-- a filter for COPS (originally named by default "cops_filter") makes
it possible to get rid of those pesky "Warning! /dev/printer is _World_
writable!" messages. Use "cops -f cops_filter" to use.
-- Code has been cleaned up, tons of flags/options have been added to make
things easier to use, documentation has been updated.
-- a fast crypt is included, stolen right from that wonderful password
cracker everyone knows and loves, Crack. I'm not about to say you
should use my password cracker instead of crack -- if you can use crack,
use it! However, it might prove to be a easy/painless alternative if
you decide that crack doesn't fit your time constraints or something.
You can try uncommenting lines 91 and 92 in the makefile for this.
-- a more powerful version of perl kuang is included.
-- a new directory, "extra_src" has been created, and contains a few
miscellaneous programs that couldn't quite fit in with the rest of this
release, but are fairly important or useful in their own right. Some
of these programs will go into future versions of COPS. There is a
README file that briefly describes the programs there. BTW, if you use
uucp, make sure you look here!
-- two mini-papers have been put in the "extensions" directory. One
is a very useful article on how to harden your uucp site, the other
is a good paper on how to write a SUID program correctly.
The easiest thing to do is unpack everything, scan the README file,
read either the README.shell or README.perl file (depending on which one
you'd like to use), and finally look at the README.final file. Alternately,
you can read the "quick_start" file if you're impatient. If you're not totally
sure that the pathnames to the executables are correct, then you should
run "reconfig" (if you have a sysV based machine, or are just suspicious
of your system, you should do this anyway.) After all that, just
type "./cops", and blast off. Finally, to steal an ending from the README
file of a few years ago...
"So good luck, and I hope you find COPS useful as we plunge into UNIX
of the 1990's.
dan farmer
January 31, 1989"
-- dan
March 6, 1992
and you just
rely on COPS, then you're f*cked anyway. Use it as a tool, not as a crutch.
Ok, changes... The main thing is that the whole thing (more or less)
has been ported to perl; both shell and perl versions are included and
will probably be supported in the future. They have various differences,
some intentional, some not, but I have attempted to keep them as similar
as possible. Tom Christiansen did a large part of the work on this cops_104/crc.chk 755 313 12 4237 5156725217 6710 :
#
# Usage: crc.chk
#
# A CRC generator, checker, slicer and dicer. See the man page for
# lots more verbage.
#
# commands 'n stuff:
AWK=/bin/awk
SED=/bin/sed
SORT=/usr/bin/sort
MV=/bin/mv
MAIL=/bin/mail
CAT=/bin/cat
TEST=/bin/test
ECHO=/bin/echo
RM=/bin/rm
DATE=/bin/date
# files used:
crc_list=./crc_list # lists files used
crc_seed=./crc_seed # optional -- contains seed
crc_old=./crc_old # old crc values
crc_tmp=./crc_tmp # temp storage for the new crc's
crc_res=./crc_res # difference between new and old crc's
bit_bucket=/dev/null # junk goes here
results=./crc_results # results go here; deleted & mailed, or
# saved here, depending on the "MAIL" flag.
# Do you want it mailed? If "YES", the results file gets deleted
MMAIL=NO
# who gets the report?
INFORM="foo@bar.edu"
# If you don't use an argument, and don't have a seed file, generate
# a semi-random seed:
if $TEST $# -eq 1 ; then
seed=$1
else
if $TEST ! -s $crc_seed ; then
seed=$$
$ECHO $seed > $crc_seed
else
seed=`$CAT $crc_seed`
fi
fi
# AIX has a broken awk.
# files=`$AWK '/^#/ {next} {print $1}' $crc_list | $SORT -u`
files=`$SED '/^#.*$/d' $crc_list | $SORT -u`
# $ECHO crc\'ing, with seed $seed
for i in $files
do
./crc -v -i $seed $i >> $crc_tmp 2> $bit_bucket
done
# First time used, create the database:
if $TEST ! -s $crc_old ; then
$MV $crc_tmp $crc_old
exit 0
fi
# any differences?
./crc_check $crc_old $crc_tmp > $crc_res
if $TEST -s $crc_res ; then
# get the hostname:
if $TEST -s /bin/hostname ; then
HOSTNAME=`/bin/hostname`
elif $TEST -s /bin/uname ; then
HOSTNAME=`/bin/uname -n`
elif $TEST -s /usr/bin/uuname ; then
HOSTNAME=`/usr/bin/uuname -l`
fi
if $TEST -z "$HOSTNAME" ; then
HOSTNAME="foobar"
fi
$ECHO >> $results
$ECHO ATTENTION: >> $results
$ECHO "CRC Security Report for "`$DATE` >> $results
$ECHO "from host $HOSTNAME" >> $results
$ECHO >> $results
$CAT $crc_res >>$results
if $TEST $MMAIL = "YES" ; then
$MAIL $INFORM < $results
$RM $results
fi
fi
$RM -f $crc_tmp $crc_res
# end it all....
exit 0
cops_104/crc_list 755 313 12 2167 5156725217 7177 # This lists any/all sensitive files the administration wants to have a
# CRC value for. Comments are lines starting with a "#".
#
# some key files that might not change too often:
/.login
/.profile
/.cshrc
/.rhosts
/*unix*
/etc/hosts.equiv
/usr/lib/crontab
/usr/lib/aliases
/usr/spool/uucp/L.sys
# some that you might like to keep an eye on, depending on your site
# stability and/or paranoia:
# /etc/passwd
# /etc/group
# default is individual files; can use wildcards, or whatever;
# here are some examples, using wildcards:
/bin/*
/usr/bin/*
/usr/lib/*
# /usr/local/lib/*
# /usr/local/bin/*
# Alternately, here are individual files that are important:
# /bin/fsck
# /bin/rrestore
# /bin/csh
# /bin/login
# /bin/ls
# /bin/mail
# /bin/mount
# /bin/passwd
# /bin/ps
# /bin/sh
# /bin/su
# /usr/lib/sendmail
# /usr/ucb/telnet
# /usr/ucb/rlogin
# /usr/ucb/ftp
# /usr/bin/at
# /usr/bin/chgrp
# /usr/bin/cu
# /usr/bin/df
# /usr/bin/login
# /usr/bin/mail
# /usr/bin/passwd
# /usr/bin/ruusend
# /usr/bin/su
# /usr/bin/tip
# /usr/bin/uucp
# /usr/bin/uulog
# /usr/bin/uuname
# /usr/bin/uusend
# /usr/bin/uustat
# /usr/bin/uux
# /usr/bin/xterm
with a "#".
#
# some key files that might not change too often:
/.login
/.profile
/.cshrc
/.rhosts
/*unix*
/etc/hosts.equiv
/usr/lib/crontab
/usr/lib/aliases
/usr/spool/uucp/L.sys
# some that you might like to keep an eye on, depending on your site
# stability and/or paranoia:
# /etc/passwd
# /etc/group
# default is individual files; can use wildcards, or whatever;
# here are some examcops_104/cron.chk 755 313 12 4362 5156725220 7073 :
#
# Usage: cron.chk
#
# This checks pathnames and files inside the cron files /usr/lib/crontab
# for writability.
#
# Mechanism: The commands inside the file /usr/lib/crontab are executed
# by root. This shell script greps for commands/paths that begins with
# "/" and takes each potential problem-string and uses the program
# "is_writable" to determine if it is world writable. All results are
# echoed to standard output.
# In addition, it throws away everything that has a /tmp, /dev/null, or
# tty in the writable string, and everything after a ">"; e.g. if crontab
# is writing to a file it doesn't care.
#
# Cron.chk will try to find a file in /usr/lib/crontab first (bsd),
# and then if it isn't there, it will look in the any alternate
# possible locations next -- right now, /usr/spool/cron/crontab -- to
# see if a directory exists, and, if it does, it checks all the cron
# files in turn.
#
# WARNING!
#
# Spurious messages can occur; a more stringent method (if perhaps less
# careful of a check) would be to test just the 6th field, instead of
# all the fields after the fifth. Also throwing away /tmp, etc. could
# be a mistake.
#
# Location of stuff:
AWK=/bin/awk
SED=/bin/sed
ECHO=/bin/echo
EGREP=/usr/bin/egrep
TEST=/bin/test
CAT=/bin/cat
# Possible location of crontab file:
cron=/usr/lib/crontab
# alternate reality locations of crontab file:
alt_cron="/usr/spool/cron/crontabs"
if $TEST ! -s $cron
then
cron=""
for i in "$alt_cron"
do
if $TEST -d $i
then
cron=`$ECHO $alt_cron/*`
fi
done
if $TEST -z "$cron"
then
exit
fi
fi
# finally, do the checking -- maybe for one, maybe for lots of
# cron-ites:
for cron_kid in $cron
do
./chk_strings $cron_kid
# A typical crontab entry might look something like this:
#
# 0,15,30,45 * * * * /bin/sh /usr/adm/newsyslog
#
risky_stuff=`$AWK '{for (i=6;i.*//' -e 's/;//g' |
$AWK '{ for (i=1; i<=NF; i++)
if (substr($i,1,1)=="/") print $i}'`
for i in $risky_stuff ; do
if $TEST `$ECHO $i | $EGREP "/tmp|/dev/null|tty"` ; then
continue
fi
if ./is_writable $i ; then
$ECHO "Warning! $i (in $cron_kid) is World writable!"
fi
done
done # for all the cron-kids
cops_104/dev.chk 755 313 12 6563 5156725221 6716 :
#
# dev.chk [-g]
#
# This shell script checks the permissions of all devs listed in the
# file /etc/fstab (the "mount" command would be a preferable way of
# getting the file system name, but the syntax of the output is variable
# from machine to machine), and flags them if they are readable by using
# the "is_able" command. It also checks for unrestricted NFS
# mountings. By default, dev_check will flag devs only if world readable
# or writable. The -g option tells it to print out devs that are also
# group readable/writable.
# As an aside, the fact that NFS mounted dirs are world readable isn't
# a big deal, but they shouldn't be world writable. So do two checks here,
# instead of one.
#
# (p.s. /dev/?mem and some misc files used to be checked here, but they
# are now checked in is_able.chk)
#
# Two types of /etc/fstab formats I've seen so far:
#
# spec:file:type:freq:passno:name:options
# NFS are indicated by an "@"
#
# fsname dir type opts freq passno
# NFS are indicated by an ":"
#
# I check for the second; comment that code out (lines 83-84), and
# uncomment the other style (lines 79-80), if you have the first type.
#
AWK=/bin/awk
SED=/bin/sed
LS=/bin/ls
ECHO=/bin/echo
TEST=/bin/test
# locations of vital stuff...
mtab=/etc/fstab
exports=/etc/exports
group=no
if $TEST $# -gt 1 ; then
$ECHO "Usage: $0 [-g]"
exit 2
fi
if $TEST $# -eq 1 ; then
if $TEST "X$1" = "X-g" ; then
group=yes
else
$ECHO "Usage: $0 [-g]"
exit 2
fi
fi
# Testing filesystems and devices for improper read/write permissions...
# grab devices from "/etc/fstab"....
# Format of /etc/fstab:
#
# spec:file:type:freq:passno:name:options
# NFS mounted:
# uther@foobar.edu:/usr/spaf:ect....
#
# Or, the default means of checking:
#
# filesystem directory type options freq pass
# NFS mounted:
# uther:foobar.edu /usr/spaf....
#
# kill comments, then get the device/filesystem in question.
#
# First style:
# nfs_devs=`$SED 's/^#.*//' $mtab | $AWK -F: '/@/ {print $2}'`
# local_devs=`$SED -e 's/^#.*$//' -e 's/^.*@.*$//' $mtab|$AWK -F: {print $1}'`
# Default style:
nfs_devs=`$SED -e 's/^#.*$//' $mtab | $AWK '/:/ {print $1}'`
local_devs=`$SED -e 's/^#.*$//' -e 's/^.*:.*$//' $mtab | $AWK '{print $1}'`
all_devs=$nfs_devs" "$local_devs
# Alternate way; grab devices from "mount [-p]"....
# Format of output from mount (some machines use -p option, some
# don't. Check your local man page... you might have to add a "-F:" or
# something, depending on your output:
# crit_devs=`/etc/mount -p|$AWK 'index($1, "/")==1
# {print $1} \
# }'`
# On an IBM/AIX box, you can try something like:
# all_devs=`$GREP 'dev.*=' /etc/filesystems | $AWK '{print $NF}'`
#
# However, do check for single line entries in /etc/exports:
if $TEST -s $exports
then
$SED -e 's/^#.*$//' $exports | $AWK '!/access=/ {
print "Warning! NFS file system " $1 " exported with no restrictions!"}'
fi
#
# Have to get them in the format that "is_able" likes:
#
# filename {world|group} {writeable|readable|both}
#
# all things check world/group writability
for i in $all_devs
do
./is_able $i w w
if $TEST "$group" = "yes"
then
./is_able $i g w
fi
done
# For local devices, we want to make sure that no one can bypass
# security by reading straight from the device:
for i in $local_devs
do
./is_able $i w r
if $TEST "$group" = "yes"
then
./is_able $i g r
fi
done
# end of script
cops_104/bug.chk.dec 700 313 12 2140 5156725221 7420 #!/bin/sh
#
# DEC module for bug/vulnerability checking
#
ECHO=/bin/echo
TEST=/bin/test
LS=/bin/ls
LS_OPTS="-slagL"
ARCH=/bin/arch
GREP=/bin/grep
AWK=/bin/awk
BUG="$AWK -f ./bug_cmp"
if $TEST ! -f ./bug_cmp ; then
$ECHO "Must have bug compare module, ./bug_cmp, to run..."
exit 2
fi
# what is the date? We just need the month and year...
# Format: Fri Feb 7 14:16:55 PST 1992
if $TEST $# -eq "2" ; then
real_date="$1 $2"
else
real_date=`$DATE | $AWK '{print $2, $NF}'`
fi
# chroot
#
# I think you could add a check to see if this was suid root, but
# I can't remember...
#
# Ultrix 4.0 and 4.1
chroot="/usr/bin/chroot"
fix_date="1 May 1991"
cert_advis="CA-91:05"
if $TEST -f "$chroot" ; then
cur_date=`$LS $LS_OPTS $chroot | $AWK '{print $8, $7, $9}'`
$ECHO $chroot $fix_date $cur_date $cert_advis $real_date | $BUG
fi
# /usr/bin/mail
#
# Fixed in 4.2
mail="/usr/bin/mail"
fix_date="23 Aug 1991"
cert_advis="CA-91:13"
if $TEST -f "$mail" ; then
cur_date=`$LS $LS_OPTS $mail | $AWK '{print $8, $7, $9}'`
$ECHO $mail $fix_date $cur_date $cert_advis $real_date | $BUG
fi
# finis
cops_104/disclaimer 755 313 12 2240 5156725222 7475 /***********************************************************************
* Copyright 1989, 1990, 1992 by Dan Farmer. All rights reserved. Some
* individual files may be covered by other copyrights.
*
* This material was originally written and compiled by Dan Farmer at
* Purdue University in 1989 and 1990, under the direction and sponsorship
* of Professor Gene Spafford. Other material was contributed as noted
* elsewhere. Recently, work has been done at the Software Engineering
* Institute. Even more recently, stuff has been done at Sun Microsystems.
*
* Redistribution and use in source and binary forms are permitted
* provided that this entire copyright notice is duplicated in all such
* copies. No charge, other than an "at-cost" distribution fee, may be
* charged for copies, derivations, or distributions of this material
* without the express written consent of the copyright holders.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR ANY PARTICULAR PURPOSE.
************************************************************************/
cops_104/docs/ 755 313 12 0 5156725263 6305 cops_104/docs/COPS.report 600 313 12 76151 5156725224 10412 .ps 12
.vs 12
.PH ````
.pn
.nr W 78
.ce 2
\fBCOPS and Robbers
UN*X System Security\fP
.sp
.sp
.PP
In the last few years, computer security has received a great deal
more attention than it has in the past. Computerized break-ins and
criminal activity, once merely the product of the imagination of
science fiction writers,
has became a fairly common occurence in both commercial and academic
circles. In this paper, I will go over the problems that face any
multiuser computing system, then discuss how these problems apply to UNIX\**
.FS
Although originally designed and developed by Ken Thompson and
Dennis Ritchie of AT&T, UNIX has grown far beyond its' original
design and now numerous companies market their own \*Qflavor\*U of
UNIX. When I use the term UNIX in this paper, I don't mean merely
AT&T's version, but instead I mean the majority of the most popular
varieties, made by developers at Berkely, Sun, and a host of other
manufacturers. I believe UNIX is still a trademark of Bell
Laboratories.
.FE
specifically, and finally present in detail a suite of programs that
were developed in an attempt to address some of the main problems
that could be solved via software. UNIX, although considered to be
a fairly secure operating system ([Wood 88], [Duff 89], etc), has the
advantage of having many published works ([Grampp and Morris 84],
[Bishop 83], etc) on the problems that a computing site can have with
security, and in addition, on how a UNIX system administrator might
make his/her system more secure by monitoring various aspects of his/her
UNIX site. This, combined with UNIX's popularity, make it an ideal
target for a software security system to operate on.
.PP
In this report I am not going to discuss specific ways of breaking
into a given UNIX machine (for a more detailed description on how to
compromise UNIX security, see either [Baldwin88], [Bishop83],
[Wood & Kochran 86], or [Grampp & Morris 84]) -- instead, I will
concentrate on how to improve and strengthen the potentially good
security of a generic UNIX system by means of a software toolkit
that examines the weaker areas of UNIX that are either traditionally
ignored (due to the time constraints or ignorance of the system
administrators) or are simply reoccurring problems that need to be
watched over. In addition, this report is not meant for UNIX neophytes
-- although a great deal of proficiency is not needed to read
this report and use the programs described herein, a familiarity with
basic UNIX features -- the file system and file permission modes for
example -- and commands such as
.ul
awk, grep, sed
as well as a working knowledge of shell and C programming are necessary
to understand the internal workings of the security system described in
this paper.
.PP
Although there is no reasonable way that all security problems can be
solved (at least not with a software solution) on any arbitrary UNIX
system, administrators and system programs can be assisted by a software
security tool. The Computer Oracle Password and Security system (COPS)
that will be described in this paper is just such a device. The COPS
system is a collection of programs and shell scripts that attempt
to address as many of these problems as possible in an efficient,
portable, and above all in a reliable and safe way. The main goal
of COPS is one of prevention; it tries to anticipate and eliminate
security problems by making sure people don't get a chance to
compromise security in the first place. Alerting the
administrators of a potential intruder or that a virus has infected
the system is beyond the scope of the present system, although with
work with such capabilities could be added ([Bauer and Koblentz 88]
and [Duff 89].)
.PP
To understand the reason COPS might check any specific problem, a
look at computer security problems in general is in order. The
problems listed below are not meant to be inclusive, but they are
indicative of the myriad types of dilemmas a typical computer multiuser
system might encounter:
.PP
1) Administrators, system programmers, and computer operators. The
very people that (should) worry the most about security are sometimes
the ones that are the
least concerned. Carelessness is one of the main culprits; a mistake by a user
might cause little or no problem, but when someone with no
restrictions (or almost none) on their computer activity makes a mistake,
a security hole can result. \*QI can trust my users\*U is a fine
statement to make -- but can you trust your users' friends? How about
the users of computers that are networked to yours?
New software, systems, or procedures
can facilitate extra problems; a computing staff is often ill or
completely non-trained on new techniques and software.
Too often \*QRTFM\*U is the only training that they will ever receive.
Programs that are created for in-house use are often ill-documented and
not debugged thoroughly, and when users other than the author start to
use/abuse the program, problems can result. Especially misunderstood,
even by experienced UNIX system programmers, is the SUID program or,
worse yet, the SUID shell script ([Bishop 83].)
When a user says that his/her password was forgotten (or any
other account/security related problem), what checks are made to verify
that the person is really the owner of that account? Are users that are
security problems kept track of, so that repeated abuses of the system will
result in punitive action? Does your site even have a security policy?
And of course, the last straw is that most system administrators simply
have too much other work to do than to constantly check
the system for potential security flaws -- let alone to double-check that
any work done by other system programmers has been done correctly.
These are the actions that often get left unsaid and undone.
.PP
A UNIX environment has no special defenses against this kind of
\*Qattack\*U. Fortunately, a number of these potential problems (unless
catastrophic in scope) are not only correctable, but are
easy to detect with a software toolkit such as COPS. Even the most
careful UNIX guru will periodically make a mistake; COPS has been
designed to aid in her/his never ending battle against the forces of
darkness.
.PP
2) Physical security. This is perhaps the most frustrating of all
possible problems because it effects all computer systems and is often the
hardest to safeguard against. Even if the software is secure, even if
the system administrators are alert to potential problems, what happens
if a user walks up to the root console and starts typing? Does the night
janitorial staff let anyone into the machine room without proper
identification? Who has access to the key that opens up the computing
center? Are terminals that are logged on left unguarded or unlocked?
Are passwords written on or near a users terminal or desk?
No software in the world can help
against human nature or carelessness. Reiterating to your staff and users
that terminals should not be left alone or unguarded and that passwords
(especially root) should not be typed in front of unfriendly (and in
this case, _everyone_ is your enemy) eyes would be a good start. A
simple analogy: since you would never give the keys to the company car
away, why on earth would you give away the keys to your computer, which
is certainly worth a hell of a lot more time and money (although it may
not get as good mileage on the interstate.) Common sense goes a long
ways to help prevent this kind of risk.
.PP
3) Authentication. What is authentication? All modern computing
systems that have capabilities for multiple users have a means of
identifying who is
using the computer at any given time. A common means of identification
is by using a password; and since the inception of this idea, poor
passwords have been a perennial problem. People have a tendency to
use their own name, or their social security number, or some other
common word, name, or phrase for a password. The problem then arises
when an unauthorized user wants to access clandestine information,
he/she simply tries one of these simple passwords until a successful
match is found.
.PP
Other problems with authentication? What computer hosts are
\*Qtrusted\*U and allow users to log in from other machines without
any further authentication? Are incorrect login attempts kept and/or
monitored so as to allow administrators to keep track of any unusual
activity? What about \*QTrojan horses\*U -- programs that can steal
passwords and the privileges that a user owns -- is there a program or a
administrative method that detects a potential 'horse?
.PP
Fortunately UNIX systems again have some fairly good tools to aid in
this fight. Although finding simple passwords is indeed a trivial
task, forcing the users on a system to use passwords that are harder to
guess is also
trivial, by either modifying the mechanism that gets/gives the password
to the user, and/or by having the system administrators run a simple
password detector periodically, and notifying users if their password is
deemed too obvious. The
.ul
crypt
command, although proven to be insecure for a knowledgeable and
resourceful attacker ([Reed and Weinberger 84], [Baldwin 86]), does
offer an added shield against most unauthorized users. Logs can be kept
of incorrect login attempts, but as with most security measures, to be
effective someone (usually the site administrator) must take the time to
examine the evidence.
.PP
4) Bugs/Features. Massive software designs (such as an operating system)
are usually the result of a team or of teams of developers working together.
It only takes one programmer to make a mistake, and it will almost always
happen. \*QBack doors\*U that allow unauthorized entrances are sometimes
purposefully coded in -- for debugging, maintenance, or other reasons.
And there are always
unexpected side effects when thousands of people using the system start
doing strange (stupid?) things. The best kind of defense against this
is to report the problems to the developer as they are discovered, and
if possible, to also report a way to fix the problem. Unfortunately,
in many cases the
source code is needed to make a bug fix, and especially in non-academic
areas, this is simply not available due to the prohibitive costs involved.
Combining this with the reluctance of a (usually) commercial developer
to admit any problems with their product, and the end result is a
security hole that will not be mended unless some kind of financial loss
or gain is at stake -- for the developer of the product, not yours!
.PP
5) Ignorance. Users who don't know or care can be a problem as well.
Even if
someone doesn't care about their own security, they can unwittingly
compromise the entire system -- especially if they are a user with
high privileges. Administrators and system operators are not immune to
this either, but hopefully are better informed, or at least have access
to a means of combating this dysfunction. It may also be due to apathy,
an unwillingness to learn a new system, a lack of time to explore all of
the features of a large system, or simply not enough computer savvy to
learn more about a very complex system, and no one willing to
teach it to the user. This problem is much like illiteracy; it is a
never-ending battle that will never go completely away. And while a
software toolkit such as COPS can help combat this problem by calling
attention to neglected or misunderstood critical areas, by far and away
the best weapon against this is education. An educated user will simply
not make as many mistakes; and while it may seem impractical to teach
_all_ users about (even) the fundamentals of computer security, think of
all the time and resources wasted tracking down the mistakes that keep
recurring time and time again.
.PP
6) Unauthorized permissions or privileges. Are users given _too much_
freedom? Do new computer accounts have any default security at all, or
are the new users expected to know what to do to protect their programs,
data, and other files. System files, programs, and data are sometimes
shipped with minimal or no protection when gotten straight from the
manufacturer; someone at the installation site must have enough
knowledge to \*Qtune\*U the system to be effective and safe. Password,
memory, and log files especially should all be carefully monitored,
but unfortunately an experienced user can often still find out any information
they want with perseverance and a little luck. This is
where a system such as COPS can really shine. After a new system is
configured, some basic flaws can be uncovered with just a small amount
of effort. New system problems that somehow slip through the cracks of
the site installers can be caught and modified before any serious
problems result. The key here is to prevent your system users from
getting a denial of computer service that they need and deserve. Service
could mean anything from CPU time, response time, file space, or any
other commodity that a computer has to offer.
.PP
7) Crackers/Hackers/Evil twin brothers. Not much is needed on this
subject, save to say that they are often not the main problem.
Professional evil-users are a rarity; often harmful acts are done
by users who \*Qjust wanted to see what would happen\*U or had no idea
of the ramifications of their acts. Someone who is truly experienced is
very difficult to stop, and is certainly outside the realm of any
software security tool as discussed in this paper. Fortunately, most
evil-doers are fairly inexperienced and ignorant, and when they make a
mistake, a watchful administrator can deal with a problem before it gets
out of hand. Sometimes they can even reveal security problems that
were previously undiscovered. COPS can help here mostly by reducing an
attacker's options; the less holes to exploit, the better.
.PP
The COPS system attempts to help protect as many of the above
items as possible for a generic UNIX system. In the proper UNIX spirit,
instead of having a large program that attempts to solve every possible
problem, it is composed of several small programs that each check one
or more potential UNIX security holes.
The COPS system uses a variety of these problems to see if there are any
cracks in a given UNIX security wall. These methods correspond to some
of the problems discussed above; specifically to administrators, system
programmers, and computer operators; authentication; ignorance;
unauthorized permissions or privileges; and finally crackers/hackers/evil
twin brothers (numbers 1,3,5, and 6.) It is very difficult, almost a
practical impossibility to give software assistance to problems in
physical security, and finally bugs or features that are present in a
given UNIX system are possible to detect, but are not covered in this
system (yet). The design of most of the the programs were at least
described if not outlined from the following sources:
.sp
Aho, Kernighan, and Weinberger 88
.sp
Baldwin 87
.sp
Fiedler and Hunter 86
.sp
Grampp and Morris 84
.sp
Wood and Kochran 86
.sp
.PP
Of course with all of the problems listed below, looking at the actual
source code of the program is very instructive -- each numbered section
lists the corresponding program that is used to perform the check. COPS
checks:
.PP
1) \*Qvital\*U system files and directories to see if they
have dangerous permissions (usually either world-writable, or world-readable.)
Files and directories thought to be critical are in a configuration
file
.ul
is_able.lst.
Wildcards are useable like in UNIX; indeed, COPS
passes everything to the shell for expansion.
.sp
The program that performs this task is
.ul
is_able.chk
.PP
2) Check devices for file systems to see if they are world-readable/writable,
plus check for any exported NFS file systems with no restrictions.
The file systems are normally found in /etc/fstab.
.sp
The program that performs this task is
.ul
dev.chk
.PP
3) Check all files in system for SUID status, notifying the COPS user
of any changes in SUID status, and if any SUID files are world-writable,
shell scripts, or non-executable (program) files.
.sp
The program that performs this task is
.ul
suid.chk
and was written by Prentiss Riddle.
.PP
4) Check the /etc/passwd file (and the yellow pages password database, if
applicable) for null passwords, improper # of fields, non-unique user-id's,
non-numeric group id's, blank lines, and non-alphanumeric user-id's.
.sp
The program that performs this task is
.ul
passwd.chk
.PP
5) Check the /etc/group file (and the yellow pages database, if
applicable) for groups with passwords, improper # of fields,
duplicate users in groups, blank lines, and non-unique group-id's.
.sp
The program that performs this task is
.ul
group.chk
.PP
6) Check passwords of users on system.
.sp
Method -- using the stock \*Qcrypt\*U command, compare the encrypted
password found in the /etc/passwd file against the following
(encrypted) guesses:
.sp
The login id (uid), information in the gecos field, and all single
letter passwords.
.sp
The program that performs this task is
.ul
pass.chk
and was written by Craig Leres and was modified by Seth Alford,
Roger Southwick, Steve Dum, and Rick Lindsley. Bugs have been reported
and fixed by numerous people.
.PP
7) Check the root path, umask, also if root is in /etc/ftpuser and
owns /bin, /etc, /etc/passwd, /.login, /.profile and /.rhosts, and
finally if a \*Q+\*U is in /etc/hosts.equiv.
.sp
The program that performs this task is
.ul
root.chk
.PP
8) Examine the commands in /etc/rc* to ensure that none of the
files or paths used are world-writable.
.sp
The program that performs this task is
.ul
rc.chk
.PP
9) Examine the commands in /usr/lib/crontab to ensure that none of the
files or paths used are world-writable.
.sp
The program that performs this task is
.ul
cron.chk
.PP
10) Check all of the user home directories to ensure they are not
world writable.
.sp
The program that performs this task is
.ul
home.chk
and was written by John Owens.
.PP
11) Check important user files in user's home directories to ensure
they are not world writable, plus checks netrc files to see if they
are readable. The files checked (all in the individual
users' home directory, all with the prefix \*Q.\*U):
.sp
rhosts profile login cshrc kshrc tcshr crhost
.sp
netrc forward dbxinit distfile exrc emacsrc logout
.sp
The program that performs this task is
.ul
user.chk
.PP
12) Checks ftp setup; anononymous ftp setup, if you support it. This
seems to be fairly site specific; it tries to check for correct ownership,
file/directory permissions, etc.; for a complete description, check the
man page for ftp.chk.
.sp
The program that performs this task is
.ul
ftp.chk [-a]
.PP
13) Check for unexpected file system corruption or security breaches,
using CRC values that are generated from your system files, then
compared against previously calculated values. As the author says:
\*QIt's nice to be able to say that you know all your files
are as they should be.\*U
.sp
The program that performs this task is
.ul
crc.chk.
Mark Mendel wrote most of
.ul
crc.c
and Jon Zeef wrote
.ul
crc_check.c
.PP
14) Checks a few miscellaneous potential security problems that really
don't belong anywhere else. This includes looking to see if tftp &
rexecd are enabled, to check if the uudecode alias is in the mail
alias file and not commented out, if uudecode is either SUID or can
create SUID files, and if the programs inside the /etc/inetd.conf
or /etc/servers aren't world-writable.
.sp
The program that performs this task is
.ul
misc.chk
.PP
15) Given a goal to compromise, such as user root, and a list of user
and group id's that can be used in an attempt to achieve the goal, this
security tool will search through the system until it verifies that the
goal is compromisible or not. The program that performs this tricky task
is part of the
.ul
U-Kuang
(rhymes with \*Qtwang\*U)
system. Robert Baldwin was kind enough to allow me to include this
security checker (a fine security machine in it's own right)
within this distribution. For more information on this fascinating
security checker, see kuang.man.ms and [Baldwin 87]. I have rewritten
it in Bourne shell (it was in C-Shell) for further portability; Steve
Romig rewrote it in Perl for speed.
.PP
.PP
None of programs listed above certain cover all of the possible areas
that can harm a system, but if run together they can aid an overworked
administrator to locate some of the potential trouble spots. The COPS
system is not meant to be a panacea against all UNIX security woes,
but an administrator who examines the security toolbox programs and
this research paper might reduce the danger of their UNIX system being
compromised -- and that's all any security tool can ever hope to do.
The COPS system could never replace a vigilant administration
staffed with knowledgeable people, but hopefully, as administrators look
into the package, more comprehensive programs will come into being,
covering more of the problems that will continue as the latest versions
of UNIX continue to grow.
.PP
Design Notes:
.PP
The programs that are described here were designed to address the
problems discussed above, but still be usable on as many UNIX
\*Qflavors\*U as possible. Speed was sacrificed for
simplicity/portability; hopefully the tools here will either be
replaced or modified, as by no means are they the final word or
solution to _any_ of these problems; indeed, it is my hope that
after other programmers/administrators see this report, they will
create newer, better, and more general tools that can be
re-distributed periodically. None of the programs need to be run by
root to be effective, with the exception of the SUID checker (to
ensure that all files are checked.) Some of the tools were written by
myself, the others were written by other programmers on the network
and (with their permission) presented here. All of the programs in
this report are in the public domain, with the exception of Robert
Baldwin's U-Kuang system; they all exist solely to be used and
modified to fit your needs. If they are re-distributed, please
keep them in their original form unless it is clearly stated that
they were modified. Any improvements (that might not be too hard :-)),
suggestions, or other security programs that
you would like to see get further distribution can be sent to:
.PP
df@medusa.cs.purdue.edu
.PP
(That's me)
.PP
or
.PP
spaf@uther.cs.purdue.edu
.PP
(Dr. Eugene Spafford)
.PP
.PP
Enhancements I envision include:
.sp
i) Improved speed and portability without sacrificing functionality
(pretty obvious, I guess....)
.sp
ii) A level of severity assigned to each warning; anything that could
compromise root instantly (root having no password, for example) might
have a level 0 priority, while simply having a user with a writable home
directory might only be level 3. This way the system could be run at
a certain threshold level, or simply have the set of warnings
prioritized for a less sophisticated administrator.
.sp
iii) The eradication of any design flaws or coding errors that are in
the COPS system.
.PP
The main purpose of creating the COPS system was twofold; the first was
to foster an understanding of the security problems common to most UNIX
systems, and the second was to try to create and apply software tools
that, when run, will inform system administrators of potential problems
present in their system. No attempt is made by the tools to correct any
problems because a potential security problem at one site may be
standard policy/practice at another. An emphasis on furthering
education and knowledge about UNIX in general is the key to good
security practices, not following blindly what an unintelligent tool
might say.
.PP
Some of the advantages to using a system such as COPS are:
.sp
i) Nearly Continuous monitoring of traditional problem areas.
.sp
ii) A new system can be checked before being put into production.
.sp
iii) New or inexperienced administrators can not only stop some of their
problems in security they may have, but can also raise their
consciousness about the potential for security dilemmas.
.PP
And a couple of disadvantages:
.sp
i) An administrator could get a false sense of security from running
these programs. Caveat emptor (ok, they are free, but still beware.)
.sp
ii) A specific path to the elimination of the problem is not presented.
This could also be construed as an advantage, when considering the third
point.
.sp
iii) Badguys can get these tools. You know -- the guys with black hats.
What happens when they get a copy of this package? With any sensitive
subject like security, knowledge is zealously guarded. People are
afraid that absolute knowledge corrupts -- who knows, they may be right.
But I staunchly stand by the tree of knowledge. Let the bad guys taste
the fruit, and they may see the light, so to speak. In addition, the
system does not say how to exploit the hole, just that it exists.
.PP
.ul
Results of Running COPS:
.PP
Not surprisingly, the results when COPS was run varied significantly
depending on what system and site it was run on. Here at Purdue, it was
run on a Sequent Symmetry running DYNIX 3.0.12, on a pair of Suns (a
3/280 and 3/50) running UNIX 4.2 release 3.4, a VAX 11/780 running 4.3
BSD UNIX, a VAX 8600 running Ultrix 2.2, and finally a NeXT machine
running their 0.9 O/S version of UNIX. The results of the COPS
system showed a reasonable amount of security concern on all of the
machines; the faculty only machines showed the weakest security, followed
by the machines used by the graduate students, and finally the undergraduate
machines had the strongest security (our administrators _know_ that you
can't trust those (us?) young folks.) Whether this was showing that
Purdue has a good administration, or that the UNIX vendors have a fairly
good grasp on potential security problems, or if it was merely
showcasing the shortcomings of this system wasn't clear to me from the
results.
.PP
The security results probably will vary significantly from machine to
machine -- this
is not a fault of UNIX; merely having the same machine and software
does not mean that two sites will not have completely different security
concerns. In addition, different vendors and administrators have
significantly varying opinions on how a machine should be set up. There
is no fundamental reason why any system cannot pass all or nearly all of
these tests, but what is standard policy at one sites may be an
unthinkable risk at another, depending upon the nature of the work being
done, the information stored on the computer, and the users of the
system.
.PP
When I first started researching this report, I thought it would be a
fairly easy task. Go to a few computing sites, read some theoretical
papers, gather all the programs everyone had written, and write a
brief summary paper. But what I found was an
tremendous lack of communication and concerted effort towards the
subject of security. AT&T had written a couple of programs ([Kaplilow
and Cherepov 88], as had Hewlett Packard ([Spence 89]), but they were
proprietary. I heard rumors that the
government was either working on or had such a security system, but they
certainly weren't going to give it to me.
The one book devoted to UNIX security ([Kochran and Wood 86]) was good,
but the programs that they presented were not expansive enough for what
I had in mind, plus the fact that they had written their programs
mostly based on System V. And while most system administrators I talked
to had written at least a shell script or two that performed a minor
security task (SUID programs seemed the most popular), no one seemed to
exchange ideas or any
their problems with other sites -- possibly afraid that the admission of
a weakness in their site might be an invitation to disaster. There is
an excellent security discussion group on the network ([Various Authors
84-]), from which I received some excellent ideas for this project, but
it is very restrictive to whom it allows to participate. I hope that
with the release of this security system it will not only help stamp
out problems with UNIX security, but would encourage people to exchange
ideas, programs, problems and solutions to the computer community at large.
Dan Farmer
September 29, 1989
(latest changes on January 7, 1991)
.PP
.ul
Acknowledgements:
I would like to thank Eugene Spafford for his invaluable help in
the researching, planning, and development of this project. Without
the writings and programs created by Robert Morris, Matt Bishop, and
other capable UNIX programmers, this project could never have gotten
off the ground. Thanks also go to Brian Kernighan, Dennis Ritchie,
Donald Knuth, and Ken Thompson, for such inspirational computer work.
And of course without Peg, none of this would have come into being.
Thanks again to all of you.
.bp
.ce
.ul
BIBLIOGRAPHY
.sp
_, UNIX Programmers Manual, 4.2 Berkeley Software Distribution,
Computer Science Division, Department of Electrical
Engineering and Computer Science University of California,
Berkeley, CA, August 1983.
.sp
_, DYNIX(R) V3.0.12 System Manuals, Sequent Computer Systems, Inc., 1984.
.sp
Aho, Alfred V., Brian W. Kernighan, and Peter J. Weinberger, The
AWK Programming Language, Addison-Wesley Publishing Company, 1988.
.sp
Authors, Various, UNIX Security Mailing List/Security Digest,
December 1984 -.
.sp
Baldwin, Robert W., Crypt Breakers Workbench, Usenet, October
1986.
.sp
Baldwin, Robert W., Rule Based Analysis of Computer Security,
Massachusetts Institute of Technology, June 1987.
.sp
Bauer, David S. and Michael E. Koblentz, NIDX - A Real-Time
Intrusion Detection Expert System, Proceedings of the Summer
1988 USENIX Conference, Summer, 1988.
.sp
Bishop, Matt, Security Problems with the UNIX Operating System,
Department of Computer Sciences, Purdue University, January
31, 1983.
.sp
Bishop, Matt, How to Write a Setuid Program, April 18, 1985.
.sp
Denning, Dorothy, Cryptography and Data Security, Addison-Wesley
Publishing Company, Inc, 1983.
.sp
Duff, Tom, Viral Attacks On UNIX System Security, Proceedings of
the Winter 1988 USENIX Conference, Winter, 1988.
.sp
Fiedler, David and Bruce Hunter, UNIX System Administration,
Hayden Book Company, 1986.
.sp
Grampp, F. T. and R. H. Morris, "UNIX Operating System Security,"
AT&T Bell Laboratories Technical Journal, October 1984.
.sp
Kaplilow, Sharon A. and Mikhail Cherepov, "Quest -- A Security
Auditing Tool," AT&T Bell Laboratories Technical Journal,
AT&T Bell Laboratories Technical Journal, May/June 1988.
.sp
Morris, Robert and Ken Thompson, "Password Security : A Case
History," Communications of the ACM, November 1979.
.sp
Reed, Brian, "Reflections on Some Recent Widespread Computer
Break-ins," Communications of the ACM, vol. Vol 30, No. 2,
February 1987.
.sp
Reed, J.A. and P.J. Weinberger, File Security and the UNIX System
Crypt Command, Vol 63, No. 8, AT&T Bell Laboratories
Technical Journal, October 1984.
.sp
Smith, Kirk, Tales of the Damned, UNIX Review, February 1988.
.sp
Spafford, Eugene H., The Internet Worm Program: An Analysis,
Purdue Technical Report CSD-TR-823, Nov 28, 1988.
.sp
Spafford, Eugene H., 1989. Private Communications
.sp
Bruce Spence, spy: A UNIX File System Security Monitor, Workshop
Proceedings of the Large Installation Systems Administration III,
September, 1988.
.sp
Stoll, Clifford, Stalking the Wily Hacker, Volume 31, Number 5,
Communications of the ACM, May 1988.
.sp
Thompson, Ken, Reflections on Trusting Trust, Volume 27, Number
8, Communications of the ACM, August 1984.
.sp
Wood, Patrick and Stephen Kochran, UNIX System Security, Hayden
Books, 1986.
.sp
Wood, Patrick, A Loss of Innocence, UNIX Review, February 1988.
t another. An emphasis on furthering
education and knowledge about UNIX in general is the key to good
security practices, not following blindly what an unintelligent tool
might say.
.PP
Some of the advantages to using a system such as COPS are:
.sp
i) Nearly Continuous monitoring of traditional problem areas.
.sp
ii) A new system can be checked before being put into production.
.sp
iii) New or inexperiecops_104/docs/KUANG.README 600 313 12 1566 5156725225 10114
The U-Kuang system is currently setup in a minimum configuration; e.g.
it assumes only that world modes/permissions are to be used. To fully
use the system, if the password checkers and the home-directory checker
come back with any positive results (i.e. with an account that can be
broken), modify the init_kuang file to reflect this.
To use this system to it's full capabilities, be sure to read the
manual, kuang.man.ms.
This directory contains the various programs and shell scripts
that make up the Kuang security checking system.
The file, kuang.man.1, documents the system in the style of a UNIX
manual page. The file, kuang.mss, is a draft of a paper on
this system.
To run the system:
0. Execute 'make' to build the programs.
1. Read kuang.man.1
2. Modify the file, init_kuang, to set the initial set of privileges.
3. Execute "sh kuang" (or run the COPS system.)
cops_104/docs/SUID.README 600 313 12 765 5156725225 7773 Findsuid is a little utility we dreamt up to watch for potential Trojan horse
programs by keeping an eye on our suid and sgid files and telling us when
they change unexpectedly.
We run it using the following line in crontab:
40 3 * * * /etc/findsuid/findsuid >/etc/findsuid/fserror 2>&1
Included here is the findsuid shell script, a man page, a makefile, and a
sample "stop" file.
--- Prentiss Riddle ("Aprendiz de todo, maestro de nada.")
--- {ihnp4,harvard,seismo,gatech,ctvax}!ut-sally!riddle
cops_104/docs/cops 600 313 12 7257 5156725226 7263 .TH COPS 1 "Jan 4, 1991"
.UC 4
.SH NAME
cops \- Checks security of system for potential danger areas.
.SH SYNOPSIS
.B cops
[
\-a architecture
]
[
\-b bit_bucket
]
[
\-s secure_dir
]
[
\-m user
]
[
\-xvV
]
.SH DESCRIPTION
.I cops
runs a set of programs that each check a different aspect of security
on a Unix system. If any potential security holes do exist, the results
are either mailed or saved to a report file.
.PP
The following programs are currently executed by
.I cops
\-\- see the appropriate man page or other documentation for
more information on each of the following:
.Ps
root.chk dev.chk group.chk
home.chk rc.chk passwd.chk
pass.chk user.chk cron.chk
misc.chk is_able.chk crc.chk
bug.chk
.Pe
In addition, it runs the U-kuang expert system, which runs these
additional programs:
.Ps
init_kuang kuang addto
clearfiles filewriters members
.Pe
.PP
.I cops
uses three internal variables that may be changed to determine where
who gets any reports generated, if it is to mailed or saved to a file.
Thes variables may be set by command line flags or by actually changing
the variables in the code. $SECURE_USERS is used to determine who gets
mailed any results, and is set when the \-m flag is used. $SECURE is
the directory that
.I cops
is in, and is set by the \-s flag. Finally, if the variable $MMAIL is
set to be NO (or the \-m flag is used), then
.I cops
will save the report in a subdirectory with the same name as the host
it is being run on, in a file called
.I year_month_date
(where this stands for the actual values/date, not that string.)
Otherwise,
.I cops
will mail the report to the whomever is listed in $SECURE_USERS.
.PP
If the variables $ONLY_DIFF and $MMAIL are set to be "YES", then cops
will examine the last report saved to a file, and compare it with the
current one. If any differences do exist, then it will be mailed; else,
the report will be discarded.
.PP
If you suspect that something is amiss, or if you're just curious or
a gluttons for punishment, you can set the variable $BIT_BUCKET to be a
file (or use the -b flag), to see all the error messages and such.
Some of the programs in cops print out an error message if a file isn't
found (for instance, if you put a file to be checked in the
.I is_able.lst
configuration file, and it doesn't exist, it will not complain to the
final report, only here; by default, this is our friend /dev/null.
.SH OPTIONS
.TP
.B \-a directory
Specifies the architecure subdirectory you want to run in; you
must run "make install" to install the appropriate binaries there.
.TP
.B \-b file
Specifies the "bit bucket", where all the error messages (stderr) go to.
You can use "tty" to go to your terminal.
.TP
.B \-s secure_dir
Tells cops where the secure directory is; this is used by
cops itself when it is run with the -a flag; it will rerun itself
with the -a flag's argument as an argument to this.
.TP
.B \-m user
Mail the output to the user specified.
.TP
.B \-x
Prints the current version number of COPS.
.TP
.B \-\[vV\]
Verbose flags. Lowercase "v" prints the program currently
running to the results file, and capital "V" will print the program
to the screen.
.SH FILES
.EX 0
root.chk dev.chk group.chk
home.chk rc.chk passwd.chk
pass.chk user.chk cron.chk
misc.chk init_kuang kuang
addto clearfiles filewriters
members crc.chk
.EE
.SH "SEE ALSO"
.EX 0
root.chk(1) dev.chk(1) file.chk(1)
group.chk(1) home.chk(1) rc.chk(1)
passwd.chk(1) pass.chk(1) user.chk(1)
cron.chk(1) misc.chk(1) kuang(1)
bug.chk(1) CRC.README KUANG.README
.EE
.SH BUGS
COPS will get confused if you use a command line arg that
expects an argument and you don't give it one.
cops_104/docs/dev.chk 600 313 12 1425 5156725227 7631 .TH DEV.CHK 1 "December 31, 1989"
.UC 4
.SH NAME
dev.chk \- Checks writability of devices and special files.
.SH SYNOPSIS
.B dev.chk
[
\-g
]
.SH DESCRIPTION
.I dev.chk
checks the permissions of /dev/mem, /dev/kmem, and
all devs listed in the file /etc/fstab for readibility/writeability (the
.I mount
command would be
a preferable way of getting the file system name, but the syntax of the
output is variable from machine to machine), and flags them if they are
readable by using the
.I is_readable
command, unless they are NFS mounted,
in which case they are ignored. It also checks for unrestricted exported
NFS filesystems in /etc/exports.
.PP
options are:
.TP
.B \-g
Check for group writability as well as world.
.SH FILES
.EX 0
/etc/fstab
/etc/exports
.EE
.SH "SEE ALSO"
is_able(1)
cops_104/docs/CRC.README 600 313 12 10266 5156725227 7675
This README.suid and everything but the C programs has been hacked up be
me, so all problems you have are probably due to me, unless you can't compile
the files. Then blame Jon :-)
This checks for unexpected file system corruption or security breaches.
It's nice to be able to say that you know all your files are as they should
be. Mark Mendel wrote most of crc.c and Jon Zeef wrote crc_check.c. Seems
to work fine on BSD or SYS V.
To use it:
1) You first create a crc list with the script "crc.chk", which takes one
argument, the seed for the crc generator. It reads the file "crc_list"
for a list of files to check; what I have are some of the more interesting
binaries, but you can add or delete from this list to your hearts content.
Wildcards or specific file names are fine. The first time you run it,
it will create a file called "crc.files", which contains all the crc
values you generated. Optionally, you can do a:
find / -mount -print | sort | xargs ./crc -v > crc.tmp
However, "xargs" is a security problem, when combined with find. Use
this judiciously, if at all, unless your vendor puts some "safe" options
to find in.
2) You can now use "crc.chk" to compare this "crc.files" file to a crc list
created each time you run the shell program. If everything is ok, nothing
is outputted, otherwise, the results are either mailed to the user INFORM,
on line xxx, or saved to a file "crc.results". You *MUST* use the same
seed each time you run the program, or the numbers generated will be
different each time you run the program, which kind of makes it useless.
IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT
IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT
IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT
Have I got your attention? Good. There are some fundamental problems
with using a crc program like this. *If* you use a seed that is hardcoded
in the program, or no seed at all, this is *bad*. That means to really
use this program usefully, you can't run it in crontab, like the rest
of COPS. Even worse, you should really store the results offline, since
anyone who breaks into your machine can modify a binary file, run the
crc checker again, then put the new values in your file. That's the
right way. But I know that most of you won't do this, so by default,
"crc.chk" just stores everything like everything else, in the COPS secure
directory. It can still help you, if the attacker doesn't know where
you keep stuff, or doesn't know enough to trash your database of old
crc values. If nothing else, be sure that you keep your older values
on tape or secondary medium, so when your system gets kicked around a
bit, you can grab the crc program off the tape (the intruder could modify
that, too, you know), run it on your binaries, and finally compare it
to your old values. Believe me, this is a lot easier, though still not
perfect, than reloading everything on your system from tape, then still
not knowing. I've put it in the "cops" shell script, but left it commented
out, on line 123, so if you want to use it this way, just uncomment this
line.
One thing you can do, if you keep the numbers online, is do a crc on the
file of values you keep; write it down, or memorize it, then if it is ever
tampered with, you can detect it.
Jon goes on about the initial crc value, and other stuff:
=========================================================================
... don't tell anyone what this is, you can
make it nearly impossible for anyone to modify a file in such a way
that it has the same crc value as the old one (primarily because they
don't know what the old one was). If anyone does discover a way to
make files of the same size that produce the same unknown crc value
for any unknown -i value, let me know.
To really do it right, you need to
1) Run find_crc in single user mode (unless you modify the crc source).
2) Store all crc results offline.
3) Don't let anyone see your -i value or the crc results.
Please send me any modifications you make.
Jon Zeeff
zeeff@b-tech.ann-arbor.mi.us
=========================================================================
Send 'em to me, too!
-- dan
iles" file to a crc list
created each time you run the shell program. If everything is ok, nothing
is outputted, otherwise, the results are either mailed to the user INFORM,
on line xxx, or saved to a file "crc.results". You *MUST* use the same
seed each time you run the program, or the numbers generated will be
different eachcops_104/docs/home.chk 600 313 12 416 5156725230 7754 .TH HOME.CHK 1 "December 31, 1989"
.UC 4
.SH NAME
home.chk \- Checks user home directories for world writability.
.SH SYNOPSIS
.B home.chk
.SH DESCRIPTION
This checks all of the user home directories (it calls getpwent() to
get user directories) for world writability.
cops_104/docs/pass.chk 600 313 12 3264 5156725231 10017 .TH PASS.CHK 1 "Feb 4, 1992"
.UC 4
.SH NAME
pass.chk \- Checks for poor passwords in a password file.
.SH SYNOPSIS
.B pass.chk
[
options
]
.SH DESCRIPTION
By default
.I pass.chk
only checks for accounts with passwords the same
as the login name. The following options add more extensive checking. (The
tradeoff is cpu time -- with all options enabled it can run into the 100's
of MINUTES.) Any argument that does not begin with a "-" is assumed to be
a file name. (A single '-' means stdin.) If no file name is given, /etc/passwd
is used.
.PP
Options are:
.TP
.B \-v
verbose -- list all guesses on stdout
.TP
.B \-u
output the username on the line of the password file
currently being checked. If the program stops
abruptly you will then know how far it got.
.TP
.B \-w file
use the list of words contained in "file" as likely
passwords. Words in the file are one to a line.
A variable, "ARB_CONST", on line 6 of the source file, "pass.c",
determines how many words can be in the dictionary file. Default is 32000.
.TP
.B \-b
check all guesses backwards too
.TP
.B \-g
use the Full Name portion of the gecos field, the user's .plan, .forward,
and .signature files to generate more guesses
.TP
.B \-s
check the single letters a-z, A-Z, 0-9 as passwords
.TP
.B \-c
with each guess, check for all lower case and
all upper case versions too.
.TP
.B \-n
complain about null passwords (default is to keep quiet)
.TP
.B \-p
print the password when guessed
.TP
.B \-P file
use an alternate password file
.PP
If used on a Sun or Sun compatible, compiling with the -DC2 flag will
enable C2/shadow passwords to be cracked (it must be run as root, however,
to read the shadow password file.)
.SH FILES
.br
.nf
/etc/passwd
.fi
cops_104/docs/is_able 600 313 12 1715 5156725231 7702 .TH IS_ABLE 1 "Jan 4, 1991"
.UC 4
.SH NAME
is_able \- Check for write/read\-ability of a file.
.SH SYNOPSIS
.B is_able
file {w|g|S|s} {r|w|s|B|b}
.SH DESCRIPTION
.I is_able
can check a file to see if a file is either write/read-able by group or by
all, or if it is setuid/setgid, or a combination of these. A first argument
of "w" or "g" determines whether it is to be world or group writable,
respectively, a "s" or "S" allows checking of SUID or SGID files, respectively.
A second argument of "r", "w", or "s", stands for readability, writeability,
or set[ug]id-ness, respectively; a "B" and a "b" stand for read and write,
and set[ug]id and write, respectively.
.I is_able
with a write option also checks the parent directories, if a complete path is
given, for writeability.
.SH BUGS
The Andrew File System, or Mach, or the combination of the two, apparently
plays games with stat(), the way I get the file info, so it can report things
as writable, when they aren't.
cops_104/docs/kuang.1 600 313 12 5371 5156725232 7553 NAME
kuang - rule based system to find inconsistencies in the security
configuration of a BSD 4.2 Unix.
SYSNOPSIS
edit init_kuang to reflect attackers initial goals
sh kuang > tracelog
DESCRIPTION
Kuang is a rule based system that searches for a path from an
initial set of privileges to a desired set. Given a goal, kuang uses
rules to determine a set of subgoals which are sufficient to achieve the
initial goal. The rules are then applied to the subgoals to determine a
set of sub-subgoals, etc. This process repeats until there are no new
goals to examine. If a subgoal can be directly achieved using the
attacker's initial privileges, then a line is added to the file
'Success' that describes how the attacker can achieve the top level goal.
The rules for Unix can be divided into three categories
depending on whether they deal with files, users, or groups. Kuang
embodies these rules in three shell scripts, dofiles, douids, and
dogids. Goals that have been examined are recorded in the files
files.p, uids.p, and gids.p. The files files.n, uids.n, and gids.n
record the goals that will be examined next. The shell script, kuang,
applies the goals in each .n file to the corresponding rule file.
The initial privileges and ultimate goal are set up in the shell
script, init_kuang. If the program finds a sequence of rules that
connects the initial privileges to the ultimate goal, that sequence will
be recorded in the file Success. Each step in the sequence is recorded
as a pair of words. For example, the line "gids users, write
/usr/bob/.login, trojan baldwin, grant staff, write /etc, replace
/etc/passwd" means that the password file can be replaced because the
group staff has write access to the directory /etc, and you can get
access to the staff group because the .login file for the user bob can
be written by members of the group users, which is one of your initial
privileges.
FILES
*.n - goals to process in the next round.
*.x - goals currently being processed.
*.p - goals that have been examined.
uids.* - goals related to user IDs.
gids.* - goals related to group IDs.
files.* - goals related to files.
Success - log of holes that are found.
tracelog - step by step trace of search.
AUTHOR
Bob Baldwin, MIT Lab for Computer Science, Programming and
Systems Group.
E-Mail Address :
baldwin@xx.lcs.mit.edu
...!mit-eddie!baldwin
Kuang was inspired by William Gibson's book, Neuromancer, which won the
1984 Hugo award. In honor of Gibon's book, systems that use rule based
searching to find security holes should be called a kuang-type systems.
BUGS
Needs to be smarter about command files (e.g., it should look
for writeable files executed via crontab).
Doesn't include rules for all the programs that run with
their user id set to root.
cops_104/docs/kuang.man 600 313 12 107362 5156725234 10233 .ps 12
.vs 12
.PH ````
.nr W 80
.in 0
.ce 3
\fBKuang: Rule-Based Security Checking\fP
Robert W. Baldwin
MIT, Lab for Computer Science Programming Systems Research Group
.PP
The security of data in a particular computer depends both on the
integrity of the computer's protection mechanism and on the consistent
uses of those mechanisms by the users of that computer. Software
verification and specification technology addresses the integrity
problem, but very little has been done to insure that the protection
mechanisms are being used consistently. This paper describes a
rule-based system that finds inconsistencies in the set of protection
decisions made by the users of an information system.
.PP
\fBIntroduction\fP
.PP
The trend in commercial computer systems has been to increase the the
number of mechanisms that allow users to execute commands and to
increase the number of mechanisms that allow users to share
information. All of these mechanisms must be considered to be part of
the protection system. For example, if users can specify a set of
commands that will be executed automatically every night, then the
database that contains these commands, and the program that processes
the database must be considered part of the protection system. Even
if the program has been certified to work correctly, the access list
for the command database and the set of privileges available to the
processing program must be considered to be part of the protection
configuration \**
.FS
The protection configuration is a subset of the
access matrix. The access matrix specifies how each user can access
each object. I use the term
.ul
protection configuration
to refer to the portion of the access matrix concerning the objects
used by any piece of the protection system.
.FE
of that computer. The problem
considered in this paper is ensuring that the protection configuration
is consistent with the user's security goals.
.PP
The goal of flexible information processing and sharing makes
computers more useful, but that goal also makes protection systems
larger and more complex. The large number of interactions between the
pieces of the protection system makes it hard for the users to make
protection decisions correctly. This is particularly true when parts
of an information system are managed by novices (e.g., personal work
stations). Users need automated tools for analyzing the interactions
between the pieces of a large protection system.
.PP
This paper describes a class of systems, called Kuang-type \**
.FS
This
project was inspired by William Gibson's book
.ul
Neuromancer
, which won the 1984 Nebula award for best science fiction novel.
Gibson's book describes innovative ways to visualize the structure of
information systems. In particular, it describes a program called a
Kuang Grade Mark 11 Ice Breaker (
.ul
ice
refers to the mechanisms used
to protect access to information). The program described in this memo
is a greatly simplified version of that ice breaker program.
.FE
systems, for analyzing large protection configurations.
This class of systems is illustrated by a Simple Unix Kuang program
(SU-Kuang) that answers a question about a Unix protection
configuration. The question is "what if an attacker had access to a
given set of privileges (groups), could that attacker become
super-user?". SU-Kuang allows a system manager to perform a simple
what-if analysis of a protection configuration, and in this mode it
helps the manager make protection decisions. A typical use of SU-Kuang
is to run it periodically to see if access to the group, World, (i.e.,
minimum privileges) is sufficient to become super-user. In this mode
Kuang functions as an automatic security checker. SU-Kuang is just one
possible tool for helping users cope with the complexity of a large
protection system. Some other desirable tools are mentioned at the
end of this paper.
.PP
The heart of the SU-Kuang program is a set of rules that describe the
Unix (BSD4.2) protection system from the point of view of an
attacker. For example, one rule says that if an attacker can write
the file /etc/passwd (the authentication database), then that attacker
can become super-user. To decide whether to use this rule, an
attacker would examine the protection configuration of the target
machine to see what privileges are required to write the file
/etc/passwd. Using similar rules, SU-Kuang can answers the what-if
question by performing a backward chaining search of the protection
configuration (see figure
.ul
goal-tree
). Given a goal, like become
super-user, SU-Kuang examines all the rules to produce a list of
subgoals that would be sufficient to meet its goal. Recursively, each
of the subgoals can be processed to produce a list of sub-subgoals.
The process continues until there are no new goals. At each step, if
a goal can be achieved using the initial privileges of the attacker,
SU-Kuang prints out a message that describes the sequence of steps
that leads from the initial goals to the target goal.
.sp
.sp
.nf
Become Super-User
/ \\
/ \\
Replace /etc/passwd Write /.rhosts
/ \\ .
/ \\ . .
Become Staff Write /etc
. .
. . . .
. . . .
.fi
(Example of a goal-tree used by SU-Kuang. The nodes of the tree
are goals desired by an attacker.
The children of each node are the subgoals that are sufficient to
achieve the parent goal. The goal-tree used by SU-Kuang is a pure
OR-tree. Any one of the subgoals is sufficient to grant the parent goal.)
.PP
Notice that SU-Kuang does not find holes in the Unix operating system.
It finds mistakes in the protection configuration. For example,
SU-Kuang found a security hole on an MIT machine that resulted from
two incorrect decisions about who should have write access to start-up
command files. SU-Kuang points out holes by describing the sequence
of steps used to exploit the hole. The sequence SU-Kuang printed was:
"member MIT, write ~tom/.cshrc, member A_STAFF, write ~dick/.login,
member STAFF, write /etc, replace /etc/passwd, become ROOT". This
means that the attacker had access to the group MIT, which all users
are in. The MIT group had write access to one of the start-up command
files executed automatically when the user Tom (not his real
name) logged in. Anyone in the MIT group could add commands to Tom's
start-up command file, and have these commands executed with Tom's
privileges next time Tom logged into the machine. Tom is a member of
the Athena Staff group, which is not particularly privileged. However,
the A_STAFF group does have write access to one of Dick's start-up
command files, and Dick is a member of the Staff group, which is one
of the most privileged groups. In fact, members of the staff group
can write the directory that contains the password database. Write
access to the directory allows staff members to delete and recreate
the password database. By creating a password database that has a
known password for the super-user account, members of the staff group
can acquire super-user privileges.
.PP
My experience running SU-Kuang is that these mistakes are created
periodically because the users do not understand the interactions
between the numerous pieces of the Unix protection system. However,
it is not complicated to write a program that can explore all the
possible interactions. SU-Kuang itself is a simple program, and
generating the rules that describe the pieces of the protection system
is also easy (see section
.ul
rules
). The simplifying idea is to
describe the protection system in terms of how an attacker can
manipulate it. Using this framework, performing the analysis is easy.
.PP
I consider any system that uses attacker-oriented rules to be a
Kuang-type system. The remainder of this paper describes the Unix
Kuang system I built to determine whether a given set of privileges is
sufficient to become super-user. The nature of the rules and the
process used to deduce them is illustrated in section
.ul
rules
, which lists the set of rules used to model Unix. The model used by
SU-Kuang was incomplete in several ways, so section
.ul
extensions
describes some of the features of Unix that were not
modeled. The incomplete model turned out to be very effective at
finding security holes, so section
.ul
experience
presents the
lessons learned from running SU-Kuang on the computers at MIT. The last
section discusses other kinds of Kuang systems and their benefits.
.PP
\fBRules to model Unix\fP
.PP
The first step in generating attacker-oriented rules is to determine
the types of goals that are relevant to an attacker of the target
system. These goal types can be deduced from the basic protection
model of the operating system, so before presenting the rules, the
Unix protection model is summarized. The second step is to make a
list of the pieces of the protection system and to examine each one in
terms of the goals an attacker could achieve using each piece.
The pieces of the Unix protection system that were included in the
prototype's model are listed below along with the rules used to
describe each piece.
.PP
\fBSummary of the Unix protection model\fP
.PP
The Unix protection model concerns processes and files. Associated
with each process is one user identifier UID, and one or more group
identifiers (GIDs). The UID and GIDs are generally inherited when one
process forks another. One exception is that the super-user (UID =
0) can change the UID and GIDs of his current process. The other
exception is that a user can associate a UID and GID with a program
stored in the file system. When anyone runs such a program, the
process executing that program will run with the stored user and/or
group IDs.
.PP
Associated with each file is one UID, one GID, and nine permission
bits. The nine permission bits are divided into three groups to
specify the read, write, and execute rights for the file's owner
(specified by the UID), for the members of the file's group (specified
by the GID), and for all others (the World group). Directories are a
special case of files. For a directory, read permission allows a
process to list a directory, write permission allows a process to
create or delete files in that directory, and execute permission
allows a process to resolve names in that directory even if the
directory is unreadable.
.PP
When a process accesses a file or directory it is given either owner,
group, or world access permissions, but only one of those three.
Owner access is granted if the process and file UIDs match; Group
access is granted if the process and file UIDs are different but the
file's GID is in the list of GIDs for the process; otherwise, World
access is granted. The super-user has full access to all files and
directories. Only the owner or the super-user can change the access
permissions of a file.
.PP
\fBThree types of attacker goals\fP
.PP
The Unix protection model deals with users, groups, and files, so
those are the three types of goals that will concern an attacker. The
canonical user goal is "execute one of the attacker's programs with a
particular UID". For example, the top level goal is "execute a
program chosen by the attacker under UID zero (i.e., as
super-user)". It is important that the attacker be able to specify
the program to be executed with super-user privileges. The login
program runs as super-user, and anyone can run it. The attacker wants
to specify the computation performed with super-user privileges. One
scheme for getting access to super-user privileges is to write the
command file that is executed automatically when the super-user logs
in.
.PP
Group ID goals are similar. The canonical form of a GID goal is
"execute an arbitrary program with a particular group ID". One
possible way to achieve this goal is to add the attacker's UID to the
list of users allowed to access the desired group. This authorization
database is stored in the file /etc/group.
.PP
The canonical file goal is "obtain read/write/replace access to a particular
file". Achieving a file goal usually involves getting access to a
particular group or user ID. However, if the attacker wants to replace
a file, one way to do that is to delete the old file and create a new
one. That can be done if the attacker has write or replace access to
the directory that contains the target file.
.PP
In summary, SU-Kuang considers three types of goals for an attacker of
Unix: user, group, and file. Each type of goal can lead to subgoals
of the same or different type.
.PP
\fBSome pieces of the Unix protection system\fP
.PP
This section presents the rules that describe many of the pieces of the
Unix protection system. Section
.ul
extensions
describes the
significant pieces that were left out of the prototype's model. The
pieces of the Unix protection system include all programs, like
.ul
login,
that have the set user/group ID property. It also includes programs
like
.ul
cron
(cron executes commands in the future) that
are forked off by processes that run with special user or group IDs.
Finally, programs like
.ul
sh
(a command interpreter) must be included
in the protection system because when they are started they execute
commands from a file using the privileges of the user invoking them.
.PP
Each rule describes how a piece of the protection system can be
used by an attacker to achieve a desired goal in terms of the ability
to achieve a subgoal. The method used to achieve a goal given the
subgoal may require that some condition be true. For that reason the
rules include a condition that can be tested to decide if the subgoal
should be pursued. The conditions are general predicates on the state
of the protection configuration. For example, the rule that says that
an attacker can become the super-user by writing the password file,
has the condition that the password file is writable by someone other
than the super-user.
.PP
In the rules listed below, the notation \*Q/d/f\*U means a
pathname for the file \*Qf\*U in the directory with pathname \*Q/d\*U.
The goal, \*Qbecome U\*U, means to execute an arbitrary command under the
user ID \*QU\*U. The goal, \*Qmember G\*U, means the same thing for
group \*QG\*U. The goal, \*Qwrite /d/f\*U, means being able to write the
file \*Q/d/f\*U. Finally, \*Qreplace /d/f\*U, means being able to write
\*Q/d/f\*U or being able to delete \*Q/d/f\*U and recreate it.
.PP
\fBThe file system\fP
.PP
Most programs in the protection system use the file hierarchy to
locate their databases. If the file hierarchy can be modified, then
the protection system can be tricked into using the wrong database
files. The file hierarchy itself must be treated as one of the
main databases in the protection configuration.
.PP
The notation \*QOwner(/d/f)\*U refers to the UID associated with the
file \*Q/d/f\*U. Similarly \*QGroup(/d/f)\*U refers to the file's GID.
The expression \*QGroupWrite(/d/f)\*U is true if the file \*Q/d/f\*U can
be written by the members of \*QGroup(/d/f)\*U. The expression
\*QWorldWrite(/d/f)\*U is true if the file can be written by members of
the World group (i.e., all users).
.sp
Rules{
.sp
.ul
.PP
Replace /d/f Write /d/f
.PP
Replace /d/f Replace /d\**
.FS
The condition stops the
recursion at the root directory of the file system.
.FE
.PP
Write /d/f Become Owner(/d/f)\**
.FS
The owner of a file can
always change the access permissions to allow owner write access.
.FE
.PP
Write /d/f GroupWrite(/d/f) Member Group(/d/f)
.PP
Write /d/f WorldWrite(/d/f) Member World\**
.FS
This subgoal is
is achievable by all users provided they can get to the file. The
notable exceptions are users logged in via anonymous ftp or uucp
connections. These users have restricted access to the file
hierarchy.
.FE
.sp
}
.PP
\fBlogin\fP
.PP
The login program uses two database to set the UID and GIDs of the
user's command interpreter. The contents of
these databases and the protection of the databases themselves
must be considered part of the protection configuration.
.PP
The user name \*Qroot\*U refers to the super-user. The label, \*QU\*U, stands
for an arbitrary UID including \*Qroot\*U. The label, \*QG\*U, stands for
an arbitrary GID. The expression \*QUIDS(G)\*U expands to all the
UIDs authorized to use the group \*QG\*U according to the files
/etc/group or /etc/passwd.
.sp
Rules{
.sp
.ul
Become U Replace /etc/passwd\**
.FS
This rule matches the goal \*QBecome root\*U.
.FE
Member G Replace /etc/group
Member G Become UIDS(G)\**
.FS
The subgoal means to try to become any member of the group \*QG\*U.
.FE
.sp
}
.PP
\fBrsh, rlogin, rcp\fP
.PP
Berkeley Unix includes several remote execution commands that greatly
improve the usability of multiple Unix hosts connected by a network.
The underlying authentication protocol does not resist an attacker
that can transmit arbitrary messages on the network, but even if that
problem was fixed, the databases used by these programs would have to
be considered as part of the protection system.
.PP
The file /etc/hosts.equiv lists the names of the hosts that are
trusted by the target machine's administrators. If a user has an
account on the target machine, and on one of the trusted hosts, then
that user can log into the target machine from the trusted machine
without supplying a password. Users can list additional hosts (or
other users) that they trust in a file (.rhosts) in their home
directory.
.PP
The expression \*QNotEmpty(/d/f)\*U is true if the file /d/f exists and
it is not empty. The label, \*Q~U\*U, refers to the home directory of user
\*QU\*U.
.sp
Rules{
.sp
.ul
.PP
Become U (~U/.rhosts) /etc/hosts\**
.FS
If there is
a host listed in the user's remote access database and the host name
table is replaceable, then an attacker can make his host appear to be
the host listed in the user's database. This assumes that the
attacker has super-user privileges on some host that can talk to the
target host, because the attacker will need to create an account with
the target's user name. This attack will become obsolete when hosts
start using a distributed name server rather than a fix hostname
database. However, the name server will open other avenues of attack.
.FE
.PP
Become U Write ~U/.rhosts\**
.FS
The remote execution routines insist that the target user be the owner
of the database file, so replace access is not sufficient to use this
attack.
.FE
.PP
Become U root Replace /etc/hosts.equiv\**
.FS
Remote execution with super-user privileges is only accepted from
the hosts listed in ~root/.rhosts, so replacing the hosts.equiv file
cannot be used to directly gain access to super-user privileges.
.FE
.sp
}
.PP
\fBshells\fP
.PP
Several command interpreters, called shells, have been written for
Unix. Different users can use different shells, but all shell have
some mechanism for executing a list of commands when a user logs in.
The files that specify these initialization commands are a part of the
protection configuration that each user can change.
.PP
The expression \*QExists(/d/f)\*U is true if the file /d/f exists.
.sp
Rules{
.sp
.ul
.PP
Become U Exists(~U/.login) Replace ~U/.login\**
.FS
This file contains the commands read when a user logs in.
The conditional should really test to see if the user is actually using
the /bin/csh command interpreter. If csh is being used, then
this rule will work even if the file .login doesn't exist, so
the conditional is overly strict.
.FE
.PP
Become U Exists(~U/.cshrc) Replace ~U/.cshrc\**
.FS
This file is read each time a /bin/csh is executed such as at login
and when a command file is executed. The conditional is also overly
strict.
.FE
.PP
Become U Exists(~U/.profile) Write ~U/.profile\**
.FS
Same trick for the /bin/sh command interpreter.
.FE
.sp
}
.PP
\fBcron\fP
.PP
Cron is a program that is forked off when a Unix system is booted.
This means that it runs with super-user privileges. Cron reads a
database (/usr/lib/crontab) that describes the commands that should be
executed periodically. By default these commands are executed with
\*Qroot\*U privileges.
.sp
Rules{
.sp
.ul
Become root none Replace /usr/lib/crontab
.sp
}
.PP
\fBsendmail\fP
.PP
The Unix mail system has many features that allow flexible forms of
information sharing. The most interesting feature (to system builders
and to attackers) is that receiving mail can trigger the invocation of
a program which is passed the mail message as its input. The file
/usr/lib/aliases specifies the human readable form of a binary
database that describes mailing lists, mail forwarding, and programs
to invoke when mail is received by certain mailboxes. Being able to
modify this database allows an attacker to get access to other
people's user and group IDs because the mail sending program runs with
the privileges of the user who invokes it. If the destination of the
message is on the same host as the source, then the receiving program
(also sendmail) will run with the invoker's privileges. If the source
of the message is on another computer, then sendmail will run under
the UID \*Qdaemon\*U.
.sp
Rules{
.sp
.ul
.PP
Become daemon none Replace /usr/lib/aliases\**
.FS
This assumes
that the command to build the binary database can be executed by
everyone, or that it is executed automatically when the mailer detects
that the binary database is out of date. There should also be rules
to see if the binary database can be written directly.
.FE
.PP
Become root none Replace /usr/lib/aliases\**
.FS
Assumes that
\*Qroot\*U sends mail to some user on this machine. Such users can be
found by scanning the mail logs, which are usually World readable. If
such a user exists, the aliases database can be set up to tell sendmail to
deliver mail to the recipient and invoke the attacker's program. Next
time root sends mail to that user, the attacker's program will be
invoked with root privileges. The program would test to see if it was
running with \*Qroot\*U privileges, and if so plant a trap door such as
making /.rhosts publicly writable.
.FE
.sp
}
.PP
\fBboot\fP
.PP
When a Unix reboots, it executes the commands in the file /etc/rc.
This file usually executes the commands in the file /etc/rc.local.
.sp
Rules{
.sp
.ul
Become root Exists(/etc/rc) Replace /etc/rc
Become root Exists(/etc/rc.local) Replace /etc/rc.local
}
.PP
\fBExtensions to the Unix model\fP
(extensions)
.PP
This section lists some of the important pieces of the Unix protection
system that were left out of the SU-Kuang's model. Most of these
pieces could be added easily.
.PP
The major deficiency of the model is that it does not include all of the
programs that run with super-user privileges. Each of these
programs must be modeled if there is some way that an attacker could
use the programs' databases to get access to root privileges.
.PP
Locating all the programs that run with super-user privileges is not
easy. Many ordinary programs are executed inside of command files
that are run with root privileges. This points out another
shortcoming of SU-Kuang. It does not look inside of command files.
For example, on system restart, Unix executes the commands in the file
/etc/rc with super-user privileges. That file executes additional
commands in the file /rc.local, so those commands also runs as root.
The prototype has an explicit rule that covers this case, whereas it
should deduce this and other cases by parsing the commands in /etc/rc.
.PP
The prototype does not understand search paths. On Unix, as with most
systems, users do not specify the full pathname of the programs they
want to execute. Instead, users specify a sequence of directories
that should be searched to find the program. Often users tell their
command interpreter to first look in a private directory of commands,
and quite often that directory is writable by any member of the user's
primary group. If an attacker can write a user's private command
directory, then the attacker can plant a trojan horse on that user.
For example, the user may want to execute /usr/local/gnuemacs, but the
user may end up executing the attacker's program in
/usr/smith/@_bin/gnuemacs. To model this attack, SU-Kuang would need to
be able to read each user's startup command file to determine each
user's search path.
.PP
The file goals considered by the model only include write and replace
access to a file. Read access is not considered. To include read
access, each piece of the protection system must be re-examined to see
if it could provide read access to an arbitrary file. For example,
the Unix finger program, which displays information about users, runs
with super-user privileges so it can read an information file (.plan)
in the specified user's home directory. Unfortunately, some
implementations of the finger program allow the .plan file to be a
symbolic link to another file, and thus the finger program allows read
access to any file on the system.
.PP
The rules that model the file system do not include the fact that the
disks can be accessed via the raw device files. Reading and writing
the device files can be used to read and write arbitrary blocks on the
disks. These files should only be accessible to the super-user, but
often anyone can read them. If so, an attacker can read any file on
the disk.
.PP
A different kind of deficiency in the model is that it does not allow
the attacker to guess at passwords. On a system that allows users to
pick their own passwords, an attacker can usually guess a few of the
passwords. Assuming that an attacker can read the password file,
\**
.FS
Protecting the password file from users logged in on a guest
account or using anonymous file transfer is a good idea. However,
protecting it from ordinary users is hard. Many programs need read
access to the non-password information kept in that file, and making
all those programs run with special privileges may create more
problems than it solves.
.FE
the attacker can test passwords at the rate of about ten per second.\**
.FS
There are lots of tricks that speed up the execution of
the Unix salted DES function on a 32 bit machine.
.FE
A 2000 word dictionary of common passwords can be processed at the
rate of a few minutes per account.
.PP
As in any kind of modeling, the better the model, the better the
results. Fortunately, in the case of Unix, making the model more
detailed does not require using a more complicated framework. The
rule-based framework of SU-Kuang is flexible enough to model all the
features described in this section.
.PP
\fBPrototype Implementation\fP
(implementation)
.PP
The SU-Kuang program described in this paper is easy to
implement. The primary inputs to the program are a list of groups
(privileges) accessible to the attacker (including the special group
\*QWorld\*U), and the target goal (usually \*Qbecome root\*U). The
program examines the protection configuration of the machine it is
running on, so this can be considered a secondary input. The
primary output is a list of the ways that an attacker can achieve the
target goal from the initial privileges. Internally, the program
builds a goal-tree based on a set of rules that are compiled into the
program. When a node of the goal-tree can be directly achieved using
the initial privileges, the program prints out the sequence of steps
that describe the path from the given node of the goal-tree to the
root of the goal-tree.
.PP
In classic Unix style, the prototype was initially implemented by a
set of shell scripts (command files). Later, to improve performance,
some of the shell scripts were re-written in C. The top level
shell script keeps track of the goal-tree, and invokes other shell
scripts to generate successive levels of the goal-tree. For each of the
three kinds of goals (user, group, and file), there is a shell script
that reads a list of goals of that kind and produces a list of
subgoals.
.PP
Associated with each node of the goal-tree is a human readable comment
that describes the path from each node to the root of the goal-tree.
This comment is appended to a list of 'successes' if the
associated goal can be directly achieved using the initial privileges
of the attacker. Since each comment specifies the sequence of steps
an attacker could use to achieve the target goal given the current
goal, it is easy to derive the comments for subgoals from the comments
of parent goals. The subgoal comments is the parent goal's comment
plus an indication of which rule was used to derive the subgoal.
.PP
The basic data abstraction used by SU-Kuang is a goal-table. There
are three goal-tables, one for each type of goal. The operations on a
goal table are:
.ul
new,
.ul
addto, and
.ul
next. The
.ul
new
operation creates an empty goal table. It takes a set of initial
goals that are directly achievable by the attacker. The
.ul
addto
operation adds a goal and a comment to the table. If the goal is
already in the table, the table is not changed. If the goal is in the
set of directly achievable goals, then
.ul
addto also appends the
comment to the file that contains a list of successes. The operation,
.ul
next, examines a goal-table and returns any goal-comment pair that
it has not already returned. The
.ul
addto
operation is effectively
the inner loop of a rule interpreter.
.PP
The goal-table abstraction is implemented by four files. One file
keeps track of all of the goals in the table and it is used to avoid
duplicate goals. Another file holds the list of goals initially
available to the attacker. Two files are used to support the next
operation. One file records all the goal-comment pairs that have been
returned by the next operations, the other file lists the goal-comment
pairs that have been added to the table but not yet selected by the
next operation.
.PP
Using the goal-table abstraction it is easy to express rules as lines
of a shell script. Figure
.ul
shell
rule shows a rule and its shell
script implementation. The conditional part of the rules are
expressed by shell script conditionals (e.g., \*Q-z\*U means that a file
exists and has a length of zero, \*Q!\*U and \*Q&&\*U mean logical
negation and conjunction).
.sp
Rules{
.sp
.ul
Become root NotEmpty(/.rhosts) Replace /etc/hosts
.sp
}
.nf
# $User and $OldComment are set by the goal-table next operation.
# $FileGoals refers to the goal-table object for file type goals.
if (($User == "root") && (! -z /.rhosts)) then
set NewComment="Fake HostAddress, $OldComment"
set SubGoal="Replace /etc/hosts"
addto $FileGoals $SubGoal $NewComment
endif
.fi
Sample rule and corresponding shell script line.
.PP
The implementation of SU-Kuang is straight forward. The only reason
for describing it in this paper is to demonstrate how easy it is to
process the attacker-oriented rules that describe a protection system.
.PP
\fBExperience\fP
(experience)
.PP
The SU-Kuang system has been run on a large number of
sites managed by personnel with a wide range of skills and interests
in security. It has almost always found a hole. A Kuang that
incorporates the extensions described in section
.ul
extensions
would find more holes.
.PP
I believe that holes are created because users do not understand how
the various pieces of the protection system interact. The main
evidence for this is that fact that most holes are found in the
protection databases that are maintained by ordinary users (e.g.,
.login and .rhosts). Also, users who have recently been given special
privileges tend to create holes that allow anyone to achieve
super-user privileges. When I tell users about the problems SU-Kuang
finds, they often do not understand what was wrong with the decision
they made.
.PP
Users create security holes periodically. When I ran SU-Kuang
periodically on one computer that had a large complicated protection
configuration (e.g., the authorization databases included 300 users
and 25 groups), SU-Kuang found new holes every week or two. Often
these new holes were created when someone modified a security
database. One common procedure for modifying a database is to first
rename the original, then copy of the original into a file with the
proper name, and finally edit the copy. The motivation for the first
rename step is to preserve the timestamp that indicates when the
database was last written. Unfortunately, the file copy step does not
copy the protection information from the original database. The
protection for the copy is determined by the defaults for the
currently running process. It is not determined by the original. The
file UID is set to the UID of the process that performs the copy,
and the GID is set to the GID of the directory that contains
the file. The permission bits are set to a default value specified in
the copier's login command file.
.PP
The holes found by SU-Kuang point out that it is hard to set up multiple
separate security groups under BSD4.2 Unix. For example, a group
that allows its members to install programs in the /etc directory,
also allows its members to replace the authentication database in
/etc/passwd. The fact that users run with their full privileges (i.e.,
they can access multiple groups in the same process), makes Berkeley
Unix easier to use than other versions of Unix that force users to
access one group at a time. However, that same feature makes it
easier for an attacker to plant a trojan horse on a user that is a
member of a lower privilege group (e.g., the implementors of some
project) and a member of a high privilege group (e.g., staff).
.PP
The impression I have gotten from running SU-Kuang is that most of the
features that make Unix easy to use also make Unix hard to secure.
However, SU-Kuang does make it easier to build a secure protection
configuration for Unix.
.PP
\fBDiscussion\fP
(conclusions)
.PP
To increase the usefulness of computers, systems designers have
provided an increasing number of mechanisms that allow users to
execute commands and share information. Since these new mechanisms
must be considered part of the protection system, this trend has made
protection systems larger and progressively harder to understand. As
a protection system becomes more complex, it becomes unlikely that
all the protection decisions are made correctly, and these mistakes
can ruin the overall security of the information and resources
controlled by computers. The commercial environment presents a
special problem because usability is the primary goal of commercial
information systems, but security cannot be neglected. There needs to
be some way to manage the complexity of the protection systems that arise
on information systems that stress usability.
.PP
This paper presents one approach for achieving both usability and
security. The idea is to use rule-based systems to analyze the
interactions between all the decisions that make up a computer's
protection configuration. If analyzing a protection configuration is
easy, then the manager of a system can ensure that the system meets
the security objectives of its users. A program that performs a
simple analysis of a Unix protection configuration was presented to
illustrate that this sort of rule-based system is easy to build if
the protection system is described from the attacker's viewpoint.
This simple Unix analysis system, called SU-Kuang, answered the
question "given access to a particular set of privileges,
can an attacker achieve super-user privileges?". Using SU-Kuang,
a security manager could ensure that a system did not allow ordinary
user to achieve super-user privileges.
.PP
SU-Kuang is just one of many helpful Kuang-type systems. For example,
many security objectives are expressed in terms of limiting the set of
people who have access to particular privileges. A Kuang-type system
that computed the set of privileges accessible to each user would help
a security manager determine whether the security objectives are being
met. Even better, if the bulk of the security objectives can be
expressed in computer understandable form, then the bulk of the work
of checking computer security could be automated.
readable comment
that describes the path from each node to the root of the goal-tree.
This comment is appended to a list of 'successes' if the
associated goal can be directly achieved using the initial privileges
of the attacker. Since each comment specifies the sequencops_104/docs/rc.chk 600 313 12 1416 5156725235 7456 .TH RC.CHK 1 "December 31, 1989"
.UC 4
.SH NAME
rc.chk \- Checks contents of /etc/rc* file(s) for potential danger.
.SH SYNOPSIS
.B rc.chk
.SH DESCRIPTION
.I rc.chk
checks pathnames and files inside the shell script files /etc/rc*
(e.g. /etc/rc, /etc/rc.local, etc.) for writability.
It filters out all paths or files that have a /tmp, /dev/null,
or /dev/*ty, plus everything after a ">"; e.g. if crontab is writing
to a file it doesn't care.
.SH FILES
.br
.nf
/etc/rc*
.fi
.SH BUGS
Awk runs out of room ("bails out") if too many files are found in the
/etc/rc* files.
.PP
Spurious messages can occur --
.I rc.chk
only uses a approximation of which files should be checked. Also,
Unless a file has a full pathname (i.e. begins with a "/", it will
not be checked for writability.
cops_104/docs/is_able.chk 600 313 12 1727 5156725236 10456 .TH IS_ABLE.CHK 1 "Jan 4, 1991"
.UC 4
.SH NAME
is_able.chk \- Check for write/read\-ability of files listed a configuration file.
.SH SYNOPSIS
.B is_able.chk
.SH DESCRIPTION
.I is_able.chk
checks all files listed in the file
.I is_able.lst
to see if files are either write/read-able by group or by
all, or if they are setuid/setgid, or a combination of these.
.PP
.I is_able.lst
is merely a list of files (or regular expressions representing a file
or files), one per line, that are checked by
.I is_able.
Any line starting with a "#" is ignored, and any file checked for
writability also checks the parent directories (if a complete path is
given) for writeability.
.SH EXAMPLE
.br
.nf
# Lines are of the format:
# /path/to/file
/etc/*
/.profile
.fi
.SH FILES
is_able.lst
.SH Bugs
When using wildcards and checking a directory with a lot of files, overflow
of the shell variables can occur, causing incorrect arguments to be passed
to the driving program.
.SH See Also
is_able(1)
cops_104/docs/release.notes 600 313 12 11574 5156725237 11105
Brief Info-Capsule of COPS programs and files (release 1.03):
-------------------------------------------------------------------------
Programs and some important files that are included in this release:
-------------------------------------------------------------------------
cops A driving shell script for most of the programs
below. It tosses output to /dev/null (unless
the -b flag is used) except what it wants to see,
and either saves the results a report file or mails
any pertinent output (depending if the -m flag is
used).
Usage: cops [-a:b:s:m:xvV]
chk_strings Checks for writable paths/files in a file.
Usage: chk_strings
crc.chk Creates and compares a database of CRC's (a kind
of digital signature that changes as the file
changes size or is otherwise modified) that warns
against changes in the filesystem. Concievably,
virii and worms could be detected in this manner,
but I wouldn't hold my breath.
crc_list List of files that are checked.
crc_seed If run automatically, crc.chk creates a semi-random
seed to use, to make your CRC's unique. This is
where it is stored (not recommended, but handy.)
cron.chk Checks for writable paths/files in crontab entries.
Usage: cron.chk
dev.chk Checks /dev/*mem and all devs listed by "/etc/fstab"
command for world read/writability (respectively.)
Usage: dev.chk [-g]
(-g checks for group read/writability as well)
disclaimer Vital document to COPS usage. Read closely.
ftp.chk Used mostly to check anonymous ftp setup; it
goes over the etc, pub, ~ftp, and bin directories,
for writability, ownership, general correctness, etc.
Usage: ftp -a
(-a checks for anon-ftp setup.)
is_able.chk Checks files and dirs listed in "is_able.lst"
for writability, readability, etc.
is_able.lst List of directories for above.
Usage: is_able.chk [-g]
(-g checks for group writability as well)
group.chk Checks /etc/group for non-unique groups, invalid
fields, non-numeric group ids, etc.
Usage: group.chk
home.chk Checks all users home-dirs listed in /etc/passwd
for bad modes (basically world write, strangeness).
Usage: home.chk
is_writable Checks a file/directory and determines writability
status; returns a "0" if is writable, a "1"
otherwise.
Usage: is_writable [-g] filename
kuang The U-Kuang expert system. Read the accompanying
instructions in kuang.man. It basically checks
to see if a given user (by default root) is
compromisible, given that certain rules are true
(i.e. /etc/passwd writable gives root access, etc.)
Usage: kuang
(init_kuang) Contains the targets for the kuang system.
misc.chk Checks various miscellaneous things -- tftp, decode
alias, rexd, etc.
Usage: misc.chk
passwd.chk Checks /etc/passwd for non-unique uids, invalid
fields, non-numeric user ids, etc.
Usage: passwd.chk
pass.chk Checks /etc/passwd for crummy passwords; lots
of options. Defaults to checking for the users' id.
pass.words A list of words that can be used by pass.chk;
use "pass.chk -w pass.words" to use them.
Usage: pass.chk [-flags]
pass_diff.chk A wrapper for pass.chk. Only checks passwords in
accounts that have *changed* their passwords since
last time run, though.
Usage: pass_diff.chk [-flags]
pass.mail Will scan a COPS result file, grabbing users that
have guessed passwords, and mail to them a letter
informing them of the fact, along with a "how2"
guide to create a good (i.e. hard to guess) password.
Usage: pass.mail cops_result_file
makefile A makefile for programs enclosed.
Type "make" or "make install" to make things (see
Makefile for more information.)
patchlevel.h Contains the version information of COPS; multiply
by .01 and add one, and that's the current version.
Used by "cops -x" to determine the version.
quickstart A lightning guide on how to start using COPS.
rc.chk Checks all commands and paths listed in /etc/rc*
for writability.
Usage: rc.chk
reconfig Changes the (hard coded) paths for the programs
used in COPS.
(file.paths) Data file for reconfig (created by reconfig.)
Usage: reconfig [file]
res_diff Looks to see if anything has changed since
the last report that was generated for the host.
Usage: res_diff /path/to/secure_dir current_report
suid.chk Checks the system for _changes_ in SUID status.
This is the one program that should be run as
superuser. You must first run a find on all
SUID programs from the / directory, and then use
that as a "stop file".
suid.stop The database originally set up with "find".
Usage: suid.chk [-s:n]
user_chk.c Checks all users listed in /etc/passwd; looks at
.login/.cshrc/.rhosts/.profile, etc., for bad
modes (basically world write, strangeness).
Usage: user_chk
cops_104/docs/suid.man 600 313 12 3532 5156725237 10027 .TH FINDSUID 1S
.UC 4
.SH NAME
suid.chk \- find changes in setuid and setgid files
.SH SYNOPSIS
.B suid.chk
[
\-m user
]
[
\-n
]
[
\-o file
]
[
\-s secure_dir
]
[
\-S start_dir
]
[
\-x
]
.SH DESCRIPTION
.I suid.chk
is a shell script intended to be run periodically by \fIcron (8)\fP
in order to spot changes in files with the suid or sgid bits set.
.PP
.I suid.chk
uses \fIfind (1)\fP
to search system directories for all files with the 4000 or 2000 permission
bits set. It then compares these files with the contents of a ``stop file''
(by default \fIsuid.stop\fP) containing
\fI``ls -lga''\fP
output for known setuid or setgid programs. In addition, it flags any
setuid or setgid programs that are either world-writable or shell scripts.
Any additions or changes to this list represent potential security
problems, so they are reported by mail to system administrators for further
investigation.
.SH OPTIONS
.TP
.B \-m user
Mail the results to this user.
.TP
.B \-n
Do *not* follow NFS mounted partitions. This is probably not
portable on most machines -- check the string in the source code
that does the work; on a sun, it's:
.TP
.B \-o
Writes the results to a file, rather than mailing it.
.TP
.B \-s secure_dir
Sets the secure dir, good for running this in cron --
else it'll think it's "/", and you'll chmod that to 700 :-)
.TP
.B \-S
Set the search directory where the \fIfind\fP starts. Warning -- does not
work with the
.B \-x
flag!
.br
"-type d \\( -fstype nfs -prune \\)";
.SH FILES
.nf
suid.stop (the ``stop file'')
.fi
.SH SEE ALSO
.nf
find(1), chmod(1), cron(8)
.fi
.SH BUGS
The location of the stop file and the directories to be searched
are all defined by shell variables in the source. The
.B \-S
and
.B \-x
flags do not work together.
.PP
Keeping the stop files up to date with changes to all
the suid files on more than a couple of hosts is a royal pain!
cops_104/docs/tilde 600 313 12 346 5156725240 7364 .TH TILDE 1 "December 31, 1989"
.UC 4
.SH NAME
tilde \- returns a user's home directory.
.SH SYNOPSIS
.B tilde
user
.SH DESCRIPTION
This merely prints a user's home directory, or "Error" if not found.
Named for the Csh feature.
cops_104/docs/warnings 600 313 12 40143 5156725241 10153
This file contains a list of most of the security warnings that you
might see while using the COPS system. Not included here are messages
that you may receive from the Kuang system and the ftp checker. For
help on using those tools, read the appropriate documentation on each
of those ("kuang.doc" and "ftp.1".)
First, I'll define some arbitrary terms which I'll use when describing
any problems you may encounter, then I'll list the messages, what they may
mean, and how you can change your system to eliminate any danger posed.
Some almost identical warnings were eliminated from the list; however
most warnings should have an analogous entry that is very close syntactically
to it in this file. All messages in COPS are prepended by "Warning!";
this has been excluded here for brevity.
There may be more than one way to overcome any problem listed here. If
you are unsure about whether to change a problem, try looking at some of
the references listed at the end of the technical report (cops.report) for
more information on how an attacker may compromise your system. Some of
the more dangerous security holes include writable directories and key files
(such as /etc/passwd), root owned SUID files writable to world or that give
a root shell, null passwords, and writable files that are executed by root.
They are more or less aranged in like groups (all the writable files/dirs/
whatever in one part, etc.)
Don't take everything that COPS says as gospel! What may be a serious
security hole on one machine may not be on your own, and vice-versa.
However, the more you value the information on your machine, the more you
should be concerned about security.
Some terms I'll use:
xyz -- An arbitrary number. Usually a line number in a file.
foo_file -- stands for a file you might see in your warning message.
foo_file2 -- Same as "foo_file", stands for a different file than the
first (used when two filenames are needed in one message.)
foo_dir -- a typical directory.
Group file -- /etc/group or the yellow pages group. If the warning starts
with "Group", it is the former, "YGroup" is the latter.
foo_group -- either /etc/group or ygroup.
Password file -- /etc/passwd or the yellow pages password. If the warning
starts with "Password", it is the former, "YPassword" refers
to the latter.
foo_pass -- either /etc/passwd or ypasswd.
cron_file -- will be either /usr/cron or
/usr/spool/cron/crontabs/foo_file.
foo -- anything that doesn't fit above. Usually an arbitrary
name, or group name, or whatever.
bar -- As "foo", if more than one name is needed in one message.
foo_bar -- As "foo", if more than two names are needed in one message.
WARNING MESSAGES
-----------------
0)
foo_file is _World_ writable!
foo_file is group readable!
This simply means that a file is world writable; e.g. Anyone can modify
or delete this file. This can be especially bad if the file can (even
indirectly) give root access, such as the system password file, "/etc/passwd".
To fix, type:
chmod a-w foo_file
This removes write access for group "all/world".
1)
foo_file (in cron_file) is World writable!"
File foo_file (inside root executed file foo_file2) is _World_ writable!"
File foo_file (in /etc/rc*) is _World_ writable!"
Similar to the above messages, but potentially more serious. Files
in this group are being used by root, and either being utilized as input,
output, or for execution. Examine the file they are inside and see how
it is being used. Files being executed are the most dangerous because
if they are changed, the new file gets executed with root privileges. Input
files are next, because changing them can alter what the executing program
does and cause undesirable side affects. Even output files can be dangerous,
however, because they may be used as an output or even as a program file
later on.
To fix, either delete the reference to foo_file inside the
cron/rc*/foo_file2/whatever file, or type:
chmod a-w foo_file
to remove write access for group "all/world".
2)
Directory foo_dir is _World_ writable!
This simply means that a directory (or it's parent directories) is world
writable; e.g. Anyone can delete this directory, as well as mess with the
files and subdirectories inside of it. For instance, if /usr/spool is world
writable, even if cron is not writable, this is a problem, because the cron
directory can be replaced and new crontab files put in (which all run with
root privileges.) As a general rule, if you wish to have a file or
directory secure, all directories that are parent directories must be secure.
To fix, type:
chmod a-w foo_dir
and/or
chmod a-w [foo_dir's parent directory]
This removes write access for group "all/world".
3)
Directory foo_dir is _World_ writable and in roots path!
This is the same as (2), but the directory was found to be in the
path variable set either in /.login or /.profile. This is a bad thing
because if it is writable, a trojan horse can be placed there, and
root will execute the command. See also (23).
4)
Duplicate Group(s) found in foo_group:
This means that one or more duplicate group names have been found.
This is mostly a system accounting problem; when adding or deleting names
from a group you will have problems.
To fix, remove all but one instance of each group in your /etc/group file.
5)
Group foo_bar has duplicate user(s):
Similar to (4), a group has the same user listed more than once. If
all instances of the user is not deleted, they probably will remain with
their old privileges.
To fix, remove all but one instance of a user in each group of your
/etc/group file.
6)
Group file, line xyz, non-numeric group id: foo
Group id's must be numeric. Testing a non-numeric id will give
unpredictable results.
To fix, change the old id to a valid group id.
7)
Group file, line xyz, is blank
To fix, remove all blank lines.
8)
Group file, line xyz, does not have 4 fields: foo
More trouble. Testing of one or more of the groups will result
in invalid results, depending which is the missing field(s).
To fix, ensure group has four valid fields.
9)
Group file, line xyz, nonalphanumeric user id: foo
As (6).
To fix, change the old id to a valid group id.
10)
Group file, line xyz, group has password: foo
To fix, change the old password to an asterisk ("*").
11)
Password Problem: Guessed: foo shell: bar passwd: foo_bar
If an account has a guessed password, it is susceptible to other password
guessing programs (the one in COPS is rather crude and slow). Obviously, if
the password is known, the account is compromised.
To fix, either have the user change her/his password or change it yourself.
12)
Password Problem: null passwd: foo shell: bar
Password file, line xyz, no password: foo
If an account has no password, anyone can log into the account at will.
To fix, either have the user change her/his password or change it yourself.
13)
Duplicate uid(s) found in foo_passwd:
This is a problem, especially if the accounts have different permissions
or privileges. When the user's account is deleted, one or more accounts may
remain active.
To fix, simply delete all but one occurrence of the users account.
14)
Password file, line xyz, user foo has uid = 0 and is not root bar
Ideally, no one but root should have uid = 0. Anyone with uid=0 is
superuser, for all purposes. Occasionally, a maintenance account has
uid=0, or perhaps a small group of administrators. Be very careful!
To fix, change the uid from 0 to some other valid number. If the
account or person really needs root privileges, have them su to the root
account so you can keep track of who is using root.
15)
Password file, line xyz, nonalphanumeric login: foo
Another maintenance problem. Someone's been messing with the password
file, or you have some bugs in your software that fools around with it.
To fix, delete or change the login to a valid login.
16)
Password file, line xyz, invalid login directory: foo
User foo's home directory bar is not a directory!
A user has a non-existent or invalid login directory listed in the password
file. Sometimes these are maintenance accounts, but it is discouraged.
Examine the account to see if it should really exist.
To fix, either delete the account or put in a valid login directory.
17)
Password file, line xyz, nonnumeric group id: foo
Password file, line xyz, nonnumeric user id: foo
A user has a invalid user or group id. Dangerous if, when checked, it
translates to invalid number (who knows what would happen), or worse yet, 0.
To fix, change the field to a legal, numeric value.
18)
Password file, line xyz, negative user id: foo
A user id is negative. This is most common with user name "nobody",
and with an id of "-2". This can be dangerous, especially if you are running
a Sun, with 4.xx SunOS. It is uncertain if it is dangerous for other
versions or machines. Changing it to 32767 is the usual course of action.
19)
Password file, line xyz, does not have 7 fields: foo
Dangerous, because when a program checks for a field value it will come
up with who knows what.
To fix, ensure all fields have legal values.
20)
Password file, line xyz, is blank
To fix, delete all blank lines. This can be very bad, because a blank
line can give a uid=0 account with no password.
21)
NFS file system foo exported with no restrictions.
Anyone can mount the file system. May or may not be a problem, but
look over closely, if you value ANY of the info on it!
To fix, put in a valid list of hosts that may mount it.
22)
Root's umask set to xyz
If root's umask is set incorrectly, any files that it creates will be
have bad permissions (e.g. world writable if 000, x00, or xy0).
To fix, put a "safe" value; 077 or whatever.
23)
"." (or current directory) is in roots path!
Trojan horses traditionally play upon having the current directory in
a users path. A bad user will put a trojan horse with a the same name as
a common system command ("ls" is a favorite) and place it in a location that
s/he thinks might be executed. When the trojan horse is executed, it will
not only execute the command, but will also either steal your account
privileges or have your account perform some action that they desire.
24)
A "+" entry in foo_file!
Host.equiv files specify which machines are equivalent; e.g., user foo on
another machine listed in your hosts.equiv can log in as user foo onto your
machine. A "+" means your machine trusts everyone (I trust no one :-)), which
is usually not desired, at least in these troubled times. Sun, in it's
infinite stupidity, makes this the default on all of it's machines.
To fix, either remove the "+", put in your own list of trusted machines,
or delete the file.
25)
rexd is enabled in foo_file!
This can allow commands to be excecuted remotely. (foo_file is usually
/etc/inetd.conf, of course.)
To fix, comment it out of foo_file (put a "#" sign in front of the line.)
25)
User foo's home directory foo_dir is mode xyz!
If a user's home directory is writable, you have the same problems as (3),
except all of the user's files are in jeopardy this time.
To fix, type:
chmod a-w foo_dir
26)
User foo: .bar is mode xyz!
In this case, ".bar" stands for one of the user's initialization files,
such as .login, .profile, .exrc, ect. If the user's file is world writable,
then anyone can modify that file, and whenever the user logs in or executes
a command (such as "vi", when referring to ".exrc"), they will execute
whatever commands the bad girl/boy wants them to.
To fix, type:
chmod a-w foo_file
27)
tftp is enabled on foo_host!
This means that people can steal your password file remotely, and run
a password cracking program on it. Bad news, unless you _really_ have great
password security, or you're running shadowpasswords. But even then, they
can still steal any world readable file on your system.
To fix, comment out (put a pound sign ("#") in the front of the line)
tftp -- usually a line in your /etc/inetd.conf file.
28)
uudecode is enabled in foofile!
If the decode mail alias is a valid mail address, people can mail to it,
and create files on your system. If the uudecode is SUID root, or something
equally insane, it can overwrite any file.
To fix, comment out the alias in your (usually /usr/lib/alias) mail alias
file.
29)
uudecode creates setuid files!
A common problem, it seems. Uudecode should not create any kind of
special files; if combined with (30), you can create hidden SUID files,
perfect for an attacker. If combined with (28), then it can be an even
worse remote attack.
30)
uudecode is suid!
Worse and worse. If this is true, then you can create files that are
owned by whomever it is SUID to.
To fix, just make it non-suid. If it has to be suid for some unknown
reason, make it SUID to user nobody, or guest, or something relatively
inoccuous, even though it won't be.
31)
ROOT owned SUID file foo_file is type: foo_type!
No root owned SUID file should be anything other than an executable
binary; however, since this test depends on the "file" command, it may get
confused, especially when using NFS, since, for example, a Sun won't recognize
a MIPS executable binary as such. In any case, examine all SUID root files
*very* carefully. And under *no* circumstance should it be a shell script.
No, no, no.
32)
User: foo SUID file is type: foo_type!
As (31), but possibly less severe.
33)
foo should be in /etc/ftpusers!
/etc/ftpusers should exist!
Problems 33-42 deal with ftp and anonymous ftp setup. All system
accounts (root, bin, etc.) should be in /etc/ftpusers, to prevent them
from using ftp.
34)
Need user foo for anonymous ftp to work!
("foo" usually means "ftp", BTW.) For anonymous ftp to work, it
needs this login to exist in the password file.
To fix, remove all but one instance of a user in each group of your
35)
Home directory for ftp doesn't exist!
ftp's home directory should not be "/"!
The home directory for ftp, found in the password file, should exist
and should *not* be "/". Make it some innocuous place on the file
system where you can keep an eye on things and dump/store stuff without
causing any damage.
36)
~ftp/etc/passwd and /etc/passwd are the same!
~ftp/etc/group and /etc/group are the same!
Login names, passwords, and such should be kept hidden from the
average anonymous ftp browser. Do *not* put your password/group
files in the ~ftp/etc directory; if you must have the actual user
names in the file, then at least star out (put an asterix ("*") in
place of the encrypted password) the password entry.
37)
File foo_file is missing (anon-ftp setup)!
Some critical file is missing, such as the password or group file.
On some versions of ftpd, this is not a problem, and on others, it
will simply not work.
38)
foo_file should be owned by foo_user or bar_user!
If key files and/or directories are owned by the wrong user, then
trouble can happen. For instance, if ftp's home directory is owned
and/or writable by ftp, then anonymous ftp users can insert .rhosts
and .forward files to cause mischief.
To fix, chown the files to root.
39)
~ftp should be mode 555!
Unless ftp's home directory is owned by root, no one should be
able to write on this directory (if root owns this, it can be
mode 755.)
40)
~ftp/.rhosts should be be empty!
There is usually no good reason to let user "ftp" trust other sites.
If any .rhosts file exists, it should be empty.
41)
Incorrect permissions on foo_file in foo_dir!
Certain files (the password file, etc.) should be set to be readable
to all, but writable by root. Other files must be executable, etc.
This flags any abberations in the setup.
42)
Anon-ftp directory foo_dir is World Writable!
If a directory is kept open for an "incoming" upload/downloads,
it is a good idea to keep the directory unreadable by all, and that it
should not hold other "trusted" software in that same directory, else
a normally "safe" program could be overwritten with a trap door,
virus, whatever.
o
User foo's home directory bar is not a directory!
A user has a non-existent or invalid login directory listed in the password
file. Sometimes these are maintenance accounts, but it is discouraged.
Examine the account to see if it should really exist.
To fix, either delete the account or put in a valid login directory.
17)
Password file, line xyz, nonnumeric group id: foo
Password file, line xyz,cops_104/docs/root.chk 600 313 12 1011 5156725241 10021 .TH ROOT.CHK 1 "Jan 4, 1991"
.UC 4
.SH NAME
root.chk \- Checks contents of root owned startup files as well as
a variety of miscellaneous potential dangers.
.SH SYNOPSIS
.B root.chk
.SH DESCRIPTION
.I root.chk
checks the paths inside root's startup files for writeability as well
as looking to see if the current directory is in root's path, for
improper umask settings (world writable), and if /bin, /etc, /.login, /.cshrc, /.rhosts, and /.profile
are all owned by root.
.SH FILES
.br
.nf
/.login
/.cshrc
/.profile
.fi
cops_104/docs/cron.chk 600 313 12 1711 5156725242 10007 .TH CRON.CHK 1 "December 31, 1989"
.UC 4
.SH NAME
cron.chk \- Checks contents of cron file(s) for potential danger.
.SH SYNOPSIS
.B cron.chk
.SH DESCRIPTION
.I cron.chk
checks pathnames and files inside the cron files for writability.
It filters out all paths or files that have a /tmp, /dev/null,
or /dev/*ty, plus everything after a ">"; e.g. if crontab is writing
to a file it doesn't care.
.PP
Since cron is run with root privileges, any file that root uses as input
inside the cron files or any program that root executes is potential danger.
World writable files can be changed by anyone to cause a root owned process
to give away unwarranted privileges.
.SH FILES
/usr/lib/cron
/usr/spool/cron/crontabs/*
.SH "SEE ALSO"
is_able(1)
.SH BUGS
Spurious messages can occur; a more stringent method (if perhaps less
careful of a check) would be to test just the 6th field, instead of
all the fields after the fifth. Also throwing away /tmp, etc. could
be a mistake.
cops_104/docs/group.chk 600 313 12 1226 5156725243 10204 .TH GROUP.CHK 1 "December 31, 1989"
.UC 4
.SH NAME
group.chk \- Checks group file(s) for inconsistencies.
.SH SYNOPSIS
.B group.chk
.SH DESCRIPTION
.I group.chk
checks the group files -- /etc/group and ypgroup if yellow pages are being
used -- for incorrect number of fields, duplicate groups, non-alphanumeric
group names, blank lines, and non-numeric group id's.
.SH FILES
.br
.nf
/etc/group
group.chk uses the process id as a temporary file name for the ypchecking.
.fi
.SH "SEE ALSO"
.br
.nf
group(5)
.fi
Awk part based on _passwd_ from _The AWK Programming Language_, page 78.
.SH BUGS
It doesn't use the exact syntax of yellow pages to check for errors.
cops_104/docs/pass_diff.chk 600 313 12 1351 5156725244 11006 .TH PASS_DIFF.CHK 1 "Jan 4, 1991"
.UC 4
.SH NAME
pass_diff.chk \- Checks passwords of accounts that have changed their passwords
since the last run.
.SH SYNOPSIS
.B pass_diff.chk
[
options
]
.SH DESCRIPTION
.I pass_diff.chk
is a front end for the
.I pass.chk
program. All it does is run a diff on the last password file checked, and
pass the accounts with changed passwords to
.I pass.chk,
along with any options it is called with. It will not run
.I pass.chk
at all if no difference was found.
.PP
.SH FILES
.br
.nf
old_passwd
passwd.diff
pass.chk
.fi
.SH "SEE ALSO"
pass.chk(1)
.SH BUGS
It calls
.I pass.chk
with the -P option in order to pass the difference from the last run. So
calling
.I pass_diff.chk
with the -P option is pointless.
cops_104/docs/user.chk 600 313 12 774 5156725245 10017 .TH USER.CHK 1 "Jan 4, 1991"
.UC 4
.SH NAME
user.chk \- Checks key files in user home directories for world writability.
.SH SYNOPSIS
.B user.chk
.SH DESCRIPTION
This checks the following "\fB.\fP" files in all of the user home directories
(it calls getpwent() to get user directories) for world writability:
.PP
.nf
profile login emacsrc
cshrc bashrc kshrc
tcshrc rhosts netrc
forward dbxinit distfile
exrc
.fi
.PP
It also looks to see if the netrc file is readable as well.
cops_104/docs/makefile 600 313 12 4142 5156725245 10063 # Simple Makefile for the COPS documentation
#
# make all -- makes everything
# make -- make a given doc
DOCS = COPS.report.ms suid.man.ms kuang.man.ms
MAN = cops.1 cron.chk.1 dev.chk.1 group.chk.1 is_able.chk.1 \
passwd.chk.1 is_able.1 home.chk.1 user.chk.1 pass.chk.1 \
root.chk.1 rc.chk.1 pass_diff.chk.1 misc.chk.1 \
is_writable.1 bug.chk.1
DOC_SOURCE = COPS.report suid.man kuang.man cops cron.chk dev.chk is_able.chk \
dir.chk file.chk group.chk passwd.chk is_able home.chk \
user.chk pass.chk root.chk rc.chk pass_diff.chk misc.chk \
is_writable bug.chk
ROFFLAGS = -ms
#
# Where the programs are....
#
NROFF=/usr/bin/nroff
RM=/bin/rm -f
# make all
all: $(DOCS) $(MAN)
clean:
$(RM) $(DOCS) $(MAN)
# 'roff out those docs
COPS.report.ms: COPS.report
$(NROFF) $(ROFFLAGS) COPS.report > COPS.report.ms
kuang.man.ms: kuang.man
$(NROFF) $(ROFFLAGS) kuang.man > kuang.man.ms
suid.man.ms: suid.man
$(NROFF) $(ROFFLAGS) suid.man > suid.man.ms
bug.chk.1: bug.chk
$(NROFF) -man bug.chk > bug.chk.1
cops.1: cops
$(NROFF) -man cops > cops.1
cron.chk.1: cron.chk
$(NROFF) -man cron.chk > cron.chk.1
dev.chk.1: dev.chk
$(NROFF) -man dev.chk > dev.chk.1
dir.chk.1: dir.chk
$(NROFF) -man dir.chk > dir.chk.1
file.chk.1: file.chk
$(NROFF) -man file.chk > file.chk.1
group.chk.1: group.chk
$(NROFF) -man group.chk > group.chk.1
passwd.chk.1: passwd.chk
$(NROFF) -man passwd.chk > passwd.chk.1
pass.chk.1: pass.chk
$(NROFF) -man pass.chk > pass.chk.1
is_able.1: is_able
$(NROFF) -man is_able > is_able.1
is_writable.1: is_writable
$(NROFF) -man is_writable > is_writable.1
is_able.chk.1: is_able.chk
$(NROFF) -man is_able.chk > is_able.chk.1
home.chk.1: home.chk
$(NROFF) -man home.chk > home.chk.1
user.chk.1: user.chk
$(NROFF) -man user.chk > user.chk.1
root.chk.1: root.chk
$(NROFF) -man root.chk > root.chk.1
rc.chk.1: rc.chk
$(NROFF) -man rc.chk > rc.chk.1
pass_diff.chk.1: pass_diff.chk
$(NROFF) -man pass_diff.chk > pass_diff.chk.1
misc.chk.1: misc.chk
$(NROFF) -man misc.chk > misc.chk.1
# the end
cops_104/docs/passwd.chk 600 313 12 1657 5156725246 10364 .TH PASSWD.CHK 1 "January 7th, 1991"
.UC 4
.SH NAME
passwd.chk \- Checks password file(s) for inconsistencies.
.SH SYNOPSIS
.B passwd.chk
.SH DESCRIPTION
.I passwd.chk
checks the password files -- /etc/passwd and yppasswd if yellow pages are being
used -- for incorrect number of fields, duplicate ids, non-alphanumeric
login names, nonnumeric user ids', users with uid = 0 and not root, blank lines,
accounts with no passwords, invalid login directories, and non-numeric
password id's. If you run C2 sun security, or have uid's of greater than
length 8 characters, you need to change "C2=TRUE" and "OVER_8=YES", on lines
46 and 50, respectively.
.SH FILES
/etc/passwd
.br
passwd.chk uses the process id as a temporary file name for the ypchecking.
.SH "SEE ALSO"
.nf
passwd(5)
.fi
Awk part based on \fIpasswd\fR from \fIThe AWK Programming Language\fR, page 78.
.SH BUGS
It doesn't use the exact syntax of yellow pages to check for errors.
cops_104/docs/misc.chk 600 313 12 1270 5156725247 10006 .TH MISC.CHK 1 "Jan 4, 1991"
.UC 4
.SH NAME
misc.chk \- Checks contents of root owned startup files as well as
a variety of miscellaneous potential dangers.
.SH SYNOPSIS
.B misc.chk
.SH DESCRIPTION
.I misc.chk
checks a variety of miscellaneous potential
security problems that really don't belong anywhere else. Currently,
it looks to see if tftp & rexecd are enabled, if anything run via
.B inetd.conf
is writeable or is a shell (/bin/sh, /bin/csh, etc.), checks if the
uudecode alias is in the mail alias file and not commented out, and
finally if uudecode is either SUID, or can produce SUID files.
.SH FILES
.br
.nf
/etc/motd
/etc/inetd.conf
/usr/lib/aliases
/bin/sh (and other shells)
.fi
SH DESCRIPTION
.I misc.chk
checks a variety of miscellaneous potential
security problems that really don't belong anywhere else. Currently,
it looks to see if tftp & rexecd are enabled, if anything run via
.B inetd.conf
is writeable or is a shell (/bin/sh, /bin/csh, etc.), checks if the
uudecode alias is in the mail alias filcops_104/docs/ftp.chk 600 313 12 5623 5156725247 7652 .TH FTP.CHK 1 "February 4, 1992"
.UC 4
.SH NAME
ftp.chk \- Checks ftp setup.
.SH SYNOPSIS
.B ftp.chk
[
\-a
]
.SH DESCRIPTION
.I ftp.chk
checks to see if you've set up (mainly anonymous)
ftp correctly. The "-a" option checks your anon-ftp setup; without that,
this script doesn't do a whole lot -- just check to see if your ftpusers
file doesn't have any root accounts in it.
.PP
There is no "right" way to set up ftp, but there are lots of wrong
ways :-)
I suggest everything be owned by either root or ftp, everthing
important owned by root only, especially if you have the "chmod" command in
your version of ftp.
Nothing should be world writable, with the exception
of a ~ftp/incoming directory or something like that (if desired). You can
change the owners via the $primary and $secondary variables (default root),
and the publically writable directory is $incoming (default ~ftp/incoming).
Do not make ~ftp/pub world writable, if you are storing data or programs for
people to use; you're inviting intruders to write all over the files and
programs, and leave all kinds of nasties...
.PP
Here are the assumptions I made for anon-ftp:
.IP \(bu 2
If your system allows the "chmod" command, you should not let _anything_
be owned by ftp. In general, it's probably a good idea to not have anything
be owned by ftp anyway.
.IP \(bu 2
User "ftp" should have a non-valid password ("*", whatever) and a invalid
shell, but a valid home directory -- this is where all the anonymous
stuff gets stashed. This checks for the passwd and valid home dir only.
I would suggest a .rhosts file of 0 size, owned by root, but that's
personal preference. This will complain if a .rhosts file exists, and
is either non-0 or non-root owned.
.IP \(bu 2
All root equivalent accounts (uid=0) with valid passwords should be in
/etc/ftpusers
.IP \(bu 2
The home dir for ftp is in /etc/passwd, should be a valid directory, and
should not be "/" (if the dir is invalid, ftpd should choke.)
.IP \(bu 2
The ~ftp/etc/{passwd|group} files should be different than their
counterparts in /etc (don't want password files available via anon-ftp.)
In addition, it seems as though the entries in ~ftp/etc/{passwd|group}
files don't do a whole lot -- some versions of ftp seem to use the
passwords in the file, some don't. If a file is created, you might see
something like:
.sp
.nf
With the entries:
drwxr-xr-x 8 cert ftp 512 Nov 7 16:56 pub/
Without:
drwxr-xr-x 8 8001 105 512 Nov 7 16:56 pub/
.fi
.sp
Some versions of ftpd allow you to leave the files off entirely; that
is the preferred method, IMHO; else, you might try putting a null file
there. Experiment... you can uncomment line 178:
.sp
crit_files=$ftpls
.sp
And the checker won't look for password and group files.
.IP \(bu 2
~ftp, ~ftp/bin, ~/ftp/etc should all be non-world-writeable, and owned
by either root or ftp. The ls command should be mode 111, the password
and group files 444.
cops_104/docs/COPS.tex 600 313 12 74371 5156725250 7700 % -*-LaTeX-*-
\documentstyle[11pt]{article}
\begin{document}
\title{\LARGE The {\sc Cops} Security Checker System\thanks{\ This paper originally
appeared in the proceedings of the Summer Usenix Conference, 1990,
Anaheim CA.} \\ \medskip {\large Purdue University Technical Report CSD-TR-993}}
\author{{\sl Daniel\ Farmer}\\
Computer\ Emergency\ Response\ Team\\
Software Engineering Institute\\
Carnegie Mellon University\\
Pittsburgh, PA 15213-3890\\
df@sei.cmu.edu\\
\and
{\sl Eugene H. Spafford} \\
Software Engineering Research Center \\
Department of Computer Sciences\\
Purdue University\\
West Lafayette, Indiana 47907-2004 \\
spaf@cs.purdue.edu}
\maketitle
\begin{abstract}
In the past several years, there have been a large number of published
works that have graphically described a wide variety of security
problems particular to {\sc Unix}. Without fail, the same problems have
been discussed over and over again, describing the problems with SUID
(set user ID) programs, improper file permissions, and bad passwords
(to name a few). There are two common characteristics to each of
these problems: first, they are usually simple to correct, if found;
second, they are fairly easy to detect.
Since almost all systems have fairly equivalent problems,
it seems appropriate to create a tool to detect potential security
problems as an aid to system administrators. This paper describes one such tool:
{\sc Cops}. (Computerized Oracle and Password System) is a
freely-available, reconfigurable set of programs and shell scripts
that enable system administrators to check for possible security holes
in their systems.
This paper briefly describes the system. Included are the
underlying design goals, the functions provided by the tool, possible
extensions, and some experiences gained from its use. We also include
information on how to obtain a copy of the initial {\sc Cops} release.
\end{abstract}
\section{Introduction}
The task of making a computer system secure is a difficult one. To
make a system secure means to protect the information from disclosure;
protecting it from alteration; preventing others from denying access
to the machine, its services, and its data; preventing degradation of
services that are present; protecting against unauthorized changes;
and protecting against unauthorized access.
To achieve all these security goals in an actual, dynamic environment
such as that presented by most {\sc Unix}
\footnote{
{\sc Unix} is a
registered trademark of AT\&T Technologies.}
systems can be a major
challenge. Practical concerns for flexibility and adaptability render
most formal security methods inapplicable, and the variability of
system configuration and system administrator training make
``cookbook'' methods too limited. Many necessary security
administration tasks can be enhanced through the use of software and
hardware mechanisms put in place to regulate and monitor access by
users and user programs. Those same mechanisms and procedures,
however, constrain the ability of users to share information and to
cooperate on projects. As such, most computer systems have a range of
options available to help secure the system. Choosing some options
allows enhanced sharing of information and resources, thus leading to
a better collaborative environment, where other settings restrict that
access and can help make the system more secure.
One of the tasks of a system and security administrator is to choose
the settings for a given system so that security is at
an appropriate level---a level that does not unduly discourage what sharing
is necessary for tasks to be accomplished, but that also
gives a reasonable assurance of safety. This often leads to problems
when a system has a very wide range of possible settings, and when
system administrators lack sufficient training and experience to
know what appropriate settings are to be applied.
Ideally, there should be some kind of assistance for system
administrators that guides them in the application of security
measures appropriate for their environment. Such a system needs to
be configurable so it provides the appropriate level of assistance
based on the perceived need for security in that environment. That
system should be
comprehensive enough so that an untrained or inexperienced
administrator is able to derive a high degree of confidence that all
appropriate features and weaknesses are identified and addressed.
Unfortunately, such a tool may also present a danger to that same
system administrator. For instance, there could be a danger if the
tool were to fall into the hands of a potential attacker. The tool could
be used to analyze the target system or to provide clues for methods
of attack. A second potential danger is that the tool can be modified
by an unfriendly agent so that the information it reports and the
actions that it takes serve not to enhance the security of the system,
but to weaken it. A third possibility is that the tool is not
comprehensive enough, or that changes in system operation are such
that the tool does not expose the security flaws made present by
those changes; the security administrator, by relying on the
tool, fails to be aware of the new dangers to his or her system.
A good example of all three dangers might be the development and use
of a tool that examines passwords to see if they can be easily guessed
by an attacker. Such a tool might consist of a fast implementation of
the password encryption algorithm used on a particular machine.
Provided with this tool would be a dictionary of words that would be
compared against user passwords. Passwords that match a word in the
dictionary would be flagged as weak passwords.
Such a tool would enable a system administrator to notify users with
weak passwords that they should choose
a password that is more difficult for an attacker to guess. However,
such a tool is a danger to the very same system it is designed to
protect should it fall into the hands of an attacker: the tool could
be used to very rapidly search through the dictionary in an attempt to
find a password that could be compromised.
A second potential danger is that an attacker with sufficient privilege
might alter the encryption algorithm or the internal workings of the
program such that it would appear to run correctly, but would fail to
match certain passwords or certain accounts. This would allow a
determined attacker to plant an account with a known simple
password that would not be detected by the program. Alternatively,
an attacker might modify such a program to send its output to not only the
administrator, but to the attacker as well.
The third problem is that the system administrator
may grow complacent by running this password tool if it continually reports
that there are no weak passwords found. The administrator may not make
any effort to enhance the quality or size of the dictionary, or to
provide other tracking or audit mechanisms to observe individuals
who may be attempting to guess passwords or break into accounts.
For all of these reasons, such a tool might be considered to lessen the
overall security of the system rather than to enhance it. That should
not prevent us from developing security tools, however. Instead, the
challenge is to build tools that enhance security without posing too
great a threat when employed by an enemy.
\section{Design and Structure}
\subsection{Design}
Although there is no reasonable way that all security
problems can be solved on any arbitrary system,
administrators and systems programmers
can be assisted by a software security tool.
{\sc Cops} is an attempt to address as many potential security
problems as possible in an efficient, portable, and above all, in a
reliable and safe way. The main goal of {\sc Cops} is one of prevention;
it tries to anticipate and eliminate security problems by
detecting problems and denying enemies an opportunity to
compromise security in the first place.
The potential security hazards that {\sc Cops} checks for were selected
from readings of a variety of security papers and books (see the
references section at the end of the paper), from
interviews with experienced system administrators, and
from reports of actual system breakins.
We applied the following important guiding principles to the
design and development of {\sc Cops}:
\begin{itemize}
\item
{\sc Cops} should be configurable so that new tools could be added or
the existing tools altered to meet the security needs of the
installation on which it is run. Since {\sc Unix} is so dynamic, it
must be possible to incorporate both new tools and methods in {\sc Cops} as the need
for them becomes apparent.
\item
{\sc Cops} should contain no
tool that attempts to fix any security problems that are discovered.
Because {\sc Cops} makes no modifications to the system, it is not required that
it be run with any particular privilege, and many of the tools
can be run with privilege less than or equal to that of a regular user.
As a result, this lessens the temptation for an intruder to modify
the code in an attempt to make surreptitious changes to the system.
\item
While {\sc Cops} should notify the administrator that there may be a
weakness, it does not describe why this is a problem or how to exploit
it. Such descriptions should be found in alternative sources that are not
embedded in the program. Thus, a determined attacker might run
the program, might be able to read the output, but be unaware of a
method to exploit anything that {\sc Cops} reports it has found.
\item
{\sc Cops} should not include any tools whose use by determined
attackers, either standalone or as part of the {\sc Cops} system, would give them
a {\em significant} advantage at finding a way to break into the system
beyond what they might already have in their possession. Thus, a
password checking tool, as was previously described, is
included, but the algorithm utilized is simply what is already present in
the system library of the target system.
\item
{\sc Cops} should consist of tools and methods that are simple to read,
understand, and to utilize. By creating the tools in such a manner, any
system administrator can read and understand the system. Not only does this
make it easier to modify the system for particular site
needs, but it allows reexamination of the code at any time to ensure
the absence of any Trojan horse or logic bomb.
\item
The system should not require a security clearance, export license,
execution of a software
license, or other restriction on use. For maximum effectiveness, the
system should be widely circulated and freely available. At the same
time, users making site-specific enhancements or including proprietary
code for local software should not be forced to disclose their
changes.
Thus, {\sc Cops} is built from new code without licensing restrictions or
onerous ``copyleft,'' and bears no restriction on distribution or use
beyond preventing it from being sold as a commercial product.
\item
{\sc Cops} should be be written to be portable to as wide a variety of
{\sc Unix} systems as possible, with little or no modification.
\end{itemize}
In order to maximize portability, flexibility, and readability, the
programs that make up {\sc Cops} are written as simple Bourne shell scripts
using common commands ({\sf awk, sed},
etc.), and when
necessary, small, heavily-commented C programs.
\subsection{Structure}
{\sc Cops} is structured as a dozen sub-programs invoked by a shell
script. That top-level script collects any output from the
subprograms and either mails the information to the local
administrator or else logs it to a file. A separate program that
checks for SUID files is usually run independently because of the
amount of time required for it to search through the filesystems. All
of the tools except the SUID checker are not meant to be run as
user root or any other privileged account.
Please note that the descriptions of the tools provided here do not
contain any detailed explanation of why the tools check what they do.
In most cases, the reason is obvious to anyone familiar with
{\sc Unix}. In those cases where it is not obvious, the bibliographic
material at the end of this paper may provide adequate explanations.
We apologize if the reasons are not explained to your satisfaction,
but we do not wish to provide detailed information for potential
system crackers who might have our system.
These are the individual the programs that comprise {\sc Cops}:
\begin{description}
\item{\bf dir.check,\ file.chk}
These two programs check a list of directories and files
(respectively) listed in a configuration file to ensure that they are
not world-writable. Typically, the files checked would include
{\it/etc/passwd, /.profile, /etc/rc},
and other key files; directories
might include {\it/, /bin, /usr/adm, /etc}
and other critical
directories.
\item{\bf pass.chk}
This program searches for and detects poor password choices. This
includes passwords identical to the login or user name, some common
words, etc. This uses the standard library crypt routine,
although the system administrator can link in a faster version, if one
is available locally.
\item{\bf group.chk,\ passwd.chk}
These two tools check the password file ({\it /etc/passwd}
and
{\sf yppasswd}
output, if applicable) and group file (
{\it /etc/group}
and
{\sf ypgroup}
output, if applicable) for a variety of problems
including blank lines, null passwords, non-standard field entries,
non-root accounts with uid=0, and other common problems.
\item{\bf cron.chk,\ rc.chk}
These programs ensure that none of the files or programs that are run
by {\sf cron}
or that are referenced in the
{\it /etc/rc*}
files are
world-writable. This protects against an attacker who might try to
modify any programs or data files that are run with root privileges at
the time of system startup. These routines extract file names from
the scripts and apply a check similar to that in {\sf file.chk}.
\item{\bf dev.chk}
checks {\it /dev/kmem, /dev/mem}, and file systems listed in
{\it /etc/fstab}
for world read/writability. This prevents would-be
attackers from getting around file permissions and reading/writing
directly from the device or system memory.
\item{\bf home.chk,\ user.chk}
These programs check each user's home directory and initialization
files ({\it .login, .cshrc, .profile}, etc) for world writability.
\item{\bf root.chk}
This checks root startup files (e.g., {\it /.login, /.profile}) for
incorrect {\sf umask}
settings and search paths containing the current
directory. This also examines {\it /etc/hosts.equiv}
for too much
accessibility, and a few miscellaneous other tests that do not fit
anywhere else.
\item{\bf suid.chk}
This program searches for changes in SUID file
status on a system. It needs to be run as user root for best results. This
is because it needs to find all SUID files on the machine, including
those that are in directories that are not generally accessible. It
uses its previous run as a reference for detecting new, deleted, or
changed SUID files.
\item{\bf kuang}
The U-Kuang expert system, originally written by Robert W. Baldwin of
MIT. This program checks to see if a given user (by default,
root) is compromisable, given that certain rules are true.
\end{description}
It is important to note once again that {\sc Cops} does not attempt to
correct any potential security hazards that it finds, but rather
reports them to the administrator. The rationale for this is that is
that even though two sites may have the same underlying hardware and
version of {\sc Unix}, it does not mean that the administrators of
those sites will have the same security concerns. What is standard
policy at one site may be an unthinkable risk at another, depending
upon the nature of the work being done, the information stored on the
computer, and the users of the system. It also means that the {\sc
Cops} system
does not need to be run as a privileged user, and it is less likely to
be booby-trapped by a vandal.
\section{Usage}
Installing and running {\sc Cops} on a system usually takes less than
an hour, depending on the administrator's experience, the speed of the
machine, and what options are used. After the initial installation,
{\sc Cops} usually takes a few minutes to run. This time is heavily
dependent on processor speed, how many password checking options are
used, and how many accounts are on the system.
The best way to use {\sc Cops} is to run it on a regular basis, via
{\sf at} or {\sf cron}. Even though it may not find any problems
immediately, the types of problems and holes it can detect could occur
at any later time.
Though {\sc Cops} is publically accessible, it is a good idea to
prevent others from accessing the programs in the toolkit, as well as
seeing any security reports generated when it has been run.
Even if you do not think of them as important, someone else might use
the information against your system. Because {\sc Cops} is
configurable, an intruder could easily change the paths and files that
it checks, thus making any security checks misleading or
worthless. You must also assume intruders will have access to the
same toolkit, and hence access to the same information on your
security problems. Any security decisions you make based on output
from {\sc Cops} should reflect this. When dealing with the security of
your system, caution is never wasted.
\section{Experience and Evaluation}
This security system is not glamorous---it cannot draw any pictures,
it consists of a handful of simple shell scripts, it does not produce
lengthy, detailed reports, and it is likely to be of little interest to
experienced security administrators who have already created their own
security toolkits. On the other hand, it has
proven to be quite effective at pointing out potential security problems
on a wide variety of systems, and should prove to be fairly valuable
to the majority of system administrators who don't have the time to create
their own system. Some administrators of major sites have informed
us that they are incorporating their old security checks into {\sc Cops} to
form a unified security system.
{\sc Cops} has been in formal release for only a few months (as of
January 1990). We have received
some feedback from sites using the system, including academic, government
and commercial sites. All of the comments about
the ease of use, the readability of the code, and the range of things
checked by the system have been quite positive. We have also,
unfortunately, had a few reports that {\sc Cops} may have been used to aid in
vandalizing systems by exposing ways to break in. In one case, the vandal
used {\sc Cops} to find a user directory with protection modes 777. In the other
case, the vandal used {\sc Cops} to find a writable system directory. Note,
however, that in both of these cases, the same vulnerability could have
easily been found without {\sc Cops}.
It is interesting to note that in the sites we have tested, and from what
limited feedback we received from people who have utilized it, over half the
systems had security problems that could compromise the root user. Whether that can
be generalized to a larger population of systems is unknown; part
of our ongoing research is to determine how vulnerable a typical site may
be. Even machines that have come straight from the vendor are not immune
from procedural security problems. Critical files and directories are often
left world-writable, and configuration files are shipped so that any other
machine hooked up to the same network can compromise the system. It
underscores this sad state of affairs when one vendor's operational manual
harshly criticizes the practice of placing the current directory in the
search path, and then in the next sentence states ``Unfortunately, this
safe path isn't the default.''
\footnote{
We will not embarrass that one vendor by citing the source of the
quote. At least they noted the fact that such a path is a hazard;
many vendors do not even provide that much warning.
}
We plan on collecting further reports from users about their experiences
with {\sc Cops}. We would encourage readers of this paper who may use it to
inform us of the performance of the system, the nature of problems indicated
by the system, and of any suggestions for enhancing the system.
\section{Future Work}
From the beginning of this project, there have been two key ideas that have
helped focus our attention and refine our design. First, there is simply no
reasonable way for us to write a security package that will perform every
task that we felt was necessary to create a truly satisfactory security
package. Second, if we waited, no one else was going to write something
like {\sc Cops} for us.
Thus, we forged ahead with the design and construction of a solid, basic
security package that could be easily expanded. We have tried to stress
certain important principles in the design of the system, so that the
expansion and evolution of {\sc Cops} will continue to provide a workable tool.
{\sc Cops} was written to be rewritten. Every part of the package is designed
to be replaced easily; every program has room for improvement. The
framework has room for many more checks. It seems
remarkable that a system as simple as this finds so many flaws
in a typical installation! Nonetheless, we have thought of a number of
possible extensions and additions to the system; these are described
in the following sections.
\subsection{Detecting known bugs}
This is a very difficult area to consider, because there are an
alarming number of sites (especially commercial ones) without the source
code that is necessary to fix bugs.
Providing checks for known bugs might make {\sc Cops} more dangerous, thus
violating our explicit design goals. At the same time, checking for known
bugs could be very useful to administrators at sites with access to source code.
If we keep in mind that {\sc Cops} is intended as a system for regular
use by an administrator, we conclude that checking for known bugs is
not appropriate, because such checks are ordinarily done once and not
repeated. Thus, a separate system for checking known bugs would be
appropriate---a a system that might be distributed in a more
controlled manner. We are currently considering different methods of
distributing such a system.
\subsection{Checksums and Signatures}
Checksums and cryptographically-generated signatures could be an
excellent method of ensuring that important files and programs have not been
compromised. {\sc Cops} could be enhanced to regenerate these checksums and
compare them against existing references. To build this into {\sc Cops} will
require some method of protecting both the checksum generator and the stored
checksums, however. It also poses the problem that system administrators
might rely on this mechanism too much and fail to do other forms of
checking, especially in situations where new software is added to the system.
\subsection{Detecting changes in important files}
There are some files that should change infrequently or not at all. The
files involved vary from site to site. {\sc Cops}
could easily be modified to check these files and notify the system administrator
of changes in contents or modification times. Again, this presents problems
with the protection of the reference standard, and with possible complacency.
\subsection{NFS and Yellow Pages}
Many new vulnerabilities exist in networked environments because of these
services. Their recent development and deployment mean that there are likely
to be more vulnerabilities and bugs present than would be found in more
mature code. As weaknesses are reported, corresponding checks should be
added to the {\sc Cops} code.
\subsection{Include UUCP security checks}
Because UUCP is very widely used, it is important to increase the
number and sophistication of the checks performed on all the different
varieties of UUCP. This includes checking the files that limit what
programs can be remotely executed, the {\it USERFILE} and {\it L.sys}
files, and the protections on directories.
\subsection{Configuration files}
There are many problems that result from improper configuration files.
These occur not only from having the files open to modification, but because
of unexpected or misunderstood interactions of options. Having rule-based
programs, similar to {\sf kuang}, which analyze these configuration files
would be an ideal way to extend {\sc Cops}.
\subsection{Checking OS-specific problems}
There are a wide variety of problems that apply only to certain flavors of
{\sc Unix}. This includes not only the placement of key files, but also
syntactical and logical differences in the way those systems operate.
Examples include such things as shadow password files, different system
logging procedures, shared memory, and network connectivity. Ideally,
the same set of tools would be used on every system, and
a configuration file or script would resolve any differences.
\section{Conclusions}
Over the last 18 months since the Internet worm, perhaps the most
strongly voiced opinion from the Internet community has been ``security
through secrecy does not work.'' Nonetheless, there is still an
appalling lack of communication about security.
System breakers and troublemakers, on the other hand, appear to encounter
little difficulty finding the time, energy, and resources necessary to break
into systems and cause trouble. It is not that they are particularly
bright; indeed, examining the log of a typical breakin shows that they
follow the same methods that are publicized in the latest
computer security mailing lists, in widely publicized works
on security, and on various clandestine bulletin boards. The
difference between them and the system administrators on the Internet
seems to be communication. It is clear that the underground community
has a well-established pipeline of information that is relatively easy for
them to tap. Many system administrators, however,
have no access to an equivalent source of information, and
are thrust into their positions with little or no
security experience. {\sc Cops} should be particularily helpful in these cases.
None of programs in {\sc Cops} cover all of the possible areas where a
system can be harmed or compromised. It can, however, aid
administrators in locating some of the potential trouble spots. {\sc
Cops} is not meant to be a panacea for all {\sc Unix} security woes,
but an administrator who examines the system and its documentation
might reduce the danger to his or her system. That is all that can
ever be expected of any security tool in a real, operational
environment.
Future work on {\sc Cops} will be done at the CERT, and work on related
tools and approaches will be done at Purdue.
People are encouraged to get a copy of {\sc Cops} and provide us with feedback
and enhancements. We expect that as time goes on, and as the
awareness of security grows, {\sc Cops} and systems like it will be
evolved through community effort. Increased communication and
awareness of the problems should not be limited to just the crackers.
\section{Acknowledgments}
Thanks go to Robert Baldwin for allowing us to include his marvelous
U-Kuang system; to Donald Knuth for inspirational work on how
not only to write but to create a software system; to Jeff Smith,
Dan Trinkle, and Steve Romig for making available their
systems and expertise during the development of {\sc Cops}; and finally, our beta testers,
without whom {\sc Cops} might never have been.
\appendix
\section*{Getting {\sc Cops}}
{\sc Cops} has been run successfully on a large number of computers, including
{\sc Unix} boxes from Sun, DEC, HP, IBM, AT\&T, Sequent, Gould, NeXT, and MIPS.
A copy of {\sc Cops} was posted to the {\it comp.sources.unix} newsgroup
and thus is available in the UUCP archives for that group, as well
as via anonymous ftp from a variety of sites ({\it uunet.uu.net {\rm and}
j.cc.purdue.edu}, for example.)
We regretfully cannot mail copies of {\sc Cops} to sites, or make tapes,
as we do not have the time or resources to handle such requests.
\section*{Biographies}
Dan Farmer is a member of the CERT (Computer Emergency Response
Team) at the Software Engineering institute at Carnegie Mellon
University. He is currently designing a tool that will
detect known bugs on a variety of {\sc Unix} systems, as well as continuing
program development and design on the {\sc Unix} system.
Gene Spafford is an assistant professor at Purdue University in the
Department of Computer Sciences. He is actively involved with
software engineering research, including testing and debugging
technology. He is also actively involved in issues of computer
security, computer crime, and professional ethics. Spaf is coauthor
of a recent book on computer viruses, is in the process of coauthoring
a book on {\sc Unix} security to be published by O'Reilly and
Associates, and is well-known for his
analysis of the Morris Internet Worm.
Besides
being a part-time netgod, Gene is involved with ACM, IEEE-CS, the
Computer Security Institute, the Research Center on Computers and
Society, and (of course) Usenix.
\section*{References}\frenchspacing
\begin{enumerate}
\item
Aho, Alfred V., Brian W. Kernighan, and Peter J. Weinberger,
{\it The
AWK Programming Language,}
Addison-Wesley Publishing Company, 1988.
\item
Authors, Various,
{\it {\sc Unix} Security Mailing List/Security Digest,}
December 1984-present.
\item
Baldwin, Robert W.,
{\it Rule Based Analysis of Computer Security,}
Massachusetts Institute of Technology, June 1987.
\item
Grampp, F. T. and R. H. Morris, ``{\sc Unix} Operating System Security,''
{\it AT\&T Bell Laboratories Technical Journal}, October 1984.
\item
Kaplilow, Sharon A. and Mikhail Cherepov, ``Quest---A Security
Auditing Tool,''
{\it AT\&T Bell Laboratories Technical Journal,}
AT\&T Bell Laboratories Technical Journal, May/June 1988.
\item
Smith, Kirk, ``Tales of the Damned,''
{\it {\sc Unix} Review,}
February 1988.
\item
Spafford, Eugene, Kathleen Heaphy and David Ferbrache,
{\it Computer
Viruses: Dealing with Electronic Vandalism and Programmed Threats,}
ADPASO, 1989.
\item
Spence, Bruce, ``spy: A {\sc Unix} File System Security Monitor,''
{\it Proceedings of the Large Installation Systems Administration III
Workshop,} Usenix Association,
September, 1988.
\item
Thompson, Ken, ``Reflections on Trusting Trust,''
{\bf 27}
(8),
{\it Communications of the ACM,}
August 1984.
\item
Wood, Patrick and Stephen Kochran,
{\it {\sc Unix} System Security,}
Hayden
Books, 1986.
\item
Wood, Patrick, ``A Loss of Innocence,''
{\it {\sc Unix} Review,}
February 1988.
\end{enumerate}
\end{document}
egenerate these checksums and
compare them against existing references. To build this into {\sc Cops} will
require some method of protecting both the checksum generator and the stored
checksums, however. It also poses the problem that system administrators
mighcops_104/docs/readme.sequent 600 313 12 317 5156725251 11203
On some sequents, I don't know why, but you'll want to have this
line uncommented out in the makefile (line 25):
SEQFLAGS = -lseq
Also, in "src/crc_check.c", you may need to uncomment lines 36-38.
cops_104/docs/is_writable 600 313 12 1231 5156725252 10604 .TH IS_WRITABLE 1 "Feb 3, 1992"
.UC 4
.SH NAME
is_writable \- Check for writability of a file.
.SH SYNOPSIS
.B is_writable
[
\-g
]
file
.SH DESCRIPTION
.I is_writable
can check a file to see if a file is either writable by group or by all,
returning either 0 if it is writable, or non-zero if it is not.
.I is_writable
also checks the parent directories, if a complete path is
given, for writeability.
Options are:
.TP
.B \-g
Check for group writability as well as world.
.SH BUGS
The Andrew File System, or Mach, or the combination of the two, apparently
plays games with stat(), the way I get the file info, so it can report things
as writable, when they aren't.
cops_104/docs/readme.C2 755 313 12 50157 5156725254 10050
A letter I got with source... I've never had the time to add this stuff
in officially. Maybe next release? Also, to crack C2 passwords on a
Sun, compile pass.c with the C2 defined (e.g. -DC2), and run the cracker
as root.
========================================================================
Dan,
Please find enclose four (4) files: passwd.chk, passwd.file.chk, group.chk,
and group.file.chk. These are the files to allow checking of the Sun C2
security variations of SunOS. They will perform checking of the yellow pages
version if so selected by the TEST_YP variable being TRUE in the passwd.chk
and group.chk files. The testing of the SUN C2 security is performed by setting
the SUN_SECURITY variable to TRUE in the passwd.chk and group.chk files.
Pete Troxell
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 01/08/1991 02:50 UTC by df@death.cert.sei.cmu.edu
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 1609 -rwx------ group.chk
# 6191 -rwx------ group.file.chk
# 1650 -rwx------ passwd.chk
# 7715 -rwx------ passwd.file.chk
#
# ============= group.chk ==============
if test -f 'group.chk' -a X"$1" != X"-c"; then
echo 'x - skipping group.chk (File already exists)'
else
echo 'x - extracting group.chk (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'group.chk' &&
#!/bin/sh
#
# group.chk
#
# Check group file -- /etc/group -- for incorrect number of fields,
# duplicate groups, non-alphanumeric group names, and non-numeric group
# id's.
#
ECHO=/bin/echo
RM=/bin/rm
TEST=/bin/test
YPCAT=/usr/bin/ypcat
X
#
# Enhanced Security Features addes by Pete Troxell:
#
# Used for Sun C2 security group file. FALSE (default) will flag
# valid C2 group syntax as an error, TRUE attempts to validate it. When
# using this option the script must be executed as root or su since the file
# /etc/security/group.adjunct is read protected from everybody except root.
#
SUN_SECURITY=FALSE
X
#
# Enable/Disable testing of the Yellow Pages group file(s)
#
TEST_YP=FALSE
X
#
# Important files:
#
etc_group=/etc/group
etc_secure_group=/etc/security/group.adjunct
yp_group=./grp$$
yp_secure_group=./sgrp$$
X
yp=false
yp_secure=false
X
#
# Testing $yp_group for potential problems....
#
if $TEST -f $YPCAT -a $TEST_YP = "TRUE"
X then
if $TEST -s $YPCAT
X then
X $YPCAT group > $yp_group 2>/dev/null
X if $TEST $? -eq 0
X then
X yp=true
X fi
X if $TEST $yp = "true" -a $SUN_SECFURITY = "TRUE"
X then
X $YPCAT -t group.adjunct.byname > $yp_secure_group 2>/dev/null
X if $TEST $? -eq 0
X then
X yp_secure=true
X fi
X fi
fi
fi
X
#
# Test the system group file
#
group.file.chk $etc_group $etc_secure_group $SUN_SECURITY
X
#
# Test yellow pages password file
#
if $TEST "$yp" = "true"
X then
X $ECHO
X $ECHO "***** Testing the Yellow Pages password file(s) ******"
X $ECHO
X group.file.chk $yp_group $yp_secure_group $SUN_SECURITY
X fi
X
#
# Clean up after ourselfs
#
$RM -f $yp_group
$RM -f $yp_secure_group
# end
SHAR_EOF
chmod 0700 group.chk ||
echo 'restore of group.chk failed'
Wc_c="`wc -c < 'group.chk'`"
test 1609 -eq "$Wc_c" ||
echo 'group.chk: original size 1609, current size' "$Wc_c"
fi
# ============= group.file.chk ==============
if test -f 'group.file.chk' -a X"$1" != X"-c"; then
echo 'x - skipping group.file.chk (File already exists)'
else
echo 'x - extracting group.file.chk (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'group.file.chk' &&
#!/bin/sh
#
# group.file.chk
#
# Awk part based on _passwd_ from _The AWK Programming Language_, page 78
#
# Mechanism: Group.check uses awk to ensure that each line of the group
# has 4 fields, as well as examining each line for any duplicate groups or
# any duplicate user id's in a given group by using "sort -u" to ferret
# out any duplications. It also checks to make sure that the password
# field (the second one) is a "*", meaning the group has no password (a
# group password is usually not necessary because each member listed on
# the line has all the privilages that the group has.) All results are
# echoed to standard output. Finally it ensures that the group names
# are alphanumeric, that the group id's are numeric, and that there are
# no blank lines. For yellow pages groups, it does the same checking,
# but in order to get a listing of all members of the groups, it does a
# "ypcat group > ./$$" and uses that temporary file for a groupfile.
# It removes the tmp file after using it, of course.
# The /etc/group file has a very specific format, making the task
# fairly simple. Normally it has lines with 4 fields, each field
# separated by a colon (:). The first field is the group name, the second
# field is the encrypted password (an asterix (*) means the group has no
# password, otherwise the first two characters are the salt), the third
# field is the group id number, and the fourth field is a list of user
# ids in the group. If a line begins with a plus sign (+), it is a yellow
# pages entry. See group(5) for more information.
# The SUN /etc/security/group.adjunct file also has a very specific
# format, makeing the check task simple. Each entry has 2 fields separated
# by a colon (:). THe first field is the user name which matches the user
# name contained in the /etc/group file. The second field is the encrypted
# password (an asterix (*) means the group has no password, otherwise the
# first two characters are the salt). The password contained in the
# /etc/group file is comprised of the #$user_id where the user_id matches
# the entry of the first field in both group files.
#
X
#
# Parameters
#
group_file=$1
group_adjunct_file=$2
SUN_SECURITY=$3
X
#
# Utilities
#
AWK=/bin/awk
DIFF=/usr/bin/diff
ECHO=/bin/echo
JOIN=/usr/bin/join
RM=/bin/rm
SORT=/usr/bin/sort
TEST=/bin/test
UNIQ=/usr/bin/uniq
X
#
# Important files:
#
join_group_1=./grp$$.1.join
join_group_2=./grp$$.2.join
sort_group=./grp$$.sort
sort_secure_group=./sgrp$$.sort
X
#
# Testing the group file for problems
#
result=`$AWK -F: '{print $1}' $group_file | $SORT |$UNIQ -d`
if $TEST "$result"
X then
X $ECHO "Warning! Duplicate gid(s) found in group file:"
X for USER in $result
X do
X $ECHO " $USER"
X done
fi
X
#
# First line is for a yellow pages entry in the group file.
# It really should check for correct yellow pages syntax....
#
$AWK 'BEGIN {FS = ":" } {
X if (substr($1,1,1) != "+") { \
X if ($0 ~ /^[ ]*$/) { printf("Warning! Group file, line %d, is blank\n", NR) } else {
X if (NF != 4) { printf("Warning! Group file, line %d, does not have 4 fields: \n\t%s\n", NR, $0) } \
X if ($1 !~ /[A-Za-z0-9]/) {
X printf("Warning! Group file, line %d, nonalphanumeric user id: \n\t%s\n", NR, $0) } \
X if ($2 != "" && $2 != "*") {
X if ("'$SUN_SECURITY'" != "TRUE")
X printf("Warning! Group file, line %d, has password: \n\t%s\n", NR, $0)
X else {
X if ("#$"$1 != $2)
X printf("Warning! Group file, line %d, invalid password field for SUN C2 Security: \n\t%s\n", NR, $0) } \
X } \
X if ($3 !~ /[0-9]/) {
X printf("Warning! Group file, line %d, nonnumeric group id: \n\t%s\n", NR, $0) \
X }}}} ' $group_file
X
#
# Ignore all groups with less than two members.
#
awk -F: '
X split($4, users, ",") > 1 {
X ct = 0
X for (i in users) {
X curuser = users[i]
X for (j in users) {
X if (j > i && curuser == users[j]) {
X if (ct++ == 0) print "Warning! Group "$1" has duplicate user(s):"
X print curuser
X }
X }
X }
X }
X ' $group_file
X
#
# Perform checks on the security enhanced version of SUNOS
#
if $TEST $SUN_SECURITY = "TRUE"
X then
X result=`$AWK -F: '{print $1}' $group_adjunct_file | $SORT -t: | $UNIQ -d`
X if $TEST "$result"
X then
X $ECHO
X $ECHO "Warning! Duplicate uid(s) found in group adjunct file:"
X for USER in $result
X do
X $ECHO " $USER"
X done
X fi
X #
X # Check that for each entry in the group file that there is a matching
X # entry in the group.adjunct file.
X #
X $SORT -t: -o $sort_group $group_file
X $SORT -t: -o $sort_secure_group $group_adjunct_file
X $JOIN -t: $sort_group $sort_secure_group > $join_group_1
X $JOIN -t: -a1 $sort_group $sort_secure_group > $join_group_2
X result=`$DIFF $join_group_1 $join_group_2`
X if $TEST "$result"
X then
X $ECHO
X $ECHO "Warning! Matching record(s) in group adjunct file not found for"
X $ECHO "these records in group file:"
X PREV=$$
X for USER in $result
X do
X if $TEST $PREV = ">"
X then
X $ECHO " $USER"
X fi
X PREV=$USER
X done
X fi
X #
X # Check that for each entry in the group.adjunct file that there is a
X # matching entry in the group file.
X #
X $RM -f $join_group_2
X $JOIN -t: -a2 $sort_group $sort_secure_group > $join_group_2
X result=`$DIFF $join_group_1 $join_group_2`
X if $TEST "$result"
X then
X $ECHO
X $ECHO "Warning! Matching record(s) in group file not found for"
X $ECHO "these records in group adjunct file"
X PREV=$$
X for USER in $result
X do
X if $TEST $PREV = ">"
X then
X $ECHO " $USER"
X fi
X PREV=$USER
X done
X fi
X #
X # Test the fields in the group.adjunct file for validity
X #
X $AWK 'BEGIN {FS = ":" } \
X {if (substr($1,1,1) != "+") { \
X if ($0 ~ /^[ ]*$/) { printf("\nWarning! Group adjunct file, line %d, is blank\n", NR) } else {
X if (NF != 2) {
X printf("\nWarning! Group adjunct file, line %d, does not have 2 fields: \n\t%s\n", NR, $0) } \
X if ($1 !~ /[A-Za-z0-9]/) {
X printf("\nWarning! Group adjunct file, line %d, nonalphanumeric login: \n\t%s\n", NR, $0) } \
X if ($2 != "" && $2 != "*") {
X printf("\nWarning! Group adjunct file, line %d, has password: \n\t%s\n", NR, $0) } \
X }}}' $group_adjunct_file
fi
X
#
# Clean up after ourself
#
$RM -f $join_group_1
$RM -f $join_group_2
$RM -f $sort_group
$RM -f $sort_secure_group
# end
SHAR_EOF
chmod 0700 group.file.chk ||
echo 'restore of group.file.chk failed'
Wc_c="`wc -c < 'group.file.chk'`"
test 6191 -eq "$Wc_c" ||
echo 'group.file.chk: original size 6191, current size' "$Wc_c"
fi
# ============= passwd.chk ==============
if test -f 'passwd.chk' -a X"$1" != X"-c"; then
echo 'x - skipping passwd.chk (File already exists)'
else
echo 'x - extracting passwd.chk (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'passwd.chk' &&
#!/bin/sh
#
# passwd.chk
#
# Check passsword file -- /etc/passswd -- for incorrect number of fields,
# duplicate uid's, non-alphanumeric uids, and non-numeric group id's.
#
#
ECHO=/bin/echo
RM=/bin/rm
TEST=/bin/test
YPCAT=/usr/bin/ypcat
X
#
# Enhanced Security Features added by Pete Troxell:
#
# Used for Sun C2 security password adjunct file. FALSE (default) will flag
# valid SUN C2 passwd syntax as an error, TRUE attempts to validate it. When
# using this option, the script must be executed as root or su since the file
# /etc/security/passwd.adjunct is read protected from everybody except root.
#
SUN_SECURITY=FALSE
X
#
# Enable/Disable testing of the Yellow Pages password file(s)
#
TEST_YP=FALSE
X
#
# Important files:
#
etc_passwd=/etc/passwd
etc_secure_passwd=/etc/security/passwd.adjunct
yp_passwd=./pwd$$
yp_secure_passwd=./spwd$$
X
yp=false
yp_secure=false
X
#
# Testing $yp_passwd for potential problems....
#
if $TEST -f $YPCAT -a $TEST_YP = "TRUE"
X then
if $TEST -s $YPCAT
X then
X $YPCAT passwd > $yp_passwd 2>/dev/null
X if $TEST $? -eq 0
X then
X yp=true
X fi
X if $TEST $yp = "true" -a $SUN_SECURITY = "TRUE"
X then
X $YPCAT -t passwd.adjunct.byname > $yp_secure_passwd 2>/dev/null
X if $TEST $? -eq 0
X then
X yp_secure=true
X fi
X fi
fi
fi
X
#
# Test the system password file
#
passwd.file.chk $etc_passwd $etc_secure_passwd $SUN_SECURITY
X
#
# Test yellow pages password file
#
if $TEST "$yp" = "true"
X then
X $ECHO
X $ECHO "***** Testing the Yellow Pages password file(s) *****"
X $ECHO
X passwd.file.chk $yp_passwd $yp_secure_passwd $SUN_SECURITY
X fi
X
#
# Clean up after ourselfs
#
$RM -f $yp_passwd
$RM -f $yp_secure_passwd
# end
SHAR_EOF
chmod 0700 passwd.chk ||
echo 'restore of passwd.chk failed'
Wc_c="`wc -c < 'passwd.chk'`"
test 1650 -eq "$Wc_c" ||
echo 'passwd.chk: original size 1650, current size' "$Wc_c"
fi
# ============= passwd.file.chk ==============
if test -f 'passwd.file.chk' -a X"$1" != X"-c"; then
echo 'x - skipping passwd.file.chk (File already exists)'
else
echo 'x - extracting passwd.file.chk (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'passwd.file.chk' &&
#!/bin/sh
#
# passwd.file.chk
#
# Check passsword file -- /etc/passswd -- for incorrect number of fields,
# duplicate uid's, non-alphanumeric uids, and non-numeric group id's.
#
# Awk part from _The AWK Programming Language_, page 78
#
# Mechanism: Passwd.check uses awk to ensure that each line of the file
# has 7 fields, as well as examining the file for any duplicate users
# by using "sort -u". It also checks to make sure that the password
# field (the second one) is either a "*", meaning the group has no password,
# or a non-null field (which would mean that the account has a null
# password.) It then checks to ensure that all uids are alphanumeric,
# and that all user id numbers are indeed numeric. For yellow pages
# passwords, it does the same checking, but in order to get a listing of
# all members of the password file, it does a "ypcat passwd > ./$$" and
# uses that temporary file for a passfile. It removes the tmp file after
# using it, of course.
# The /etc/passwd file has a very specific format, making the task
# fairly simple. Normally it has lines with 7 fields, each field
# separated by a colon (:). The first field is the user id, the second
# field is the encrypted password (an asterix (*) means the user id has no
# password, otherwise the first two characters are the salt), the third
# field is the user id number, the fourth field is the group id number,
# the fifth field is the GECOS field (basically holds miscellaneous
# information, varying from site to site), the sixth field is the home
# directory of the user, and lastly the seventh field is the login shell
# of the user. No blank lines should be present.
# The SUN /etc/security/passwd.adjunct file also has a very specific
# format, making the check task simple. Each entry has 7 fields, each field
# separated by a colon (:). The first field is the user name which matches
# the user name contained in the /etc/passwd file. The second field is the
# encrypted password (an asterix (*) means the user login is disabled,
# otherwise the first two characters are the salt). The password contained
# in the /etc/passwd file is comprised of ##user_id where the user_id
# matches the entry of the first field in both password files. The third
# through fifth specify the minimum, maximum, and default security labels
# for the user. The sixth and seventh fields specify which auditing flags
# should be always or never monitored.
# If a line begins with a plus sign (+), it is a yellow pages entry.
# See passwd(5) for more information, if this applies to your site.
#
X
#
# Parameters
#
passwd_file=$1
passwd_adjunct_file=$2
SUN_SECURITY=$3
X
#
# Utilities
#
AWK=/bin/awk
DIFF=/usr/bin/diff
ECHO=/bin/echo
JOIN=/usr/bin/join
RM=/bin/rm
SORT=/usr/bin/sort
TEST=/bin/test
UNIQ=/usr/bin/uniq
X
#
# Important files:
#
join_passwd_1=./pwd$$.1.join
join_passwd_2=./pwd$$.2.join
sort_passwd=./pwd$$.sort
sort_secure_passwd=./spwd$$.sort
X
#
# Testing the passwd file for problems
#
result=`$AWK -F: '{print $1}' $passwd_file | $SORT -t: | $UNIQ -d`
if $TEST "$result"
X then
X $ECHO
X $ECHO "Warning! Duplicate uid(s) found in password file:"
X for USER in $result
X do
X $ECHO " $USER"
X done
fi
X
#
# First line is for a yellow pages entry in the password file.
# It really should check for correct yellow pages syntax....
#
$AWK 'BEGIN {FS = ":" } \
X {if (substr($1,1,1) != "+") { \
X if ($0 ~ /^[ ]*$/) { printf("\nWarning! Password file, line %d, is blank\n", NR) } else {
X if (NF != 7) {
X printf("\nWarning! Password file, line %d, does not have 7 fields: \n\t%s\n", NR, $0) } \
X if ($1 !~ /[A-Za-z0-9]/) {
X printf("\nWarning! Password file, line %d, nonalphanumeric login: \n\t%s\n", NR, $0) } \
X if ($2 == "") {
X printf("\nWarning! Password file, line %d, no password: \n\t%s\n", NR, $0) } \
X if ("'$SUN_SECURITY'" == "TRUE" && "##"$1 != $2) {
X printf("\nWarning! Password file, line %d, invalid password field for SUN C2 Security: \n\t%s\n", NR, $0) } \
X if ($3 !~ /[0-9]/) {
X printf("\nWarning! Password file, line %d, nonnumeric user id: \n\t%s\n", NR, $0) } \
X if ($3 == "0" && $1 != "root") {
X printf("\nWarning! Password file, line %d, user %s has uid = 0 and is not root\n\t%s\n", NR, $1, $0) } \
X if ($4 !~ /[0-9]/) {
X printf("\nWarning! Password file, line %d, nonnumeric group id: \n\t%s\n", NR, $0) } \
X if ($6 !~ /^\//) {
X printf("\nWarning! Password file, line %d, invalid login directory: \n\t%s\n", NR, $0) } \
X }}}' $passwd_file
X
#
# Perform checks on the security enhanced version of SUNOS
#
if $TEST $SUN_SECURITY = "TRUE"
X then
X result=`$AWK -F: '{print $1}' $passwd_adjunct_file | $SORT -t: | $UNIQ -d`
X if $TEST "$result"
X then
X $ECHO
X $ECHO "Warning! Duplicate uid(s) found in password adjunct file:"
X for USER in $result
X do
X $ECHO " $USER"
X done
X fi
X #
X # Check that for each entry in the passwd file that there is a matching
X # entry in the passwd.adjunct file.
X #
X $SORT -t: -o $sort_passwd $passwd_file
X $SORT -t: -o $sort_secure_passwd $passwd_adjunct_file
X $JOIN -t: $sort_passwd $sort_secure_passwd > $join_passwd_1
X $JOIN -t: -a1 $sort_passwd $sort_secure_passwd > $join_passwd_2
X result=`$DIFF $join_passwd_1 $join_passwd_2`
X if $TEST "$result"
X then
X $ECHO
X $ECHO "Warning! Matching record(s) in password adjunct file not found for"
X $ECHO "these records in password file:"
X PREV=$$
X for USER in $result
X do
X if $TEST $PREV = ">"
X then
X $ECHO " $USER"
X fi
X PREV=$USER
X done
X fi
X #
X # Check that for each entry in the passwd.adjunct file that there is a
X # matching entry in the passwd file.
X #
X $RM -f $join_passwd_2
X $JOIN -t: -a2 $sort_passwd $sort_secure_passwd > $join_passwd_2
X result=`$DIFF $join_passwd_1 $join_passwd_2`
X if $TEST "$result"
X then
X $ECHO
X $ECHO "Warning! Matching record(s) in password file not found for"
X $ECHO "these records in password adjunct file"
X PREV=$$
X for USER in $result
X do
X if $TEST $PREV = ">"
X then
X $ECHO " $USER"
X fi
X PREV=$USER
X done
X fi
X #
X # Test the fields in the passwd.adjunct file for validity
X #
X $AWK 'BEGIN {FS = ":" } \
X {if (substr($1,1,1) != "+") { \
X if ($0 ~ /^[ ]*$/) { printf("\nWarning! Password adjunct file, line %d, is blank\n", NR) } else {
X if (NF != 7) {
X printf("\nWarning! Password adjunct file, line %d, does not have 7 fields: \n\t%s\n", NR, $0) } \
X if ($1 !~ /[A-Za-z0-9]/) {
X printf("\nWarning! Password adjunct file, line %d, nonalphanumeric login: \n\t%s\n", NR, $0) } \
X if ($2 == "") {
X printf("\nWarning! Password adjunct file, line %d, no password: \n\t%s\n", NR, $0) } \
X #
X # Fields 3-5 are ignored since they deal with labels which are
X # currently unused on the SUN (perhaps a future B-level??)
X #
X # Fields 6+7 contain audit flags for the user and are selected
X # from the following: dr, dw, dc, da, lo, ad, p0, p1, and all.
X # More than 1 flag can be selected by separating flags with a
X # comma (,).
X #
X if ($6 != "") {
X j=1
X len=length($6)
X for (i=1; i<=len; i++) {
X if ((substr($6,i,1) != ",") && (i < len))
X continue
X if (i == len)
X token=substr($6,j,i-j+1)
X else
X token=substr($6,j,i-j)
X j=i+1
X if (token == "dr") continue
X if (token == "dw") continue
X if (token == "dc") continue
X if (token == "da") continue
X if (token == "lo") continue
X if (token == "ad") continue
X if (token == "p0") continue
X if (token == "p1") continue
X if (token == "all") continue
X printf("\nWarning! Password adjunct file, line %d, invalid audit flag: %s\n\t%s\n", NR, token, $0) } \
X }
X }}}' $passwd_adjunct_file
fi
X
#
# Clean up after ourself
#
$RM -f $join_passwd_1
$RM -f $join_passwd_2
$RM -f $sort_passwd
$RM -f $sort_secure_passwd
# end
SHAR_EOF
chmod 0700 passwd.file.chk ||
echo 'restore of passwd.file.chk failed'
Wc_c="`wc -c < 'passwd.file.chk'`"
test 7715 -eq "$Wc_c" ||
echo 'passwd.file.chk: original size 7715, current size' "$Wc_c"
fi
exit 0
chk (File already exists)'
else
echo 'x - extracting passwd.file.chk (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'passwd.file.chk' &&
#!/bin/sh
#
# passwd.file.chk
#
# Check passsword file -- /etc/passswd -- for incorrect number of fields,
# duplicate uid's, non-alphanumeric uids, and non-numeric group id's.
#
# Awk part from _The AWK Programming Language_, page 78
#
# Mechanism: Passwd.check uses awcops_104/docs/readme.apollo 755 313 12 3330 5156725255 11042
Try setting the $OVER_8 variable (line 50) in "passwd.chk" to "YES",
if you get warnings about having extra long uid's.
This little script can be used to generate a better password file for
the password cracker, if you use those funky more-than-one-field in field
one of the password file; e.g., if you have something that looks like:
root.foo.bar:xxxxxxxxxxxxx:0:0:Mr. Fu Bear:/:/bin/sh
This will change it to:
root:xxxxxxxxxxxxx:0:0:foo bar Mr. Fu Bear:/:/bin/sh
So that you can use the extra fields as gcos information for password
cracking. You can substitute the normal password cracking stuff in "cops"
("pass.chk") with something like (assuming you call this "apollo.sh"):
apollo.sh > ./apollo.pw.$$
pass.chk -P ./apollo.pw.$$
rm -f ./apollo.pw.$$
In addition, you can add these 2 lines to the "passwd.chk" shell script
(right before the start of the awk on line 82 would be fine):
$AWK -F: '{print $1}' $etc_passwd | $AWK -F. '{if (NF > 3)
printf("Warning! Password file, line %d, has %d sub-fields in the user field: \n\t%s\n", NR, NF, $0) }'
And if you're running YP (is that possible, with all of that? :-)
You can add these 2 lines before line 119:
$AWK -F: '{print $1}' $yp_passwd | $AWK -F. '{if (NF > 3)
printf("Warning! YPassword file, line %d, has %d sub-fields in the user field: \n\t%s\n", NR, NF, $0) }'
:
#
# apollo.pw
#
AWK=/bin/awk
# Quote from the man page (passwd):
# On DOMAIN systems, passwords are kept in the registry files (/registry/*).
#
# Important files:
etc_passwd=/etc/passwd
$AWK -F: '{split($1,temp,"."); \
$1=temp[1]; \
for (i in temp) {
if (i!=1) \
$5 = $5" "temp[i]; \
} \
for (j=1;j<=NF;j++)
printf("%s:",$j); \
printf("\n") \
}' $etc_passwd
# end
cops_104/docs/readme.ibm 600 313 12 502 5156725255 10266
Make sure you uncomment out line 92 in dev.chk:
# On an IBM/AIX box, you can try something like:
# all_devs=`$GREP 'dev.*=' /etc/filesystems | $AWK '{print $NF}'`
So that COPS can read the right devices. Also, read the "readme.shadow"
file for shadow-password info, and how to crack passwords, etc, on this
beast.
cops_104/docs/readme.shadow 755 313 12 5307 5156725256 11050
Part of a conversation I had with a guy about cracking shadow passords;
at the end of this is a script that should work with SVR3.2; I'm not
sure about the rest, but minor changes should make it work on
just about anything (for instance, I think on my sun, the variable
$num_fields should be changed to 15 (or you could compile pass.c with
the C2 flag)). Let me know if you can't get it to work, and I'll
*make* it work :-) In any case, you'll need to run as root to get the
passwords for cracking.
>On system V3.2, both AT&T, SCO, and us (Interactive) use the following format
> /etc/passwd looks pretty much normal;
> adm:x:4:4:0000-Admin(0000):/usr/adm:
[...]
> except that the passwd field always contains an "x".
> Then, the etc/shadow file, which is owned by root and perms 400 looks
> like;
[...]
> sally:e4T6g5HbjOnck:7449:0:7000
[...]
> The first field is the account name, the second field is the excrypted
> passwd string, and the rest is password aging garbage.
> Ignore the password fields above containing "LOCKED". I do that by
> hand to secure an account, since the output of crypt will never match it.
Try this on for size:
========== shadow.stuff ================
#!/bin/sh
#
# Usage: shadow.stuff [shadow_password_file]
#
# Extracts the correct info from shadow pass to use for processing with
# pass.chk and passwd.chk.
#
# (written by me, modified by John F Haugh II, remodified by me. Hope
# it still works :-))
#
if test -f "$1" ; then
shadow=$1
else
if test -f "/etc/shadow" ; then
shadow=/etc/shadow
else
echo "Can't find shadow password file..."
exit 1
fi
fi
# This is 15, I think, for a sun? Others seem to want 13
num_fields=13
passwd=/etc/passwd
foo_pass="./shadow.tmp.$$"
ptmp="./pfile.tmp.$$"
stmp="./sfile.tmp.$$"
sed -e 's/^/p:/' $passwd | sort > $ptmp
sed -e 's/^/s:/' $shadow | sort > $stmp
cat ./pfile.tmp.$$ ./sfile.tmp.$$ | \
sort -t':' +1 -2 +0r -1 | \
sed -e 's/^[sp]://' > $foo_pass
awk -F: '{parray[$1] = $0":"parray[$1]} END { \
for (line in parray) { \
nf=split(parray[line], pline, ":"); \
if (nf == '"$num_fields"') {
print pline[1]":"pline[9]":"pline[3]":"pline[4]":" \
pline[5]":"pline[6]":"pline[7]; \
} \
} \
}' $foo_pass
rm -f $ptmp $stmp $foo_pass
==========================================
Ok, the way you use this is just to type "shadow.stuff > tempfile";
this will create a file, "tempfile" (or whatever), that *should*
be the equivalent to a normal password file. Of course, you'll have
to run this as root so that you can read the shadow password file.
This should work, but no blame if it doesn't, please :-) Just let
me know if it does or not; I can put it in the normal distribution,
if so.
Hope this helps -- 'luck!
-- dan
stuff [shadow_password_file]
#
# Extracts the correct info from shadow pass to use for processing with
# pass.chk and passwd.chk.
#
# (written by me, modified by John F Haugh II, remodified by me. Hope
# it still works :-))
#
if test -f "$1" ; then
shadow=$1
else
if test -f "/etc/shadow" ; then
shadow=/etcops_104/docs/readme.svr4 600 313 12 146 5156725257 10423
In bug.chk, you'll need to change this line (29) to "no":
# Do you decend from 4.3 BSD?
bsd43=yes
cops_104/docs/readme.xenix 755 313 12 1320 5156725257 10706
Uncomment the "BRAINDEADFLAGS=-lcrypt" in the makefile, and put the line:
extern char *crypt();
Right after the #include lines in "pass.c". This apparently came from
the makers of Xenix, about the availability of crypt(3):
========================
Subject: crypt in Xenix
Due to the export restrictions on CRYPT, we do not ship it with the
standard product. We do ship it as an SLS: the relevant numbers are
lng190 (for shipment inside the U.S. only) and lng225, which can be
shipped outside the U.S..
========================
Make the following change in dev.chk:
line 39:
> mtab=/etc/fstab
To:
< mtab=/etc/checklist
(note to myself:
Need to change something... checklist has has one fs per line...)
cops_104/docs/readme.yp 755 313 12 1117 5156725260 10201
There are a couple of things to keep in mind if you're using yellow
pages/NIS. Automatic checks are made in the passwd.chk, group.chk, suid.chk,
and ftp.chk. However, if you want to crack passwords from that database,
you need to do one of three things:
1) If you're using "pass_diff.chk" to check only changed passwords (on
line 108 of "cops"), change the flag on line 33 in "pass_diff.chk" from
"NO" to "YES"
2) If you're not running "pass_diff.chk", replace "pass.chk" with
"yp_pass.chk" on line 109 of "cops".
3) Create a password file with ypcat and run "pass.chk -P file".
cops_104/docs/bug.chk 700 313 12 5134 5156725261 7630 .TH CARP 1 "February 16, 1992"
.UC 4
.SH NAME
bug.chk \- bug date testing tool
.SH SYNOPSIS
.B bug.chk
[
architecture
]
.SH DESCRIPTION
.I bug.chk
uses publically available (available via anonymous ftp from
cert.sei.cmu.edu) data to determine if a security bug is present. The
way it does this is by checking the modification time of the program in
question against the cert advisory date (or patch date, if available),
and, if it is older than that, it flags it as a potential
bug/vulnerability (the awk program "bug_cmp" is used to check dates).
It attempts to determine the machine type run on
automatically, but, failing that, can be run with the machine type
as an argument.
.PP
There are numerous problems with this approach! One, no actual check
is done; whether or not the bug actually does exist has nothing to
do with the date. Also, if someone changes, updates, or even touches
the file, then this is pretty worthless. A far better check would
be to either try to exploit the bug or to have lists of all good and
bad crc's for the files in questions, and just test against it. Still,
this seems to be a good compromise for the time being. However,
updates should be made for each new CERT advisory as they are made
public.
.PP
Right now, it either uses your argument as an architecture type, or
tries to figure out what kind of platform you're running
on (see the program "platform"), and then looks at the bugs known
for your host in a file named "bug.chk.architecture_type".
.PP
Bugs bug.chk currently tries to look at:
.br
.IP
Morris Worm threats: sendmail, login, fingerd, and ftpd.
.IP
Generic BSD problem: rdist.
.IP
IBM/AIX tftpd.
.IP
Apollo -- /usr/apollo/bin/crp
.IP
Ultrix/DEC -- chroot, /usr/bin/mail.
.IP
NeXT -- restore0.9, npd, BuildDisk, npd, and perms on /private/etc.
.IP
SGI -- /usr/sbin/Mail, /usr/sbin/fmt.
.IP
Sun -- sendmail, restore, TIOCCONS, sel_svc, lpd, bin_mail,
telnetd/rlogind, makeinstall/winstall, mountd,
divide/multiply by 0, nfs, loadmodule.
.IP
SVR4 -- /bin/login, /usr/etc/rexecd.
.br
.PP
Note that many of the bugs that Sun has reported either have
not been publically reported and fixed by other vendors, even though
they usually exist on their hosts. I don't think that Sun's
OS is designed any worse than any other OS; instead, I think
that Sun is more open in reporting them to their constituents
and CERT, as well as having the largest user base to beat on
their boxes.
.SH "SEE ALSO"
CERT advisories, available via anon-ftp from cert.sei.cmu.edu,
or by calling (412) 268-7090. Perusing the source code might
be beneficial as well.
.SH BUGS
Easily fooled, doesn't actually do anything :-)
atically, but, failing that, can be run with the machine type
as an argument.
.PP
There are numerous problems with this approach! One, no actual check
is done; whether or not the bug actually does exist has nothing to
do with the date. Also, if someone changes, updates, or even touches
the file, then this is pretty worthless. A far better check would
be to either try to exploit the bug or to have lists of all goodcops_104/docs/readme.filter 600 313 12 12046 5156725261 11047
A quick primer on "cops_filter"
"cops_filter" is a mechanism for eliminating warning messages in
the final COPS report that you deem spurious. It's a simple awk
program that looks at a list of regular expressions and prunes
out any that match. As simple as it is, however, it is an extremely
dangerous program -- a slip of the ol' regular expression and bam --
you don't get notified that /etc/passwd is world writable, or something
like that. Hence this file, in hopes to enlighten the masses (yeah,
right, like I can do that... anyway, on to business.)
Awk uses regular expressions to search for things, which means you
can use wildcards or even a part of a line to nuke a warning. For
instance -- let's say on a particular host you have NIS explicitly
included in your password file (e.g. no "+" there), but you are a
member of a NIS domain that does have NIS password maps. Since COPS
isn't smart enough right now to figure out that you might not care
about the NIS password maps on your machine (and I'm not sure that
it would be a good idea to ignore this anyway), it checks everything...
you might get a warning like:
Warning! YPassword file, line 9, no password:
ypg::2200:10:YP guest acct:/tmp:/bin/rsh
There are several things you can do to eliminate this message.
If you're familiar with awk, there are some example lines in
"cops_filter"; you can just change those to do what you want. If
you're not an awk hacker, run out and by the book by aho, kernighan,
and weinberger, and learn awk. Well, no, you don't have to -- it's
very easy to do simple things.
IMPORTANT! All filter lines in "cops_filter" will *ONLY* match the
first line of this multi-line warning message (at least, and do the
right thing.) Do not try to filter out the second line -- it won't
work.
(No new information below to awk/shell people that you couldn't get
by just glancing at the filter file -- you can go play with "cops_filter"
now if you wish.)
The simplest thing to do is to add a line (actually 4 lines, as you'll
see below -- but the most important one is the first line) that exactly
matches what you want to get rid of; e.g., for the above example,
you could put something like:
if ($0 ~ /Warning! YPassword file, line 9, no password:/) {
skip_next = 1
next
}
An explanation. In awk, every line of code in the awk program
will act on every line in the input file. In most programming languages
you need to put a loop around the program, but in awk, it is implied.
The $0 here refers to the current input line that the awk program
is looking at. This line says that if the current input line is
equal to "Warning! YPassword file, line 9, no password:", then
you should do what it says between the two curly braces. In this case,
you just set a variable (don't worry about exactly what it does right
now), and then skip to the next line of input from the COPS report file.
That's all there is to it. Notice that at the bottom half of the awk
program, there are places where information gets printed out -- all
those mean is that unless awk sees a pattern that it matches and gets
told to go to the next line, it will print out the current line.
Well, this is probably as clear as mud, but the basic idea is
that you'll be putting a regular expression inbetween two forward
slanting lines ("/"), and if awk matches that, then it will not
print that out in the final COPS report file.
If you don't want to use an exactly matching line, either because
you're a poor typist or lazy or perhaps you have a group of warnings,
all alike, and you'd like to get rid of them, then you can use
wildcards, or even a part of the line(s) in question -- be careful with
this, and make sure you test your awk program out before inflicting it
for real on your cops reports.
For instance, to match the above example, you could say:
if ($0 ~ /Warning! YPassword file, line 9, no password:/)
or:
if ($0 ~ /YPassword file, line 9, no password/)
or, if you really don't want to see any YP/NIS messages, you could use:
if ($0 ~ /YPassword file/)
alternately, an example with wildcards:
if ($0 ~ /YP.* no password/)
All of these would match the example line. However, the bottom two
would match other lines as well -- something like:
Warning! YPassword file, line 12, invalid login directory:
Would also be eliminated from the result file. Be careful especially
when you're dealing with anything that is in the report file that looks
like a regular expression -- characters like "*", "+", and "?", as
well as the forward slash "/" (to keep it separate from the awk
regular expression separator character) should be preceded with a
backslash -- e.g. something like:
if ($0 ~ /\/usr\/spool\/mail is _World_ writable!/)
Check your awk program as described before, and compare the output
with the old report file with diff -- does it do what you thought?
Be careful.
Almost the last Important note -- you can test your filter by saying
something like:
awk -f cops_filter cops_result_file
Where cops_result_file is usually named something like "1992_Dec_31".
Well, that's about it -- good luck!
-- dan
cops_104/docs/obligitory.joke 600 313 12 1565 5156725262 11425 (Many forwards deleted)
An excerpt from Herb Caen:
"We're still trying to check this, but around USAir, staffers are
circulating the story of an employee last-named Gay who boarded a USAir
flight with a non-revenue ticket. Finding the seat assigned to him
occupied by a paying passenger, he slipped into an empty one a couple
of rows back. Then, due to a mechanical delay on another flight, the
plane began filing up so the gate agent came aboard to get all
non-paying passengers off. Stopping at the seat assigned to Mr. Gay,
he said to the man, "Are you Gay?" Looking startled, the man nodded,
at which the agent said, "Then you'll have to get off." Mr. Gay,
hearing this, called out to the agent, "You've got the wrong man --
*I'm* Gay." Whereupon a young man seated across the aisle leaped to
his feet and announced, "Hell, I'm gay, too--they can't kick us *all*
off!"
elay on another flight, the
plane began filing up so the gate agent came aboard to get all
non-paying passengers off. Stopping at the seatcops_104/docs/obligitory.album 600 313 12 342 5156725263 11546
_Big Circumstance_, by Bruce Cockburn (1988, Gold Castle Records, may
have been rereleased by Sony.) A blend of introspection, love, political,
ecological, and religious songs; kind of bouncy rock/folk/blues. Great album!
cops_104/extensions/ 755 313 12 0 5156725272 7554 cops_104/extensions/THINGS_2_DO 600 313 12 3117 5156725264 11356
Possible improvements/extensions of the COPS package might (will?) include
(other than merely fixing bugs existing in the package) :
0) Smarter detection of problems -- a lot of problems can be found in
configuration files; the way they are set up, not merely if they are
writable. These aren't neccessarily hard to check for, but take someone
with a good understanding for the file to write.
1) Better and more thorough Yellow Pages checking.
2) Ditto for UUCP stuff. Fix the perl stuff to work in shell, too.
3) Once again for NFS things.
4) Problems that are specific to a certain flavor of UNIX. For
instance, HP-UX has different files in different places. Perhaps
the system could look for and hunt for the vital files in the various
places rather than having to be put in a configuration file. Also
support for various secure UNIX varieties; e.g. C2 level Sun, IBM's
secure AIX, etc.
5) More problems to be added; by no means are all security problems detected
by COPS. More potential hazards should not be difficult to detect -- merely
adding another module to the system or simply modifying what is here might
suffice.
6) Trying to detect what kind of machine you are on, then acting on that,
possibly using larry wall's configure program.
7) Automounters... a problem. Can we divorce all the home-dir
accessing stuff? Sounds interesting in theory, hard in fact. Maybe
the perl version could handle it?
8) Make a version/script that would run on a "fake" filesystem; e.g. a
full unix filesystem that starts someplace other than root ("/"), like
a diskless client or something.
cops_104/extensions/YAR 600 313 12 1413 5156725265 10210
(YAR -- Yet Another README file)
This is where the odds 'n ends go.
"THINGS_2_DO" is a file that says what I'd like to see done, either
in COPS or in other packages.
"crypto-stuff" tells you where you can get some programs to do
secure digital signatures.
"questions" is a questionaire and some answers I recieved about
computer security. It might prove of interest for general reading.
"netstuff" is a short list of net.references for further information.
"passwords" gives a reference for Matt Bishop's replacement passwd
program, and his fast password cracker.
"uucp.hardening" is a couple of articles taken from the net on how
you beef up uucp security.
"writing.suid" is a nice writeup on how to write a SUID program correctly.
cops_104/extensions/crypto-stuff 600 313 12 613 5156725265 12203
Snefru and MD4 are both digital signature algorithms that are much more
secure than the crc producer in this package. Snefru was posted to
comp.unix.sources, volume 21, I believe, and is hence available from any
c.u.s. archive site, like uunet.uu.net; MD4 is available via anon-ftp from
theory.lcs.mit.edu. You might check them out if you're really serious about
your binaries and stuff.
cops_104/extensions/netstuff 600 313 12 4116 5156725266 11417
For additional information, help on various subjects, etc., there
are various resources available on the net. By no means is this list
exclusive:
alt.security -- high noise, but has some real gems in here. If
you had to read one newsgroup/mailing list for security, this is it.
If you don't read it, you're endangering your system by not keeping
up on the latest methods used to attack and defend systems...
comp.risks -- a moderated newsgroup that talks about the risks of
computing, often discussing computer security.
comp.unix.wizards -- a high noise free-for-all group that has
some choice tidbits of information. Now that this is gone, you might
check out comp.unix.esoterica, or any of the other weird new names.
*I* voted to keep comp.unix.wizards :-)
Security Mailing list -- moderated by Neil Gorsuch, fits and bursts
of information that can be gotten nowhere else. Hard to join the elite
who are on the list, and a long wait for acceptance. Security programs
can be snarfed off of this list at times.
CERT -- the Computer Emergency Response Team has a mailling list
devoted to the development of security tools. As quoted from
their initial mailing:
"The Computer Emergency Response Team Coordination Center (CERT/CC) has
established a new Internet mailing list named CERT-TOOLS. This new
mailing list is now available.
The purpose of this new mailing list is to encourage the exchange of
information on security tools and security techniques. The list
should not be used for security problem reports.
[...]
Mailing list problems, additions, changes, and deletions requests should
be sent to:
cert-tools-request@cert.sei.cmu.edu
[...]
CERT/CC is planning to collect many of the tools and will make the
archive available via anonymous ftp on the cert.sei.cmu.edu system.
A trusted archive service will also be available for tools not intended
for general public usage.
All mail intended to be redistributed should be mailed to:
cert-tools@cert.sei.cmu.edu
Computer Emergency Response Team
Email: cert@cert.sei.cmu.edu
Telephone: 412-268-7090 (answers 24 hours a day)"
cops_104/extensions/passwords 600 313 12 1262 5156725267 11606
For those who need _fast_ password cracking, for whatever reason,
Matt Bishop wrote a fairly incredible password cracking engine, which
is detailed in:
"An Application of a Fast Data Encryption Standard Implementation",
Matt Bishop, Computing Systems 1(3) pp. 221-254 (Summer 1988).
If you have a valid reason for using it, you can mail to Matt at:
bishop@bear.dartmouth.edu
for more information on his package.
For an even better solution, try Matt's replacement for "passwd", which
allows you to configure it to your site to dissallow stupid passwords or
localisms. Highly recomended, available right now via anon-ftp, at
bear.dartmouth.edu, in ~pub/passwd.tar.Z
cops_104/extensions/questions 600 313 12 32033 5156725270 11625
I polled a security mailing list and got about 40 responses to a
selected number of questions dealing with security; it might be useful
for inclusion on how the net (at least some of the security minded ones)
view security. The answers to these questions shaped some of the philosophies
of COPS and might be indicative of the type of security tools to be
developed in the future. My questions start with a number and a ")".
1) What kinds of problems should a software security system (SSS)
such as COPS check for? (Mention specific examples, if you can.)
Just about everyone agreed that the more things checked, the better.
Some specific wants of items I didn't mention, more or less in the order
of # of requests:
Some kind of _secure_ checksum method for checking up on binary files.
Checking binaries for known security problems - sendmail, fingerd,
ftpd, ect.
Checking the validity of the _format_ of key files rather than merely
checking if they are writable.
Checking for potential trojan horses; files such as "ls" in a users
account.
Finding things hidden under mount points.
Keeping track of accounts in a seperate file from /etc/passwd and
run periodic checks to see if any accounts have been added by any
unauthorized user.
Report unusual system activity, such as burning lots of CPU time.
Record unsuccessful login attempts and su's to root, when and by whom
if possible.
2) Are there any security problems too sensitive to be checked
by a SSS? That is, what things should *not* be built into a SSS?
Boy, this was a landslide. Over 90% said NO, and not only no,
but basically "Hell No". The only concerns I got were against password
cracking and problems that could not be easily fixed. There was also
a small amount of concern about limiting access to root, but most realized
that no matter what, the benifits would outweigh any losses if the programs
were put out.
3) What should the primary goal of a SSS be -- discovering as many
security holes as possible in a given system (including bugs or
design flaws that may not be easily fixed -- especially without
source code), or merely uncovering correctable errors (due to
ignorance, carelessness, etc)?
Another landslide. Of all the responses, only one person objected
to finding all holes, although a few did say that finding the fixable
holes was top priority.
One view:
My use for an SSS is as a system monitor, not as a diagnostic tool.
I suppose the diagnostic version also has its uses, but writing and
distributing such a program is asking for trouble. I don't see
anything wrong with writing it and distributing only the binaries.
4) Do you feel that SSS are a security threat themselves?
Some dissent begins to show.... It was almost even here, with the
no's beating out the yes's by a single vote. However, 2/3 of the yes
votes qualified there answer by stating something like "a tool can be
misused" and whatnot. Here are some typical responses:
Of course. They point to way for bad guys. Such is life.
They are a tool. They have the potential for anything. The
security threat lies in how they are used....
No, as long as they don't breed complacency. Just by running
a SSS each night should not make you thinks your systems are
secure.
Fire is also dangerous but VERY useful.
5) Do you think that the SSS should be restricted to be used only
by system administrators (or other people in charge), or should
they be accessible to all?
Here's where the problems start :-) Everyone wants as many
features as possible, but quite a few of you don't want anyone else
to have it. Hmm... Out of 35 responses on this question:
12 - Yes, only SA's.
10 - No.
6 - It would be nice to have it restricted, but... How?
5 - Have two versions; one restricted, one not. Needless to say,
the dangerous stuff should go in the first.
1 - Restrict only parts that detect bugs/whatever that cannot be
repaired.
1 - Argh! Help!
Some quotable quotes:
I don't see how it could be restricted.
Admins, etc only. (possibly said because I'm an admin. From an
intellectual standpoint, I would want to know about this stuff even
if I was just a user)
I think the SSS should be restricted to system
administrators with the realisation that others can probably
get their hands on the code if they want to.
Definitely available to all, SA's can be as lazy as anyone and should not be
allowed to hide behind a veil of secrecy if, in doing so, they expose the
systems they administer.
It seems to me that only an "administrator type" will have sufficient
privilege levels to make _effective_ use of such a tool. Ordinary users
may be able to garner _some_ benefit though, if run on their own files.
If possible, can there be an "administrator" mode and a (restriced/limited)
"user" mode?
(and finally, my personal favorite...)
I think that a check for a hole that can't be closed shouldn't be a part of
the check, if that hole is widespread. I have no examples of any such hole,
but a weak spot that can't be closed and has no workaround is one of the few
candidates for the security by secrecy concept. I have mixed feelings about
this, but if I can't fix the hole, I'd rather not have it's existence be
"public" knowledge. A freely available routine to locate the hole would
spread it's existence far and wide.....(?)
But, if I didn't know about it beforehand then it would be good to have a
tool to tell me it existed. Gads, I hate moral conflicts!
6) When a SSS finds a security flaw in a system, do you want it to
indicate how they flaw could be used to compromise your system, or
would you just accept the conclusion and apply a fix?
This question was ill worded and gramatically incorrect, but still
managed to conjure up a lot of comments. Some thought it was asking if
the system should apply a fix.
In any case, almost 3/4 said Yes, indicate exactly how to exploit
any potential hole. As usual, there were a few with reservations about
the info getting out, but....
Here are some of the more interesting comments:
(Think about this one!)
*I* would like to know to futher my knowledge of Unix, but more importantly
to make sure that the version I have was not modified by a cracker to
put security holes *into* a system. (That'd be sneaky :-)
Security by obfuscation doesn't work.
By definition, a SSS is a software system, and therefore has bugs in it.
If it reported a problem which would cause quite a bit of inconvenience if
fixed, or would be difficult to fix, then I would be much more apt to make
the fix if I knew how the problem could be exploited. This is important,
because many, if not most, sites require only a moderate level of security,
and many security holes are fiendishly difficult to exploit.
We cannot assume that end-purchasers of a system can be as aware of
the internal workings of a system as the designers of the system (or SSS)
are. If a security flaw is discovered, the administrators need to be
informed about what changes are necessary to remove that flaw, and what
repercussions they may have.
[...]
Imagine a SSS that knew sendmail(8) was a security flaw
allowing a worm to enter systems. It would report that sendmail is a
security flaw, please disable it like.... If the vendor had released
a patch, and the SSS didn't know how it, the administrator (in blind
faith to this SSS program) might disable a *very* useful program
unnecessarily.
7) Do you think that there is too much, not enough, or just about
the right amount of concern over computer security? How about at
your computer site? At other sites?
The "not enough"s won, but not by much. I thought that given
the paranoia of a security group, this would be a larger victory.
Lots of people said it depends -- on the type of facility, the size, etc.
Large sites seem to have a healthier view of security (paranoia :-)) than
smaller/non-governmental. Only 4 or 5 said there was enough concern.
A couple of people mentioned _The Cuckoo's Egg_ as suggested reading
(I heartily agree.)
More quotes:
(I don't know if the next answer is true, but I like it anyway!)
This is really a deep philosophical question---something to talk about
over a few beers at the bar, but not here.
I think it's a site dependent problem, and all the above are
true: too much, too little, and just right. Computer is not a
"one size fits all" situation. Having offered that opinion, I
think an assessment of my site or other sites is extraneous, and I
will reserve that opinion.
... more attention to unauthorized use of the networks.
8) Do you think that there should be a ruling body that governs
and enforces rules and regulations of the net -- sort of a net.police?
Some of you wondered what this had to do with software security, but
just about everyone answered anyway. This one scared me! The "No's" only
beat out the "yes's" by one vote. Yikes! Maybe I'm from the old school
of thought, but.... Several people said that it couldn't be done anyway;
a couple mentioned they a CERT-like agency to help out, but not control,
and finally two said that the laws and government were already there to
do this.
It's there, defacto. The free market is working pretty well.
Absolutely. I quarrel with the "net.police" designation, per se, of
course, as do many others. But perhaps something more like a recognized
trade association, and providing similar services. Also, it is time that
the basic duties which must be reasonably performed by a site in order for
it to remain on the net should become a requirement rather than a matter
of individual whim.
Yuck! This is very distasteful to me. It will probably be necessary
though as more and more people participate in the net. Enforcement will
have to be judicious until secure networking is developed and implemented
generally.
No. Aside from the fact that it'd never work, I like Usenet as an
anarchy. It has some rough edges, but for the most part it works. What
does this question have to do with SSS-type programs?
Enforcement will be tough and may hold back legitimate users. But
we have to start somewhere. So I suppose that I agree with having
net.police, as long as they don't turn things into a police.state.net.
9) Do you believe that breaking into other people's systems should
continue to be against the law?
Only one said "no", and s/he had a smiley following the answer.
But there were some of you who voiced concern that it wasn't really
against the law to begin with. In _The Cuckoo's Nest_, Cliff Stoll talked
about a (Canadian, I think) case that the only reason the cracker was
prosecuted was for stealing electricity! Less than a watt or something.
A few of you mentioned denial of services as being a just reason, but
what if they break in only at night, when no one else is on, and they
really don't take anything at all? Should that be less punishable than
someone who sucks away user CPU/disk/whatever?
Breakins should be encouraged and rewarded (1/2 :-).
Yes. Unquestionably. However, those laws should not attempt to regulate
inter-system traffic to cause these things to happen.
Yes - and as a felony in all cases, without exception.
Yes but murder, rape, robbery... are more important and laws and
sentencing should reflect this. There are some around who want to treat
cracking as a capital crime!
Yes, from the denial of services standpoint. I pay $XXX,XXX.XX for a
system, and joe blow slides in and sucks away at those resources, there
should be a nontrivial penalty for getting caught. Don't behead the guy,
but monetary fines or community service would be just fine.
I don't know. I'm not a philosopher. Certainly causing
damage to others is wrong, including denial of service,
compromising sensitive info, or whatever. I'm concerned
though that clamping down on young kids will discourage them
from becoming computer geeks. I think we need to encourage
our young people to become technically literate. If we
don't become a more expert society we can kiss it goodbye;
all we'll have left is our military solutions, like some
brainless jock bully...
I'm not sure that it is everywhere - but: Yes. Should attempting
to break in be against the law: No. Is this vague: Yes.
I did not know that it was. The laws about it have not been tested and
are vague and unclear. You need to be very clear about what the laws
are going to do.
**HELL FUCKING YES** Those of us who started in UNIX years ago have
for the most part *always* respected others!! This I can't stress strong
enough.
10) Is your site academic, government, or commercial in nature?
Just over 1/2 of those that answered claimed university ties,
with about 1/4 being commercial, 1/6 government, a few research sites,
and a couple that were a mixture. Sites included Sun, AT&T, SCO (Xenix),
the DoD, and the Army, among others.
(Guess where this one came from :-)
Research. We invented Unix.
Academic with commercial applications.
Primarily academic, but we are part of the government.
Academic, except when collecting student fees *) *)
nd has no workaround is one of the few
candidates for the security by secrecy concept. I have mixed feelings about
this, but if I can't fix the hole, I'd rather not have it's existence be
"public" knowledge. A freely available routine to locate the hole would
spread it's existence far and wide.....(?)
But, if I didn't know about it beforehand then it would be good to have a
tool to tell me it existed. Gads, I hate moral conflicts!
6) When a SSS finds a security flaw in a cops_104/extensions/uucp.hardening 600 313 12 25633 5156725271 12516 From davidsen@crdos1.crd.ge.com Mon Jun 24 21:39:17 1991
Organization: GE Corporate R&D Center
Date: Fri, 21 Jun 91 23:32:54 EDT
To: df@cert.sei.cmu.edu
Subject: uucp hardening
Well, I might not get to it tomorrow, so I did it tonight. Here's the
stuff I have on uucp hardening. It's not all I know, but all I have
written down...
I give, I give! I got 60+ requests for this so here it is.
I am reposting a few articles about uucp hardening which I have used as
a starting point for hardening my own system. I don't totally agree
with all the things in them, but they are useful input. In particular, I
like to leave uucp as the main uucp file owner, and move all the logins
to other UIDs.
This is the heart of what I do; change all data files in /usr/lib/uucp
to be owned by uucp, rw to owner only, all uucp programs, such as
uucico, uuxqt, uucp, etc, should all be owned by uucp and run setuid.
The uucp related programs in /usr/bin should be done as well, except
uuto and uupick if you have them, they failed on my system when setuid.
The uucp account is made no login. A second account having the same UID
and GID is setup with your favorite shell to do maintenence. The second
login should follow uucp in the passwd file, to allow mail to work
correctly. Then each system dialing into yours is given its own
username and UID, and its login shell is set to /usr/lib/uucp/uucico
(or wherever uucico lives in your system). This prevents anyone from
running under the uucp UID.
If your system will allow it, make up a group just for uucp dialin, put
all the dialing id's there, and don't allow anyone but owner to execute
uucico (chmod 4700 uucico). On some systems this may not work, and you
will have to put the dialin id's as group uucp, and allow that group to
execute uucico (chmod 4710 uucico).
In all cases, no interactive users should run as UID or GID uucp, other
than the maintenence account. This will prevent executing uucico with
debug set and getting login info about systems you call, and/or forcing
calls you don't want to originate and pay for.
Here are the original articles I read about uucp hardening, they were
the starting point for my learning curve in this matter. They were
originally on the unix-pc, but contain info directly applicable to any
"old" uucp, and with modifications to HDB as well.
================
Path: chinet!ethos!gizzmo!fthood!egray
From: egray@fthood
Newsgroups: unix-pc.uucp
Subject: uucp security
Message-ID: <6700001@fthood>
Date: 24 Nov 86 19:14:00 GMT
Lines: 117
Nf-ID: #N:fthood:6700001:000:5839
Nf-From: fthood!egray Nov 24 14:14:00 1986
The 'rules' of uucp security were not applied to the Unix PC, perhaps
because it was assumed that it was going to be a 'home' computer. That
might well be the case in quite a few instances but in other situtations,
the Unix PC might be in a 'hostile' environment. The following dicussion
is directed to those your wish to harden their uucp security.
The first rule is to have an administrative account to own the uucp
commands and directories (call it 'uucpadm' for example). This account
should NOT have the same UID number as the 'uucp' account. The account
should be a normal 'user' account and have one of the standard shells in
the 7th field of the password file instead of /usr/lib/uucp/uucico. The
purpose of this is to prevent a user on a remote system using 'uucp' from
gaining access to your uucp commands and directories.
The second rule is to restrict execute permission on the uucico program.
Any person who can execute this command can turn on the debugging with
the -x option and gain access to the login and passwords to your uucp
accounts on all of your remote systems. This can be easily prevented by
removing the execute permission to 'others'.
The third rule ties the first two together. In order for your uucp
accounts to be able to execute 'uucico', you must create a group for
these users. This group (call it 'uucpgrp' for example) would be
assigned to the uucico program the uucp directories and to the 'uucp'
accounts. In this way only members of this group would have execute
permission on 'uucico'.
Some additional consideration should be given to providing unique UID's
for each 'uucp' account. For example, if the remote machines 'sys1'
and 'sys2' both call your system then they should have unique UID's but
share the same group. This is to provide an accurate accounting records
of login times, etc.
Every uucp file and directory should have it's write permission removed
to 'others'. The files /usr/lib/uucp/L.sys and /usr/lib/uucp/USERFILE
should be set to mode 400 (read to the owner and no access to the
group or 'others').
The /usr/lib/uucp/USERFILE determines which accounts should have 'free
reign' over your files. This file should be set to give read permission
to whatever files your remotes systems need. On a 'generic' account
like 'uucp', the read permission should be set to /usr/spool/uucppublic.
This is to allow the machine calling in as 'uucp' to gain access to
only those files that you have placed in the /usr/spool/uucppublic
directory.
This is the /usr/spool/uucp directory:
drwxrwxr-x 2 uucpadm uucpgrp 272 Nov 23 19:13 .
drwxrwxr-x 5 root bin 80 Oct 11 1985 ..
-rw------- 1 uucpadm uucpgrp 58 Nov 23 18:33 AUDIT
-rw-rw-r-- 1 uucpadm uucpgrp 97 Nov 23 18:33 ERRLOG
-rw-rw-rw- 2 root root 4 Nov 23 19:11 LCK..ph0
-rw-rw-r-- 1 uucpadm mail 78 Jun 5 04:30 LOGDEL
-rw-rw-r-- 1 uucpadm uucpgrp 0 Nov 23 18:33 LOGFILE
-rw-rw-rw- 2 root root 4 Nov 23 19:11 LTMP.44
-rw-r--r-- 1 uucpadm uucpgrp 7320 Nov 23 18:33 Log-WEEK
-rw-rw-r-- 1 uucpadm uucpgrp 1693 Nov 23 18:33 SYSLOG
-rw-r--r-- 1 uucpadm mail 59 Nov 10 05:30 o.Log-WEEK
-rw-r--r-- 1 uucpadm uucpgrp 792 Nov 23 18:33 o.Log-WEEK.z
-rw-rw-r-- 1 uucpadm uucpgrp 202 Nov 23 18:33 o.SYSLOG
This is the /usr/lib/uucp directory:
drwxrwxr-x 4 uucpadm uucpgrp 368 Oct 11 1985 .
drwxrwxr-x 13 bin bin 992 Oct 11 1985 ..
drwxrwxr-x 2 uucpadm uucpgrp 32 Jan 1 1970 .OLD
drwxrwxr-x 2 uucpadm uucpgrp 32 Jan 1 1970 .XQTDIR
-rw-r--r-- 1 root uucpgrp 606 Nov 23 18:33 L-devices
-rw-r--r-- 1 uucpadm uucpgrp 24 Jan 1 1970 L-dialcodes
-r--r--r-- 1 uucpadm uucpgrp 39 Aug 11 09:54 L.cmds
-r-------- 1 uucpadm uucpgrp 180 Nov 23 18:33 L.sys
-r-------- 1 root daemon 180 Sep 24 17:19 L.sys.bak
-rw-r--r-- 1 uucpadm uucpgrp 18 Nov 23 18:33 L_stat
-rw-r--r-- 1 uucpadm uucpgrp 26 Nov 23 18:33 L_sub
-rw-r--r-- 1 uucpadm uucpgrp 84 Nov 23 18:33 R_stat
-rw-r--r-- 1 uucpadm uucpgrp 22 Nov 23 18:33 R_sub
-rw-rw-rw- 1 uucpadm uucpgrp 4 Nov 23 18:33 SEQF
-r-------- 1 uucpadm uucpgrp 55 Aug 11 16:13 USERFILE
-r--r--r-- 1 uucpadm uucpgrp 2581 Jan 1 1970 modemcap
---s--x--- 1 uucpadm uucpgrp 69376 Jan 1 1970 uucico
---s--x--x 1 uucpadm uucpgrp 15536 Jan 1 1970 uuclean
-rwxrwxr-x 1 uucpadm operators 390 Jun 11 20:08 uudemon.day
-rwxrwxr-x 1 uucpadm operators 134 Jan 1 1970 uudemon.hr
-rwxrwxr-x 1 uucpadm operators 332 Jun 11 20:08 uudemon.wk
---x------ 1 uucpadm uucpgrp 7586 Jan 1 1970 uusub
---s--x--x 1 uucpadm uucpgrp 21616 Jan 1 1970 uuxqt
These are the permissions of the uucp commands:
---s--x--x 1 uucpadm bin 21942 Jan 1 1970 /usr/bin/uucp
-rwxr-xr-x 1 bin bin 2108 Jan 1 1970 /usr/bin/uucppwd
---s--x--x 1 uucpadm bin 7378 Jan 1 1970 /usr/bin/uulog
---s--x--x 1 uucpadm bin 2248 Jan 1 1970 /usr/bin/uuname
-rwxr-xr-x 1 bin bin 1596 Jan 1 1970 /usr/bin/uupick
---s--x--x 1 uucpadm bin 18042 Jan 1 1970 /usr/bin/uustat
-rwxr-xr-x 1 bin bin 959 Jan 1 1970 /usr/bin/uuto
---s--x--x 1 uucpadm bin 25310 Jan 1 1970 /usr/bin/uux
This the line out of the /etc/group file:
uucpgrp:NONE:11:uucp,uucpadm,sys1,sys2
This is the part of the /etc/passwd file:
uucpadm:MslxlslvaW5E2:5:11:Admin for Uucp:/usr/lib/uucp:
uucp:QKqtywR1ggBeo:6:11:Generic Unix to Unix Copy:/usr/spool/uucppublic:/usr/lib/uucp/uucico
usys1:bksugI32a9Z/o:7:11:UUCP for sys1:/usr/spool/uucppublic:/usr/lib/uucp/uucico
usys2:g328dkfgl83wo:8:11:UUCP for sys2:/usr/spool/uucppublic:/usr/lib/uucp/uucico
This is a sample /usr/lib/uucp/USERFILE:
usys1,sys1 /
usys2,sys2 /
uucp, /usr/spool/uucppublic /tmp
greg,sys1 /u/greg
------------------------------
Path: chinet!ethos!mtune!shlepper!andys
From: andys@shlepper.UUCP (andy sherman)
Newsgroups: unix-pc.uucp
Subject: Re: uucp security
Summary: HDB uucico does not echo passwords
Message-ID: <119@shlepper.UUCP>
Date: 25 Nov 86 13:51:48 GMT
References: <6700001@fthood>
Organization: AT&T Bell Laboratories, Middletown, NJ
Lines: 33
In article <6700001@fthood>, egray@fthood writes:
> The second rule is to restrict execute permission on the uucico program.
> Any person who can execute this command can turn on the debugging with
> the -x option and gain access to the login and passwords to your uucp
> accounts on all of your remote systems. This can be easily prevented by
> removing the execute permission to 'others'.
>
> The third rule ties the first two together. In order for your uucp
> accounts to be able to execute 'uucico', you must create a group for
> these users. This group (call it 'uucpgrp' for example) would be
> assigned to the uucico program the uucp directories and to the 'uucp'
> accounts. In this way only members of this group would have execute
> permission on 'uucico'.
>
First off, a lot of the lack of security for the 7300 uucp is in the
version of uucp distributed with the basic system. These
shortcomings, incidentally, are shared with any vanilla SysV R2 UNIX
system. The HoneyDanBer uucp package deals with a lot of these
security holes. For example, there is a port of the HoneyDanBer
uucp to the 7300 which does not echo passwords for uucico debugging.
(I know this package is available inside of AT&T. I don't know
if/when it is released outside the company.)
As for restricted access to uucico, I know that when I send mail,
the uucp stuff goes across under my UID. If you have mail set its
UID to call uucico as uucp or mail, don't you lose the ability
to see what user is attached to which jobs in a uustat or in the log?
--
andy sherman 480 Red Hill Road
at&t bell laboratories Middletown, NJ 07748
DDD: (201) 615-5708
UUCP: {ihnp4,allegra,akgua,cbosgd,vax135,mtune,...}!shlepper!andys
------------------------------
Path: chinet!ethos!mtune!mtung!jmd
From: jmd@mtung.UUCP (JM Donnelly)
Newsgroups: unix-pc.uucp
Subject: Re: uucp security
Message-ID: <837@mtung.UUCP>
Date: 25 Nov 86 16:15:21 GMT
References: <6700001@fthood> <119@shlepper.UUCP>
Reply-To: jmd@mtung.UUCP (JM Donnelly)
Organization: AT&T ISL Middletown NJ USA
Lines: 3
I think that protecting /usr/spool/uucp will break the terminal
emulater (async_main) which tries to create a LCK file there.
--
bill davidsen (wedu@ge-crd.ARPA -or- davidsen@crdos1.uucp)
{uunet | philabs}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me
o gain access to
only those files that you have placed in the /usr/spool/uucppublic
directory.
Thiscops_104/extensions/writing.suid 600 313 12 22366 5156725272 12233 .TH SETUID 7 local
.DA 21 Feb 1987
.SH NAME
setuid \- checklist for security of setuid programs
.SH DESCRIPTION
Writing a secure setuid (or setgid) program is tricky.
There are a number of possible ways of subverting such a program.
The most conspicuous security holes occur when a setuid program is
not sufficiently careful to avoid giving away access to resources
it legitimately has the use of.
Most of the other attacks are basically a matter of altering the program's
environment in unexpected ways and hoping it will fail in some
security-breaching manner.
There are generally three categories of environment manipulation:
supplying a legal but unexpected environment that may cause the
program to directly do something insecure,
arranging for error conditions that the program may not handle correctly,
and the specialized subcategory of giving the program inadequate
resources in hopes that it won't respond properly.
.PP
The following are general considerations of security when writing
a setuid program.
.de P
.nr x \\w'\(sq'u+1n
.TP \\nxu
\(sq
..
.P
The program should run with the weakest userid possible, preferably
one used only by itself.
A security hole in a setuid program running with a highly-privileged
userid can compromise an entire system.
Security-critical programs like
.IR passwd (1)
should always have private userids, to minimize possible damage
from penetrations elsewhere.
.P
The result of
.I getlogin
or
.I ttyname
may be wrong if the descriptors have been meddled with.
There is
.I no
foolproof way to determine the controlling terminal
or the login name (as opposed to uid) on V7.
.P
On some systems (not ours), the setuid bit may not be honored if
the program is run by
.IR root ,
so the program may find itself running as
.IR root .
.P
Programs that attempt to use
.I creat
for locking can foul up when run by
.IR root ;
use of
.I link
is preferred when implementing locking.
Using
.I chmod
for locking is an obvious disaster.
.P
Breaking an existing lock is very dangerous; the breakdown of a locking
protocol may be symptomatic of far worse problems.
Doing so on the basis of the lock being `old' is sometimes necessary,
but programs can run for surprising lengths of time on heavily-loaded
systems.
.P
Care must be taken that user requests for i/o are checked for
permissions using the user's permissions, not the program's.
Use of
.I access
is recommended.
.P
Programs executed at user request (e.g. shell escapes) must
not receive the setuid program's permissions;
use of daughter processes and
.I setuid(getuid())
plus
.I setgid(getgid())
after
.I fork
but before
.I exec
is vital.
.P
Similarly, programs executed at user request must not receive other
sensitive resources, notably file descriptors.
Use of
.IR closeall (3)
or close-on-exec arrangements,
on systems which have them,
is recommended.
.P
Programs activated by one user but handling traffic on behalf of
others (e.g. daemons) should avoid doing
.IR setuid(getuid())
or
.IR setgid(getgid()) ,
since the original invoker's identity is almost certainly inappropriate.
On systems which permit it, use of
.I setuid(geteuid())
and
.I setgid(getegid())
is recommended when performing work on behalf of the system as
opposed to a specific user.
.P
There are inherent permission problems when a setuid program executes
another setuid program,
since the permissions are not additive.
Care should be taken that created files are not owned by the wrong person.
Use of
.I setuid(geteuid())
and its gid counterpart can help, if the system allows them.
.P
Care should be taken that newly-created files do not have the wrong
permission or ownership even momentarily.
Permissions should be arranged by using
.I umask
in advance, rather than by creating the file wide-open and then using
.IR chmod .
Ownership can get sticky due to the limitations of the setuid concept,
although using a daughter process connected by a pipe can help.
.P
Setuid programs should be especially careful about error checking,
and the normal response to a strange situation should be termination,
rather than an attempt to carry on.
.PP
The following are ways in which the program may be induced to carelessly
give away its special privileges.
.P
The directory the program is started in, or directories it may
plausibly
.I chdir
to, may contain programs with the same names as system programs,
placed there in hopes that the program will activate a shell with
a permissive
.B PATH
setting.
.B PATH
should \fIalways\fR be standardized before invoking a shell
(either directly or via
.I popen
or
.IR execvp/execlp ).
.P
Similarly, a bizarre
.B IFS
setting may alter the interpretation of a shell command in really
strange ways, possibly causing a user-supplied program to be invoked.
.B IFS
too should always be standardized before invoking a shell.
(Our shell does this automatically.)
.P
Environment variables in general cannot be trusted.
Their contents should never be taken for granted.
.P
Setuid shell files (on systems which implement such) simply cannot
cope adequately with some of these problems.
They also have some nasty problems like trying to run a
.I \&.profile
when run under a suitable name.
They are terminally insecure, and must be avoided.
.P
Relying on the contents of files placed in publically-writeable
directories, such as
.IR /tmp ,
is a nearly-incurable security problem.
Setuid programs should avoid using
.I /tmp
entirely, if humanly possible.
The sticky-directories modification (sticky bit on for a directory means
only owner of a file can remove it) (we have this feature) helps,
but is not a complete solution.
.P
A related problem is that
spool directories, holding information that the program will trust
later, must never be publically writeable even if the files in the
directory are protected.
Among other sinister manipulations that can be performed, note that
on many Unixes (not ours), a core dump of a setuid program is owned
by the program's owner and not by the user running it.
.PP
The following are unusual but possible error conditions that the
program should cope with properly (resource-exhaustion questions
are considered separately, see below).
.P
The value of
.I argc
might be 0.
.P
The setting of the
.I umask
might not be sensible.
In any case, it should be standardized when creating files
not intended to be owned by the user.
.P
One or more of the standard descriptors might be closed, so that
an opened file might get (say) descriptor 1, causing chaos if the
program tries to do a
.IR printf .
.P
The current directory (or any of its parents)
may be unreadable and unsearchable.
On many systems
.IR pwd (1)
does not run setuid-root,
so it can fail under such conditions.
.P
Descriptors shared by other processes (i.e., any that are open
on startup) may be manipulated in strange ways by said processes.
.P
The standard descriptors may refer to a terminal which has a bizarre
mode setting, or which cannot be opened again,
or which gives end-of-file on any read attempt, or which cannot
be read or written successfully.
.P
The process may be hit by interrupt, quit, hangup, or broken-pipe signals,
singly or in fast succession.
The user may deliberately exploit the race conditions inherent
in catching signals;
ignoring signals is safe, but catching them is not.
.P
Although non-keyboard signals cannot be sent by ordinary users in V7,
they may perhaps be sent by the system authorities (e.g. to
indicate that the system is about to shut down),
so the possibility cannot be ignored.
.P
On some systems (not ours)
there may be an
.I alarm
signal pending on startup.
.P
The program may have children it did not create.
This is normal when the process is part of a pipeline.
.P
In some non-V7 systems, users can change the ownerships of their files.
Setuid programs should avoid trusting the owner identification of a file.
.P
User-supplied arguments and input data
.I must
be checked meticulously.
Overly-long input stored in an array without proper bound checking
can easily breach security.
When software depends on a file being in a specific format, user-supplied
data should never be inserted into the file without being checked first.
Meticulous checking includes allowing for the possibility of non-ASCII
characters.
.P
Temporary files left in public directories
like
.I /tmp
might vanish at inconvenient times.
.PP
The following are resource-exhaustion possibilities that the
program should respond properly to.
.P
The user might have used up all of his allowed processes, so
any attempt to create a new one (via
.I fork
or
.IR popen )
will fail.
.P
There might be many files open, exhausting the supply of descriptors.
Running
.IR closeall (3),
on systems which have it,
is recommended.
.P
There might be many arguments.
.P
The arguments and the environment together might occupy a great deal
of space.
.PP
Systems which impose other resource limitations can open setuid
programs to similar resource-exhaustion attacks.
.PP
Setuid programs which execute ordinary programs without reducing
authority pass all the above problems on to such unprepared children.
Standardizing the execution environment is only a partial solution.
.SH SEE ALSO
closeall(3), standard(3)
.SH HISTORY
Locally written, although based on outside contributions.
.SH BUGS
The list really is rather long...
and probably incomplete.
.PP
Neither the author nor the University of Toronto accepts any responsibility
whatever for the use or non-use of this information.
cops_104/bug.chk.sgi 700 313 12 1747 5156725273 7472 #!/bin/sh
#
# SGI module for bug/vulnerability checking
#
ECHO=/bin/echo
TEST=/bin/test
LS=/bin/ls
LS_OPTS="-slagL"
ARCH=/bin/arch
GREP=/bin/grep
AWK=/bin/awk
BUG="$AWK -f ./bug_cmp"
if $TEST ! -f ./bug_cmp ; then
$ECHO "Must have bug compare module, ./bug_cmp, to run..."
exit 2
fi
# what is the date? We just need the month and year...
# Format: Fri Feb 7 14:16:55 PST 1992
if $TEST $# -eq "2" ; then
real_date="$1 $2"
else
real_date=`$DATE | $AWK '{print $2, $NF}'`
fi
# Mail
#
# IRIX 3.3 & 3.31
Mail="/usr/sbin/Mail"
fix_date="31 Oct 1990"
cert_advis="CA-90:08"
if $TEST -f "$Mail" ; then
cur_date=`$LS $LS_OPTS $Mail | $AWK '{print $8, $7, $9}'`
$ECHO $Mail $fix_date $cur_date $cert_advis $real_date | $BUG
fi
# fmt
#
# Fixed in 4.0
fmt="/usr/sbin/fmt"
fix_date="26 Aug 1991"
cert_advis="CA-91:14"
if $TEST -f "$fmt" ; then
cur_date=`$LS $LS_OPTS $fmt | $AWK '{print $8, $7, $9}'`
$ECHO $fmt $fix_date $cur_date $cert_advis $real_date | $BUG
fi
# finis
F}'`
fi
# Mail
#cops_104/ftp.chk 755 313 12 20303 5156725273 6744 :
#
# Usage: ftp.chk [-a]
#
# This shell script checks to see if you've set up (mainly anonymous)
# ftp correctly. The "-a" option forces a check on your anon-ftp setup
# (without the flag, this will look in your /etc/passwd, to see if user
# ftp exists, and proceed onwards anyway) without that, this script
# doesn't do a whole lot -- just check to see if your ftpusers file
# doesn't have any root accounts in it. There seems to be some different
# types of ftp's around; for instance, some allow "chmod" -- and if the home
# dir is owned by "ftp", you're toast. So I've tried to err on the side of
# safety...
#
# See the man page for a more detailed description, here's what this
# checks for:
#
# - User ftp exists in the password file.
# - root (or all root equivalents) are in ftpusers file.
# - Home directory for ftp should exist, and not be /
# - The ~ftp/etc/{passwd|group} should not be the same as the real ones.
# - Various critical files/directories should exist, and have correct
# permissions and owners; variables "$primary" and "$secondary" can be set
# to whomever you want owning the files:
#
# File/Dir Perms Owner Other
# ========= ====== ====== ======
# ~ftp non-w.w. root
# or
# ~ftp 555 ftp if no chmod command exists
#
# All of these are ftp owned iff no chmod exists...
#
# ~ftp/bin non-w.w. root/ftp
# or
# ~ftp/bin non-w. and ftp w. ftp
# ~ftp/bin/ls 111 root/ftp
# ~ftp/etc non-w.w. root
# or
# ~ftp/etc non-w. & ftp w. ftp
# ~ftp/etc/passwd non-w.w. root/ftp 0 size or nonexistant
# ~ftp/etc/group non-w.w. root/ftp 0 size or nonexistant
# ~ftp/pub non-w.w. root/ftp
# ~ftp/incoming world-writable root/ftp This can be set to "pub"
# ~ftp/.rhosts non-w.w. root 0 size, is optional
# ~ftp/* non-w.w. other dirs/files in ~ftp
#
# If an argument is present, it should be an "a"
TEST=/bin/test
ECHO=/bin/echo
if $TEST $# -gt 1 ; then
$ECHO Usage: $0 [-a]
exit 1
fi
if $TEST $# -eq 1 ; then
if $TEST $1 = "-a" ; then
anonymous=yes
else
$ECHO Usage: $0 [-a]
exit 1
fi
fi
# Primary and secondary owners of the ftp files/dirs; if you *don't* have
# chmod, you can probably change the secondary owner to "ftp". If you have
# chmod in your ftp, definitely have secondary to some other account (root
# is fine for this.)
primary=root
secondary=root
# some might have this as ftpd; is the account in /etc/passwd
ftpuid=ftp
# Where is everyone?
AWK=/bin/awk
EGREP=/usr/bin/egrep
LS=/bin/ls
CMP=/bin/cmp
RM=/bin/rm
YPCAT=/usr/bin/ypcat
CAT=/bin/cat
# system files
ftpusers=/etc/ftpusers
passwd=/etc/passwd
group=/etc/group
# A pox on YP/NIS, making life tougher for me :-) Thanks to Rob Kolstad
# for pointing this out -- you need to use ypcat to get the password file,
# if you run yp:
# Scratch files for testing:
yp_passwd="./p.$$"
yp_group="./g.$$"
all_passwds="./ap.$$"
# generic test to check for yp use?
if $TEST -s $YPCAT ; then
$YPCAT passwd > $yp_passwd
if $TEST $? -eq 0 ; then
$YPCAT group > $yp_group
yp=true
else
yp=false
fi
fi
if $TEST "$yp" = "true" ; then
$CAT $yp_passwd $passwd > $all_passwds
passwd=$yp_passwd
group=$yp_group
else
$CAT $passwd > $all_passwds
fi
# ftp's files:
ftproot=`$AWK -F: '/^'"$ftpuid"':/{print $6}' $passwd`
# just recheck that user ftp exists:
ftpuid=`$AWK -F: '/^'"$ftpuid"':/{print $1}' $passwd`
#
# If they have user $ftpuid in /etc/password, then anon-ftp is possible...
#
# Comment this (next three lines) out if you don't want this program to
# automatically detect anon-ftp setup!
if $TEST -n "$ftpuid" ; then
anonymous=yes
fi
ftprhosts=$ftproot/.rhosts
ftpbin=$ftproot"/bin"
ftpls=$ftpbin"/ls"
ftpetc=$ftproot"/etc"
ftppasswd=$ftpetc"/passwd"
ftpgroup=$ftpetc"/group"
# the pub/incoming stuff; by default, pub is *not* world writable, incoming
# is; if you want pub to be world writable, just change incoming to "pub"
incoming=incoming
ftppub=$ftproot"/pub"
crit_files="$ftpgroup $ftppasswd $ftpls"
if $TEST -s "$ftpusers" ; then
# check to see if root (or root equivalents) is in ftpusers file
all_roots=`$AWK -F: '{if ($3==0 && length($2)==13) printf("%s ", $1)}' $all_passwds`
if $TEST -n "$all_roots" ; then
for i in $all_roots
do
if $TEST ! "`$EGREP '^'"$i"'$' $ftpusers`"
then
$ECHO Warning! $i should be in $ftpusers!
fi
done
fi
else
$ECHO "Warning! $ftpusers should exist!"
fi
# do the anonymous ftp checking stuff now
if $TEST -n "$anonymous" ; then
# if the user ftp doesn't exist, no-anon stuff....
if $TEST -z "$ftpuid" ; then
$ECHO Warning! Need user $ftpuid for anonymous ftp to work!
$RM -f $yp_passwd $yp_group $all_passwds
exit 1
fi
#
# ftp's home dir checking
if $TEST ! -d "$ftproot" -o -z "$ftproot"; then
$ECHO Warning! Home directory for ftp doesn\'t exist!
$RM -f $yp_passwd $yp_group $all_passwds
exit 1
fi
if $TEST "$ftproot" = "/" ; then
$ECHO Warning! $ftproot ftp\'s home directory should not be \"/\"!
fi
#
# Don't want the passwd and group files to be the real ones!
if $TEST "$passwd" != "$ftppasswd" ; then
if $TEST "`$CMP $passwd $ftppasswd 2> /dev/null`" ; then
:
else $ECHO ftp-Warning! $ftppasswd and $passwd are the same!
fi
fi
if $TEST "$group" != "$ftpgroup" ; then
if $TEST "`$CMP $group $ftpgroup 2> /dev/null`" ; then
:
else $ECHO ftp-Warning! $ftpgroup and $group are the same!
fi
fi
# want to check all the critical files and directories for correct
# ownership.
#
# This is what a "/bin/ls -l" of a file should look like:
# ---x--x--x 1 root 81920 Dec 31 1999 /bin/ls
# So in awk, $3 is the owner, $1 is the permission.
#
# some versions don't need much of anything... no etc directory or
# password/group files.
# crit_files=$ftpls
# others need etc directory & password/group files. Experiment.
crit_files=$crit_files" "$ftpbin" "$ftpetc
for i in $crit_files
do
if $TEST ! -f $i -a ! -d $i; then
$ECHO "ftp-Warning! File $i is missing (anon-ftp setup)!"
fi
owner=`$LS -Lld $i | $AWK '{print $3}'`
if $TEST "$owner" = "$primary" -o "$owner" = "$secondary" ; then
:
else
$ECHO ftp-Warning! $i should be owned by $primary or $secondary!
fi
done
# ftproot is special; if owned by root; should be !world writable;
# if owned by ftp, should be mode 555
owner=`$LS -Lld $ftproot | $AWK '{print $3}'`
perms=`$LS -Lld $ftproot | $AWK '{print $1}'`
if $TEST "$owner" = "$primary" -o "$owner" = "$secondary" ; then
:
else
$ECHO ftp-Warning! $ftproot should be owned by $primary or $secondary!
fi
# ftp-root should not be world-writable:
./is_able $ftproot w w
# if ftp owns root-dir, then mode should be 555:
if $TEST "$owner" = "$ftpuid" -a "$perms" != "dr-xr-xr-x" ; then
$ECHO ftp-Warning! $ftproot should be mode 555!
fi
#
# check the .rhosts file:
if $TEST -f $ftprhosts ; then
if $TEST -s $ftprhosts ; then
$ECHO ftp-Warning! $ftprhosts should be be empty!
fi
owner=`$LS -Lld $ftprhosts | $AWK '{print $3}'`
if $TEST "$owner" = "$primary" -o "$owner" = "$secondary" ; then
:
else
$ECHO ftp-Warning! $ftprhosts should be owned by $primary or $secondary!
fi
fi
#
# finally, some permissions of miscellaneous files:
perms=`$LS -Lld $ftpls | $AWK '{print $1}'`
if $TEST "$perms" != "---x--x--x" ; then
$ECHO ftp-Warning! Incorrect permissions on \"ls\" in $ftpbin!
fi
perms=`$LS -Lld $ftppasswd | $AWK '{print $1}'`
if $TEST "$perms" != "-r--r--r--" ; then
$ECHO ftp-Warning! Incorrect permissions on \"passwd\" in $ftpetc!
fi
perms=`$LS -Lld $ftpgroup | $AWK '{print $1}'`
if $TEST "$perms" != "-r--r--r--" ; then
$ECHO ftp-Warning! Incorrect permissions on \"group\" in $ftpetc!
fi
# Finally, the ~ftp/{pub|incoming|whatever} stuff:
all_dirs=`$LS -Lal $ftproot | $AWK '{if (NF >= 8) print $NF}'`
for i in $all_dirs
do
if $TEST -n "`is_able $ftproot/$i w w`" -a $i != "$incoming" ; then
$ECHO Warning! Anon-ftp directory $i is World Writable!
fi
done
fi
# get rid of any yp evidence
$RM -f $yp_passwd $yp_group $all_passwds
# end of script
===== ======
# ~ftp non-w.w. root
# or
# ~ftp 555 ftp if no chmod command exists
#
# All of these are ftp owned iff no chmod exists...
#
# ~ftp/bin non-w.w. root/ftp
# or
# ~ftp/bin non-w. and ftp w. ftp
# ~ftp/bincops_104/kuang 755 313 12 13521 5156725275 6522 :
# /* Copyright 1985 Robert W. Baldwin */
# /* Copyright 1986 Robert W. Baldwin */
#
# Jan 1990, Ported to bourne shell from Csh. Dan Farmer
#
# Took out some comments, combined four of Bob's shell
# scripts into one (the target script remains separate for
# easy editing of targets.) More or less a straight line
# for line translation; a rewrite that goes for speed will
# come later. Maybe just rewrite it in C. Yeah, that's it....
###############################################
# Kuang: Rule based computer security checker.
###############################################
# commands used....
SH=/bin/sh
MV=/bin/mv
TEST=/bin/test
ECHO=/bin/echo
AWK=/bin/awk
RM=/bin/rm
# Initialization.
$SH ./init_kuang
# Main loop
#
$ECHO Starting main loop #>/dev/tty
while $TEST -f uids.n -o -f gids.n -o -f files.n
do
if $TEST -f uids.n ; then
$MV uids.n uids.x
# Process a list of uids from stdin.
# Usage: douids username comments
$ECHO Called douids #>/dev/tty
i=1
while $TEST "1"
do
nextuid=`$AWK '{if (NR=="'$i'") print $0}' uids.x`
i=`expr $i + 1`
if $TEST -z "$nextuid" ; then
break;
fi
user=`$ECHO $nextuid | $AWK '{print $1}'`
$ECHO " " User $user #>/dev/tty
# Rules mapping uids to files.
#
next=`$ECHO $nextuid | $AWK '{for (i=2;i<=NF;i++) printf("%s ", $i)}'`
./addto files /etc/passwd replace grant $user $next
./addto files /usr/lib/aliases replace trojan $user $next
# hsh = home sweet home = home directory of $user
hsh=`./tilde $user`
if $TEST -f $hsh/.rhosts ; then
./addto files $hsh/.rhosts write grant $user $next
fi
if $TEST -f $hsh/.login ; then
./addto files $hsh/.login replace trojan $user $next
fi
if $TEST -f $hsh/.cshrc ; then
./addto files $hsh/.cshrc replace trojan $user $next
fi
if $TEST -f $hsh/.profile ; then
./addto files $hsh/.profile replace trojan $user $next
fi
if $TEST "$user" = "root" ; then
if $TEST -f /usr/lib/crontab ; then
./addto files /usr/lib/crontab replace create supershell $next
else
./addto files /usr/spool/cron/crontabs replace create supershell $next
fi
./addto files /etc/rc replace trojan $user $next
./addto files /etc/rc.local replace trojan $user $next
fi
if $TEST "$user" != "root" ; then
./addto files /etc/hosts.equiv replace allow rlogin $next
fi
if $TEST "$user" != "root" -a -f /etc/hosts.equiv -a -s /etc/hosts.equiv
then
./addto files /etc/hosts replace fake HostAddress $next
fi
done
fi
if $TEST -f gids.n ; then
$MV gids.n gids.x
$ECHO Called dogids #>/dev/tty
i=1
while $TEST "1"
do
nextgid=`$AWK '{if (NR=="'$i'") print $0}' gids.x`
i=`expr $i + 1`
if $TEST -z "$nextgid" ; then
break;
fi
group=`$ECHO $nextgid | $AWK '{print $1}'`
$ECHO " " Group $group #>/dev/tty
# Rules mapping gids to uids.
#
next=`$ECHO $nextgid | $AWK '{for (i=2;i<=NF;i++) printf("%s ", $i)}'`
use=`./members $group`
for user in $use
do
./addto uids $user grant $group $next
done
# Rules mapping gids to files.
#
./addto files /etc/group replace grant $group $next
done
fi
if $TEST -f files.n ; then
$MV files.n files.x
# A list of file names is read from successive lines of stdin.
# Each file is examined for ways to access it.
# The input format is:
#
# The is either "write" or "replace".
#
$ECHO Called dofiles. #>/dev/tty
i=1
while $TEST "1"
do
nextfile=`$AWK '{if (NR=='"$i"') print $0}' files.x`
i=`expr $i + 1`
if $TEST -z "$nextfile" ; then
break;
fi
file=`$ECHO $nextfile | $AWK '{print $1}'`
mode=`$ECHO $nextfile | $AWK '{print $2}'`
$ECHO " File $file, mode $mode" #>/dev/tty
# Rules converting filename goals into UserName or GroupName goals.
#
next=`$ECHO $nextfile | $AWK '{for (i=3;i<=NF;i++) printf("%s ", $i)}'`
writers=`./filewriters $file`
numwriters=`$ECHO $writers | $AWK '{print NF}'`
if $TEST "$numwriters" = "3" ; then
owner=`$ECHO $writers | $AWK '{print $1}'`
group=`$ECHO $writers | $AWK '{print $2}'`
other=`$ECHO $writers | $AWK '{print $3}'`
$ECHO " Writers are $owner $group $other" #>/dev/tty
./addto uids $owner $mode $file $next
if $TEST "$group" != "NONE" ; then
./addto gids $group $mode $file $next
fi
if $TEST "$other" != "NONE" ; then
./addto uids $other $mode $file $next
fi
else
$ECHO " $file does not exist" #>/dev/tty
continue
fi
# Rules converting filename goals into other filename goals.
#
if $TEST "$mode" != "replace" ; then
continue
fi
parent=`$ECHO $file | $AWK -F/ '{if (NF == 2) {
printf("/%s", $1)}
else if (NF>2) {for (i=2;i/dev/tty
$ECHO ", " basename is $basename #>/dev/tty
if $TEST -n "$parent" ; then
./addto files $parent write replace $basename $next
fi
done
fi
done
# destroy the evidence.... Need "Success" file for report, though.
$RM files.? gids.? uids.?
cops_104/group.chk 755 313 12 13500 5156725275 7312 :
#
# group.chk
#
# Check group file -- /etc/group -- for incorrect number of fields,
# duplicate groups, non-alphanumeric group names, and non-numeric group
# id's.
#
# Awk part based on _passwd_ from _The AWK Programming Language_, page 78
#
# Mechanism: Group.check uses awk to ensure that each line of the group
# has 4 fields, as well as examining each line for any duplicate groups or
# any duplicate user id's in a given group by using "sort -u" to ferret
# out any duplications. It also checks to make sure that the password
# field (the second one) is a "*", meaning the group has no password (a
# group password is usually not necessary because each member listed on
# the line has all the privilages that the group has.) All results are
# echoed to standard output. Finally it ensures that the group names
# are alphanumeric, that the group id's are numeric, and that there are
# no blank lines. For yellow pages groups, it does the same checking,
# but in order to get a listing of all members of the groups, it does a
# "ypcat group > ./$$" and uses that temporary file for a groupfile.
# It removes the tmp file after using it, of course.
# The /etc/group file has a very specific format, making the task
# fairly simple. Normally it has lines with 4 fields, each field
# separated by a colon (:). The first field is the group name, the second
# field is the encrypted password (an asterix (*) means the group has no
# password, otherwise the first two characters are the salt), the third
# field is the group id number, and the fourth field is a list of user
# ids in the group. If a line begins with a plus sign (+), it is a yellow
# pages entry. See group(5) for more information.
#
#
AWK=/bin/awk
SED=/bin/sed
ECHO=/bin/echo
TEST=/bin/test
SORT=/usr/bin/sort
UNIQ=/usr/bin/uniq
YPCAT=/usr/bin/ypcat
RM=/bin/rm
# Used for Sun C2 security group file. FALSE (default) will flag
# valid C2 group syntax as an error, TRUE attempts to validate it.
# Thanks to Pete Troxell for pointing this out.
C2=FALSE
etc_group=/etc/group
yp_group=./$$
yp=false
if $TEST -f $YPCAT
then
if $TEST -s $YPCAT
then
$YPCAT group > $yp_group
if $TEST $? -eq 0
then
yp=true
fi
fi
fi
# Testing $etc_group for potential problems....
# First line is for a yellow pages entry in the group file.
# It really should check for correct yellow pages syntax....
$AWK 'BEGIN {FS = ":" }
{
if (substr($1,1,1) != "+") { \
if ($0 ~ /^[ ]*$/) {
printf("Warning! Group file, line %d, is blank\n", NR)
}
else {
if (NF != 4) {
printf("Warning! Group file, line %d, does not have 4 fields: %s\n", NR, $0)
} \
if ($1 !~ /[A-Za-z0-9]/) {
printf("Warning! Group file, line %d, nonalphanumeric user id: %s\n", NR, $0)
} \
if ($2 != "" && $2 != "*" && $2 != "!") {
if ("'$C2'" != "TRUE") {
if (length($2) == 13)
printf("Warning! Group file, line %d, group has password: %s\n", NR, $0)
}
else {
if ("#$"$1 != $2)
printf("Warning! Group file, line %d, group has invalid field for C2:\n%s\n", NR, $0)
} \
} \
if ($3 !~ /[0-9]/) {
printf("Warning! Group file, line %d, nonnumeric group id: %s\n", NR, $0)
}
}
}
}' $etc_group
#
# Look for duplications in groups in $etc_group
#
result=`$AWK -F: '{print $1}' $etc_group | $SORT |$UNIQ -d`
if $TEST "$result"
then
$ECHO "Warning! Duplicate Group(s) found in $etc_group:"
$ECHO $result
fi
#
# Next, check for duplicate users in a group in /etc/group. Let
# awk do all the work (thanks, adri!)
#
# Ignore all groups with less than two members.
#
awk -F: 'split($4, users, ",") > 1 {
ct = 0
for (i in users) {
curuser = users[i]
for (j in users) {
if (j > i && curuser == users[j]) {
if (ct++ == 0) print "Warning! Group "$1" has duplicate user(s):"
print curuser
}
}
}
}' $etc_group
#
# Test yellow pages groups as well
if $TEST "$yp" = "true"
then
$AWK 'BEGIN {FS = ":" }
{
if ($0 ~ /^[ ]*$/) {
printf("Warning! YGroup file, line %d, is blank\n", NR)
}
else {
if (NF != 4) {
printf("Warning! YGroup file, line %d, does not have 4 fields: %s\n", NR, $0)
} \
if ($1 !~ /[A-Za-z0-9]/) {
printf("Warning! YGroup file, line %d, nonalphanumeric user id: %s\n", NR, $0)
} \
if ($2 != "" && $2 != "*") {
if (length($2) == 13)
printf("Warning! YGroup file, line %d, group has password: %s\n", NR, $0)
} \
if ($3 !~ /[0-9]/) {
printf("Warning! YGroup file, line %d, nonnumeric group id: %s\n", NR, $0)
}
}
}' $yp_group
#
# Look for duplications in groups in yellow pages groups
#
yresult=`$AWK -F: '{print $1}' $yp_group | $SORT |$UNIQ -d`
if $TEST "$yresult"
then
$ECHO "Warning! Duplicate Group(s) found in yellow pages group:"
$ECHO $result
fi
#
# Next, check for duplicate users in a group in yellow groups. Let
# awk do all the work (thanks, adri!)
# ignore all groups with one member.
#
awk -F: 'split($4, users, ",") > 1 {
ct = 0
for (i in users) {
curuser = users[i]
for (j in users) {
if (j > i && curuser == users[j]) {
if (ct++ == 0)
print "Warning! YGroup "$1" has duplicate user(s):"
print curuser
}
}
}
}' $yp_group
fi
$RM -f $yp_group
# end
cops_104/init_kuang 755 313 12 1666 5156725276 7535 # /* Copyright 1985 Robert W. Baldwin */
# /* Copyright 1986 Robert W. Baldwin */
###############################################
# Kuang: Rule based computer security checker.
###############################################
CAT=/bin/cat
ECHO=/bin/echo
#
# Initialization.
#
./clearfiles
#
# First setup what we have access to.
# The uids.k file must include the user 'OTHER' meaning the world access bits.
# Add any other UIDs accessible to the attacker (e.g., ftp, daemon).
#
# Directly accessible user IDs.
$CAT >uids.k <uids.k <gids.k <gids.k </dev/tty
./addto uids root DO ANYTHING
cops_104/is_able.chk 755 313 12 4440 5156725277 7541 :
#
# is_able.chk
#
# This shell script checks the permissions of all files and directories
# listed in the configuration file "is_able.lst", and prints warning messages
# according to the status of files. You can specify world or group readability
# or writeability. See the config file for the format of the configuration
# file.
#
# Mechanism: This shell script parses each line from the configure file,
# changes into the directory the file is in, and then uses the "is_able"
# program to check if any of the directories in question are writable by
# world/group. All results are written to standard output.
#
TEST=/bin/test
ECHO=/bin/echo
AWK=/bin/awk
SED=/bin/sed
config_file=is_able.lst
# where the test is run:
old_dir=`pwd`
if $TEST ! -f "$config_file" ; then
$ECHO "Config file $config_file doesn't exist!"
exit
fi
# Read from $dir_list (e.g. "is.chk.lst") what files/dirs to check.
#
# Comments are lines starting with a "#".
#
# /path/to/{dir|file} World/Group Read/Write/Both
# as above {W|w|G|g} {R|r|W|w|B|b}
#
$AWK '/^#/ {
next;}
{ world=group=read=write=both=0; \
# need 3 fields, or format error
if (NF != 3) next; \
if ($2 != "W" && $2 != "w" && $2 != "G" && $2 != "g") next; \
if ($3!="R"&&$3!="r"&&$3!="W"&&$3!="w"&&$3!="B"&&$3!="b") next; \
for (f=1;f < NF; f++) printf("%s ", $f); \
print $NF;
}' $config_file |
while read targets
do
# Use sed, 'cause awk lets me down (line too long) -- then realize
# I should have used sed anyway. Lazy bum.
foo=`echo "$targets" | $SED 's/\(.*\)....$/\1/'`
args=`echo "$targets" | $SED 's/.*\(...\)$/\1/'`
# I added this, to change into the directory before checking
# for writability; the reason? With long dir pathnames that had
# lots of files inside, the shell would blow up, trying to expand
# all the full paths, and stuff it into a single variable. For
# instance, a line like this in $config_file:
#
# /usr/foo/bar/cowabunga/* w w
#
# Would expand to "/usr/foo/bar/cowabunga/ls /usr/..." Need full
# pathnames, tho! And it can still blow up, tho it's tougher.
#
dir=`echo "$targets" | $SED 's/\(.*\\)\/[^ ]* .*$/\1/'`
if $TEST -n "$dir" -a -d "$dir" ; then
cd $dir
fi
for f in $foo
do
# echo $dir $f $args
$old_dir/is_able $f $args
done
cd $old_dir
done
# end of script
cops_104/rc.chk 755 313 12 6311 5156725311 6533 :
#
# Usage: rc.chk
#
# This checks pathnames and files inside the shell script files /etc/rc*
# for writability.
#
# Mechanism: The commands inside the files /etc/rc* are executed when
# the machine is booted. This shell script greps for commands/paths that
# are of these forms:
#
# /path/command # or whatever
# or
# PATH=:/bin:/usr/bin:. # or whatever
# or
# MYVAR=`/path/command` # or whatever
#
# It then takes each potential problem-string and uses the program
# "is_writable" to determine if it is world writable. All results are
# echoed to standard output.
#
# 12 Apr 90, Mark Plumbly made it ignore lines starting with rm -f
# (popular in rc files) and fixed my code so it would ignore everything
# after a ">".
#
SED=/bin/sed
CAT=/bin/cat
RM=/bin/rm
AWK=/bin/awk
LS=/bin/ls
TEST=/bin/test
EGREP=/usr/bin/egrep
ECHO=/bin/echo
SORT=/usr/bin/sort
FIND=/bin/find
# temp file for stuff:
FOO_RC="./rc.foo.$$"
FOO_RC2="./rc.foo2.$$"
# CHANGE THIS LINE OR PUT IN FILE NAMES IF/AS NEEDED!
# (for example: init_files="/etc/rc /etc/rc.local")
#
# init_files=`$LS /etc/*rc /etc/rc* /etc/rc*.d/* /etc/shutdown.d/* /etc/inittab | $SORT -u`
potential_files="/etc/*rc /etc/rc*"
if $TEST -d /etc/shutdown.d ; then
potential_files=$potential_files" /etc/shutdown.d"
fi
if $TEST -f /etc/inittab ; then
potential_files=$potential_files" /etc/inittab"
fi
init_files=`$FIND $potential_files -print | $SORT -u`
#
# This should get all paths in /etc/rc* files; at least two types here.
# First type starts with a "/", the second is either in the form :
#
# PATH=:/bin:/usr/bin:. # or whatever
# or
# MYVAR=`/bin/echo "hello"` # or whatever
#
# Notice also I strip out any references to /tmp, /usr/tmp,
# /dev/*ty's, and /dev/null.
#
# 12 Apr mdp: Modified to remove "> file" as well as ">file"
# and remove "rm -f file" (this removes a few bogus ones).
# (i.e. things which are written to or removed only are ignored).
#
# You can try this, or use the old method...
# for file in $init_files
# do
# if $TEST -s $file ; then
# ./chk_strings $file
# fi
# done
# exit
for file in $init_files
do
if $TEST -f "$file" ; then
$AWK '{ if (substr($1,1,1)== "#") next; \
for (i=1;i<=NF;i++) \
{ first=substr($i,1,1); \
if (first==">"||first=="#"||first=="$") \
break; \
else if ($i == "rm") \
break; \
else if (first == "/") \
print "\"'$file'\"", $i;\
} \
}' $file |
$SED -e s/\"//g -e s/\'//g -e s/\`//g -e s/\;// |
$EGREP -v "/dev/.*ty|/tmp|/usr/tmp|/dev/null"
fi
done | sort -u >> $FOO_RC2
#
# Ok -- $FOO_RC has a format like thus:
# /etc/rc.local /bin/foofile
#
# We want to kill off all dups in the second field:
$AWK '{dup[$2] = $1}
END { for (i in dup) print dup[i], i;}' $FOO_RC2 | $SORT > $FOO_RC
# First, get the ones starting with "/":
#
# DANGER! DANGER! DANGER Will Robinson! Awk runs out of room ("bails
# out") if too many files are here....
# for i in `$CAT $FOO_RC`
cat $FOO_RC | while read i
do
target=`$ECHO $i | $SED 's/.* //'`
if $TEST -f "$target" ; then
blame=`$ECHO $i | $SED 's/ .*$//'`
if ./is_writable $target
then
$ECHO "Warning! File $target (in $blame) is _World_ writable!"
fi
fi
done
$RM -f $FOO_RC $FOO_RC2
# end of script
cops_104/is_able.lst 755 313 12 3216 5156725300 7561 # This lists any/all sensitive files the administration wants to ensure
# non-read/writability of. Comments are lines starting with a "#".
#
# USE FULL PATHNAMES!
#
# Lines are of the format:
#
# /path/to/{dir|file} World/Group Read/Write/Both
#
# as above {w|g} {r|w|b}
#
/ w w
/etc w w
/usr w w
/bin w w
/dev w w
/usr/bin w w
/usr/etc w w
/usr/adm w w
/usr/lib w w
/usr/include w w
/usr/spool w w
/usr/spool/mail w w
/usr/spool/news w w
/usr/spool/uucp w w
/usr/spool/at w w
/usr/local w w
/usr/local/bin w w
/usr/local/lib w w
/usr/users w w
/Mail w w
# some Un*x's put shadowpass stuff here:
/etc/security w r
# /.login /.profile /.cshrc /.rhosts
/.* w w
# I think everything in /etc should be !world-writable, as a rule; but
# if you're selecting individual files, do at *least* these:
# /etc/passwd /etc/group /etc/inittab /etc/rc /etc/rc.local /etc/rc.boot
# /etc/hosts.equiv /etc/profile /etc/syslog.conf /etc/export /etc/utmp
# /etc/wtmp
/etc/* w w
/bin/* w w
/usr/bin/* w w
/usr/etc/* w w
/usr/adm/* w w
/usr/lib/* w w
/usr/include/* w w
/usr/local/lib/* w w
/usr/local/bin/* w w
/usr/etc/yp* w w
/usr/etc/yp/* w w
# individual files:
/usr/lib/crontab w b
/usr/lib/aliases w w
/usr/lib/sendmail w w
/usr/spool/uucp/L.sys g b
# NEVER want these writeable/readable!
/dev/kmem w b
/dev/mem w b
# Optional List of assorted files that shouldn't be
# write/readable (mix 'n match; add to the list as desired):
/usr/adm/sulog w r
/.netrc w b
# HP-UX and others:
/etc/btmp w b
/etc/securetty w b
# Sun-fun
/dev/drum w b
/dev/nit w b
/etc/sunlink/dni/rc w w
cops_104/kuang.pl.shar 755 313 12 123304 5156725302 10100 #!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 01/09/1991 15:04 UTC by df@death.cert.sei.cmu.edu
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 9782 -rw------- README.perl
# 1776 -rwx------ get-cf
# 6490 -rw------- kuang.1
# 16925 -rwx------ kuang.pl
# 284 -rwx------ kuang_all
# 1307 -rw------- put-cf
# 1274 -rw------- yagrip.pl
#
# ============= README.perl ==============
if test -f 'README.perl' -a X"$1" != X"-c"; then
echo 'x - skipping README.perl (File already exists)'
else
echo 'x - extracting README.perl (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'README.perl' &&
XThis is a perl version of Dan's version of Bob Baldwin's Kuang program
X(originally written as some shell scripts and C programs).
X
XThe original intent was to improve the speed of kuang, which is
Xespecially important for installations like ours with several thousand
Xaccounts and NFS things and all that. The shell version of Kuang used
XC programs to add rules, get a groups members, determine the writers
Xof a file, and so on, which really slowed things down.
X
X "no" problems /etc staff writeable
X ------------- --------------------
Xshell kuang 2:14 (14) 12:26 (98) 0.1 p/s
Xperl kuang 1:10 (18) 2:34 (588) 3.8 p/s
X
XThe "no" problems column indicates the time taken (and number of plans
Xconsidered) for the shell and Perl versions of Kuang on a system with
Xno known security problems. The "/etc staff writeable" column gives
Xtiming and # of plans for a system with a /etc directory that is
Xwriteable by group staff, which contains several dozen users.
X
XAs you can see, the Perl version is a bit faster. Turns out there are
Xall sorts of details that need to be considered in real
Ximplementations of Kuang type programs, some of which are discussed
Xbelow.
X
X --- Steve Romig, CIS, Ohio State, October 1990
X
X------------------------------------------------------------------------------
X
XSome Features of the Perl Version
X
X Caches passwd/group file entries in an associative array for faster
X lookups. This is particularly helpful on insecure systems using YP
X where password and group lookups are slow and you have to do a lot of
X them...:-)
X
X Can specify target (uid or gid) on command line.
X
X Can use -l option to generate PAT for a goal.
X
X Can use -f to preload file owner, group and mode info, which is
X helpful in speeding things up and in avoiding file system
X 'shadows'... See the man page for details.
X
XFuture plans, things to fix:
X
X- An earlier version scanned the password file looking for generally
X accessible accounts (no password), which would be added to the
X uids.known list (in addition to -1, "other"). I had planned on also
X adding a password checker which would allow us to also add accounts
X with easily guessed passwords. Eventually I nuked the code that
X scanned the password file to speed things up, and further reflection
X reveals that it isn't wise to add the password scanning to Kuang
X itself (since there are many other things that might be considered
X in determining whether an account is accessible or not, and you
X probably don't want to add them all to Kuang).
X
X At some point we should add a command line option that allows us to
X add additional uid's (or gid's?) to the uids.known list. That way
X the user could run some other tool to scan the password file and
X generate a list of accessible accounts, which could then be fed to
X kuang. Makes it faster on clients using YP since most of the
X password file is the same for all N clients, why scan it N times.
X This would make it easier for the Kuang user to do smarter things
X to/with the password file checks (list all accounts with no password
X or easily guessed password, filter out "ok" entries (eg, sync) and
X etc.)
X
X- This version doesn't deal with uid's and gid's correctly. If there
X are several entries that list the same UID, but with different
X names, directories and shells, we'll only check plans for becoming
X one of them, rather than any of them, so some possible plans aren't
X even examined.
X
X Hmmm...this is easier than I thought - when we evaluate some plan
X for granting a particular uid, we need to evaluate plans for all
X usernames that can become that uid. Just stick a loop in there
X somewhere...get CF's for each of username's in turn.
X
X Bah, harder than I thought, since it'd have to scan the whole
X password file to figure which username/home directories can become
X which uid's. Similarly with groups.
X
X Current plan: by default, kuang will have to scan the whole password
X and group files so it can be sure to get all possible ways to become
X some uid or gid. Internally, really need several lists:
X
X mapping from uid to list of usernames that have that uid
X mapping from a username to home directory, shell
X mapping from gid to list of uids that have access to that
X gid when they login (either member of group with that gid or
X given as login group in passwd file)
X mapping from gid to list of group names for that gid
X
X Course, this means that we have to read the whole password and group
X file, most of which will be common to many machines (like in a YP
X environment). We could preload the tables above from files created
X once, containing the brunt of the YP info, and then augment that
X with the local passwd and group info on each host when kuang is
X invoked, but then we need to correctly interpret funky YP things
X like +@netgroup:::*:..., which means that the uid has a name but no
X password here...and similarly with shell substitutions and so on.
X Bah.
X
X- In a large environment (like ours, 260+ machines, 30+ file systems
X on as many servers, 2000 password file entries served by YP) it
X would be nice to 'precompute' successful plans that would be common
X to all systems. In particular, plans for becoming most of the users
X with home directories on the NFS file systems would be useful, since
X we don't really want to recheck these on each host. You wouldn't
X want the plan to be too deep - probably shouldn't span more than 2
X uids (1 on each end: grant u.romig grant g.staff write ~foo/.login
X grant u.foo). I'm thinking that you could feed a list of these
X precomputed plans to kuang and add some code that causes it to
X splice in relevant plans where it can to short cut the planning
X steps. For example, if one of the plans in uids.next is something
X like "grant u.foo ...", and I have the precomputed plan mentioned
X above, I could splice the two: "grant u.romig grant g.staff write
X ~foo/.login grant u.foo ..." and skip all the normal steps that
X would've been taken to get there.
X
X I'm not sure this is even feasible or useful. Food for thought.
X
X- Hmmm...thinking about it, it seems like some of the steps are a bit
X too implicit...maybe the rules should be broken out a bit more.
X That will cost in processing time, though.
X
X- Would be really, really nice to be able to deal with PATH variables
X - location of ., who can write elements of path, etc. Basic rule is
X "anyone who can replace anything in any of path directories or the
X path directories themselves can become that PATH's user..." This
X can be really messy though - in our environment, the path for a user
X will depend on the architecture type of the machine that he is
X logged into, and to get the path, you'd have to read and interpret
X his .login (including variable assignments, source's and
X conditionals). Urf. One wonders whether it might be better to have
X something running as root that su's to each username in turn and
X gets the path that way...:-)
X
X- The kuang described in Baldwin's dissertation is somewhat different
X in nature from this one. The original computes a Privilege Access
X Table (PAT) which describes for each uid and gid which uids have
X access to that uid. To assess security, we compare this against the
X security policy for the site, which similarly describes which uid's
X are supposed to have access to each uid and gid. A sample SP might
X be that each uid should be accessible only by itself and root, and
X each gid should be accessible only to the members of that group and
X root. If the PAT listed additional uid's for some priv, that would
X constitute a violation of the Security Policy for the site.
X
X The current kuang is different. It registers Success (a problem was
X found) if it determines that some uid in the uids.known list (-1,
X "other" by default) can access the target privilege. It may find
X along the way that extra uids can access some uid, but these aren't
X reported as specific problems unless they are added to the
X uids.known list.
X
X We could do something similar to the kuang described in the paper by
X setting uids.known to be all the uids that aren't in the security
X policy table for the target uid, and running kuang against the
X target. This would report success for each uid that could access
X the target. You could do similar things with groups - uids.known
X would be all the uids that aren't members of the group...
X
X Alternately, we could simply have kuang record the list of uids that
X can access the target priv and print the list when its done. That
X way you could iterate kuang against all uids and gids and compare
X the resulting PAT against your security policy and record the
X differences. You'd probably want to record the plan for each uid
X reported also.
X
X On our system this would mean running kuang roughly 2500
X times to check 1 host, and we have about 300 hosts...urf...assuming
X that each kuang invocation has to check 50 plans, that's a total of
X 125,000 plans per host, or about an hour of real time...not as bad
X as it could be, though.
X
X- It would be nice to add to the list of rules. It would be especially
X nice to extract the rules from the code so that we can create site
X specific rule files (for example, we use X11r4 here, and many users
X have a .Xinitrc that contains shell commands that get executed when
X they login.)
X
X Easiest way to do this would be to extract the rules as Perl code so
X we can take advantage of conditionals and so on, and include them
X within the body of kuang somehow. A sample rule in perl:
X
X if (&shell($uid) eq "/bin/csh") {
X &addto("files", &home($uid)."/.login",
X "replace .login $plan");
X }
X
X which simply means "if the user's shell is csh, then try to replace
X his .login file."
X
SHAR_EOF
chmod 0600 README.perl ||
echo 'restore of README.perl failed'
Wc_c="`wc -c < 'README.perl'`"
test 9782 -eq "$Wc_c" ||
echo 'README.perl: original size 9782, current size' "$Wc_c"
fi
# ============= get-cf ==============
if test -f 'get-cf' -a X"$1" != X"-c"; then
echo 'x - skipping get-cf (File already exists)'
else
echo 'x - extracting get-cf (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'get-cf' &&
X#! /usr/local/bin/perl
X
X@dot_files = (
X ".login", ".logout", ".cshrc", # csh, cshe or tcsh
X ".profile", # ksh, sh
X ".env", # ksh
X ".alias", ".aliases", # common for all shells
X "user.ps", ".user.ps", "tools.ps", ".tools.ps",
X "startup.ps", ".startup.ps", # NeWS
X ".mgrc", # MGR
X ".X11init", ".awmrc", ".twmrc", ".xinitrc", # X11
X ".emacs" # emacs
X);
X
X%seen = {};
X
Xopen(HOST, "/bin/hostname |") || die "can't get the hostname";
Xchop($hostname=);
Xclose(HOST);
X
Xuser_loop:
X for (($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwent();
X $name ne "";
X ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = getpwent()) {
X
X #
X # If the user has a home directory on this server, get the info
X # about the directory, his CF's and so on.
X #
X if ($dir =~ m,^/n/$hostname/,) {
X if (! -d $dir) {
X printf(stderr "home directory '%s' for user '%s' doesn't exist.\n",
X $dir,
X $name);
X next user_loop;
X }
X
X ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
X $atime,$mtime,$ctime,$blksize,$blocks)
X = stat(_);
X $mode = $mode & 07777;
X
X &spit_it_out("d", $uid, $gid, $mode, $dir);
X
X foreach $file (@dot_files) {
X $path = "$dir/$file";
X
X if (-f $path) {
X ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
X $atime,$mtime,$ctime,$blksize,$blocks)
X = stat(_);
X $mode = $mode & 07777;
X
X &spit_it_out("f", $uid, $gid, $mode, $dir);
X }
X }
X }
X }
X
X
X
X
Xsub spit_it_out {
X local($type, $uid, $gid, $mode, $name) = @_;
X
X if (defined($seen{$name})) {
X return;
X }
X
X printf("%s %d %d 0%o %s\n", $type, $uid, $gid, $mode, $name);
X $seen{$name} = 1;
X}
X
SHAR_EOF
chmod 0700 get-cf ||
echo 'restore of get-cf failed'
Wc_c="`wc -c < 'get-cf'`"
test 1776 -eq "$Wc_c" ||
echo 'get-cf: original size 1776, current size' "$Wc_c"
fi
# ============= kuang.1 ==============
if test -f 'kuang.1' -a X"$1" != X"-c"; then
echo 'x - skipping kuang.1 (File already exists)'
else
echo 'x - extracting kuang.1 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'kuang.1' &&
X.TH KUANG 1 "4 October 1990"
X.SH NAME
Xkuang \- find security problems through rule based analysis
X.SH SYNOPSIS
X.B kuang
X.RB "[\|" \-v "\|]"
X.RB "[\|" \-d "\|]"
X.RB "[\|" \-l "\|]"
X.RB "[\|" \-D "\|]"
X.RB "[\|" \-f filedata "\|]"
X.RB "[\|"
X.IR u.username "\|]"
X.br
X.B kuang
X.RB "[\|" \-v "\|]"
X.RB "[\|" \-d "\|]"
X.RB "[\|" \-l "\|]"
X.RB "[\|" \-D "\|]"
X.RB "[\|" \-f filedata "\|]"
X.RB "[\|"
X.IR g.groupname "\|]"
X.br
X.SH DESCRIPTION
X.LP
X.B kuang
Xuses rule based analysis to examine the current security configuration
Xof a site and determine whether certain security problems exist.
X
X.B kuang
Xcontains embedded rules that describe the projection model and
Xsome of the attacker tricks used on Unix systems. It uses these rules
Xto reason backward from a desired goal (such as "grant u.root"),
Xgenerating potential "attack" plans from the rules and file system
Xstate and then evaluating them to see whether they are reachable
Xaccording to the state recorded in the password and group files and in
Xthe ownership and modes of the file systems.
X
XBy default,
X.B kuang
Xuses "grant u.root" as its initial goal. You can change that by
Xspecifying a username (u.username) or groupname (g.groupname) on the
Xcommand line. Normally
X.B kuang
Xdetermines a plan to be successful if it determines that anyone
X(u.other) can become the initial goal.
X
XThe
X.B \-v
Xoption causes
X.B kuang
Xto print a message about every plan added to the evaluation list.
XThis can help one to understand how
X.B kuang
Xworks. The
X.B \-d
Xoption causes
X.B kuang
Xto print a message when it evaluates a plan to determine whether to
Xretain it and add onto it or ignore it. These options will often
Xproduce lots of output, beware.
X
XNormally
X.B kuang
Xonly registers success when it finds that everyone on the system can
Xbecome the target uid or gid. With the
X.B \-l
Xoption,
X.B kuang
Xwill list every uid that can become the goal. This provides a more
Xcomplete picture of the state of security - you might deem it a
Xproblem if several users can become root, even if the rest cannot.
X
XOne might adopt the view that each uid should only be accessible by
Xitself and root, and that each gid should be accessible only by the
Xmembers of that group and root. One can then compare the expected
Xaccess list for a given uid or gid against the
X.B kuang
Xgenerated list to find security problems that
X.B kuang
Xwouldn't ordinarily tell you about.
X
XThe goals that
X.B kuang
Xuse seem cryptic, but are really pretty straightforward. Each goal
Xconsists of a list of