[comp.sources.unix] v22i106: System security analysis tool, patch1

rsalz@uunet.uu.net (Rich Salz) (06/08/90)

Submitted-by: Dan Farmer <df@cert.sei.cmu.edu>
Posting-number: Volume 22, Issue 106
Archive-name: cops.pch
Patch-To: volume21/cops


Here's the first patch for COPS.  Pretty minor stuff on the whole, but I'd
appreciate it if you would get it out to the world for me.  This one fixes
some bugs and minor doc stuff; I'll be putting out another patch later
this year that should add features and all that good stuff (hopefully it
won't be repairing problems with this patch :-)).

 thanks,

  -- dan

---------------  Cut here for patch -------------------------

Patch #: 1
Priority: MEDIUM

  This is the first patch for COPS.  This shar file includes three files; the
original csh version of kuang (actually, another shar file), a patch file,
and a "patchlevel.h" file.

o  The csh version of kuang was meant to be included in the original release,
 but somehow got lost along the way.  It should be functionally equivalent to
 the version I ported to bourne shell for wider portability, but is a little
 cleaner design, since I had to do some strange things to get it to work in
 bourne.
o  Perhaps the biggest problem was with the password guessing program; turned
 out there was a bug that someone added while adding features through the
 years (it was originally written in 1983, and the bug was not in the original
 version, looking at my archives.)  The problem was that once a dictionary
 passwd was guessed, a variable wasn't reset.  The original author also added
 some comments about the design and intent of the program.
o  /bin/rm -f in rc* files (pretty common stuff) are now ignored.
o  findsuid now uses "ls -ldga" instead of "ls -lga" to find files.
o  A couple of error messages and docs were slightly changed, and a couple
   of miscellaneous "'"'s were added to improve robustness; minor nits.


  Enjoy!  If you have any problems, drop me a line at:

 df@sei.cmu.edu
   or
 (412) 268 7197


  P.S.  To apply the patch, merely type:

  patch < cops.patch.1

     If you don't have the patch program, apply the patch by hand,
     or get patch (I highly recommend it -- great program!  It can
     be gotten from uunet.uu.net, via anonymous ftp)

     After patching, type "make", and all should be well again....

  The original COPS toolkit (as well as the "patch" program) can be gotten
via anonymous ftp from uunet.uu.net (192.48.96.2), or wherever fine software
is archived :-)

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

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  cops.patch.1 kuang.orig patchlevel.h
#
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'cops.patch.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cops.patch.1'\"
else
echo shar: Extracting \"'cops.patch.1'\" \(6595 characters\)
sed "s/^X//" >'cops.patch.1' <<'END_OF_FILE'
XIndex: MANIFEST
X17a18
X> kuang.orig
X
XIndex: README
X123c123
X<    -- Next, change lines 36 and 37 in the "cops" shell file from:
X---
X>    -- Next, change lines 37 and 38 in the "cops" shell file from:
X129c129
X<    -- Set "MAIL=NO" in the "cops" shell file (line 22).  This will prevent
X---
X>    -- Set "MAIL=NO" in the "cops" shell file (line 23).  This will prevent
X140c140
X<    -- You may wish to comment out the password checker (line 72 in the
X---
X>    -- You may wish to comment out the password checker (line 73 in the
X187c187
X< groups in their respective target lines (below lines 21 and 27,
X---
X> groups in their respective target lines (below lines 20 and 27,
X
XIndex: XTRA_CREDIT
X9,10c9,10
X< Craig Leres, Seth Alford, Roger Southwick, Steve Dum, and Rick Lindsley
X< all get credit for the password guessing program.
X---
X> Craig Leres, Jef Poskanzer, Seth Alford, Roger Southwick, Steve Dum,
X> and Rick Lindsley all get credit for the password guessing program.
X24c24,28
X< implementation ideas at LISA II.
X---
X> implementation ideas at LISA III.
X> 
X>   In round II (the first patch), Mark Plumbly fixed rc.chk so it would
X> work like I said it would, as well as pointing out a few problems with
X> the password guesser.
X
XIndex: group.chk
X75,76c75,77
X< 		if ("'$C2'" != "TRUE")
X< 			printf("Warning!  Group file, line %d, group has password: %s\n", NR, $0)
X---
X> 		if ("'$C2'" != "TRUE") {
X> 			if (length($2) == 13)
X> 				printf("Warning!  Group file, line %d, group has password: %s\n", NR, $0) }
X127c128,129
X< 		printf("Warning!  YGroup file, line %d, group has password: %s\n", NR, $0) } \
X---
X> 		if (if (length($2) == 13))
X> 			printf("Warning!  YGroup file, line %d, group has password: %s\n", NR, $0) } \
X
XIndex: kuang
X0a1
X> #!/bin/sh
XOnly in cops.src: kuang.orig
X
XIndex: makefile
X28a29
X> RM=/bin/rm
X32a34,36
X> 
X> clean:
X> 	$(RM) $(EXECUTABLE)
X
XIndex: passwd.chk
X88,89c88,92
X< 	if ($3 !~ /[0-9]/) {
X< 		printf("Warning!  Password file, line %d, nonnumeric user id: \n\t%s\n", NR, $0) } \
X---
X> 	if ($3 !~ /^[0-9]/) {
X> 		if ($3 < 0) {
X> 			printf("Warning!  Password file, line %d, negative user id: \n\t%s\n", NR, $0) } \
X> 		else {
X> 		printf("Warning!  Password file, line %d, nonnumeric user id: \n\t%s\n", NR, $0) }} \
X117,118c120,124
X< 		if ($3 !~ /[0-9]/ && $3 != "-2") {
X< 			printf("Warning!  YPassword file, line %d, nonnumeric user id: \n\t%s\n", NR, $0) } \
X---
X> 		if ($3 !~ /^[0-9]/) {
X> 			if ($3 < 0) {
X> 			printf("Warning!  YPassword file, line %d, negative user id: \n\t%s\n", NR, $0) } \
X> 			else {
X> 			printf("Warning!  YPassword file, line %d, nonnumeric user id: \n\t%s\n", NR, $0) }} \
X121c127
X< 		if ($4 !~ /[0-9]/ && $4 != "-2") {
X---
X> 		if ($4 !~ /[0-9]/) {
XOnly in cops.src: patch.1
X
XIndex: rc.chk
X21a22,27
X> # 12 Apr 90, Mark Plumbly made it ignore lines starting with rm -f
X> # (popular in rc files) and fixed my code so it would ignore everything
X> # after a ">".
X> #
X> SED=/bin/sed
X> CAT=/bin/cat
X43d48
X< #
X46c51,70
X< first_pass=`$AWK '{for (i=1;i<=NF;i++) if ((index($i,"/")) && ((first=substr($i,1,1)!=">"))&& first!="#" && first!="$" && (last=substr($i,length($i),1))!="\"") print $i}' $init_files | $EGREP -v "/dev/.*ty|/tmp|/usr/tmp|/dev/null" | $SORT -u`
X---
X> #
X> # 12 Apr mdp: 	Modified to remove "> file" as well as ">file"
X> #		and remove "rm -f file" (this removes a few bogus ones).
X> #		(i.e. things which are written to or removed only are ignored).
X> #
X> first_pass=`${CAT} ${init_files} 	|				\
X> ${SED} -e 's/ *#.*$//'			|				\
X> $AWK '
X> {									\
X>   for (i=1;i<=NF;i++) {							\
X>     if 	((index($i,"/")) &&						\
X> 	((first=substr($i,1,1)!=">")) &&				\
X> 	$(i-1)!=">" && 							\
X> 	( i<=2 || $(i-2)!="rm" || $(i-1)!="-f" ) &&			\
X> 	first!="#" &&							\
X> 	first!="$" &&							\
X> 	(last=substr($i,length($i),1))!="\"")				\
X> 	print $i							\
X>     }									\
X> }' | $EGREP -v "/dev/.*ty|/tmp|/usr/tmp|/dev/null" | $SORT -u`
X
XIndex: root.chk
X71c71
X< 	if test ! `$GREP "root" $ftp`
X---
X> 	if $TEST ! "`$GREP "root" $ftp`"
X91c91
X< $GREP path $csh | $AWK '{split($0,p1,"="); \
X---
X> $GREP path $csh | $SED 's/#.*$//' | $AWK '{split($0,p1,"="); \
X105c105
X< $GREP PATH $sh | $SED 's/\(PATH=.*\);.*/\1/' |
X---
X> $GREP PATH $sh | $SED 's/#.*$//' | $SED 's/\(PATH=.*\);.*/\1/' |
X118c118
X< 		$ECHO "Warning!  \".\" is in roots path!"
X---
X> 		$ECHO "Warning!  \".\" (or current directory) is in roots path!"
X123c123
X< 		$ECHO "Warning!  Directory $i is _World_ writable!"
X---
X> 		$ECHO "Warning!  Directory $i is _World_ writable and in roots path!"
X
XIndex: suid.chk
X37c37
X< SEARCH=.
X---
X> SEARCH=/
X58c58
X< $FIND $SEARCH \( -perm -4000 -o -perm -2000 \) -exec $LS -lga {} \; | \
X---
X> $FIND $SEARCH \( -perm -4000 -o -perm -2000 \) -exec $LS -ldga {} \; | \
X
XIndex: docs/warnings
X50c50
X< 1)
X---
X> 0)
X61c61
X< 2)
X---
X> 1)
X80c80
X< 3)
X---
X> 2)
X93a94,101
X> 3)
X> Directory foo_dir is _World_ writable and in roots path!
X> 
X>    This is the same as (2), but the directory was found to be in the
X> path variable set either in /.login or /.profile.  This is a bad thing
X> because if it is writable, a trojan horse can be placed there, and
X> root will execute the command.  See also (23).
X> 
X198a207,214
X> Password file, line xyz, negative user id: foo
X> 
X>    A user id is negative.  This is most common with user name "nobody",
X> and with an id of "-2".  This can be dangerous, especially if you are running
X> a Sun, with 4.xx SunOS.  It is uncertain if it is dangerous for other
X> versions or machines.  Changing it to 32767 is the usual course of action.
X> 
X> 19)
X204c220
X< 19)
X---
X> 20)
X206c222,223
X<    To fix, delete all blank lines.
X---
X>    To fix, delete all blank lines.  This can be very bad, because a blank
X> line can give a uid=0 account with no password.
X208c225
X< 20)
X---
X> 21)
X214c231
X< 21)
X---
X> 22)
X220,221c237,238
X< 22)
X< "." is in roots path!
X---
X> 23)
X> "." (or current directory) is in roots path!
X229c246
X< 23)
X---
X> 24)
X238c255
X< 24)
X---
X> 25)
X
XIndex: src/pass.c
X15a16,27
X> 
X> 	Insecure is something that Jef Poskanzer and I wrote to rid a
X> 	local system of an overly persistent ankle-biting adolescent.
X> 	It was a quick hack we whipped up in just a few minutes and was
X> 	never intended to be publically distributed. Unfortunately, I
X> 	made the mistake of giving a copy to an associate at UC
X> 	Berkeley. Apparently, he incorporated it in a security package
X> 	he later developed for use at Berkeley. Someone else
X> 	distributed it outside Berkeley which explains why it's been
X> 	publically distributed.
X> 
X> 
X226c238
X< #define ARB_CONST	80
X---
X> #define ARB_CONST	1024
X275a288,289
X> 
X>         done = 0;
X
END_OF_FILE
if test 6595 -ne `wc -c <'cops.patch.1'`; then
    echo shar: \"'cops.patch.1'\" unpacked with wrong size!
fi
# end of 'cops.patch.1'
fi
if test -f 'kuang.orig' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kuang.orig'\"
else
echo shar: Extracting \"'kuang.orig'\" \(7758 characters\)
sed "s/^X//" >'kuang.orig' <<'END_OF_FILE'
X#! /bin/sh
X# This is a shell archive.  Remove anything before this line, then unpack
X# it by saving it into a file and typing "sh file".  To overwrite existing
X# files, type "sh file -c".  You can also feed this as standard input via
X# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
X# will see the following message at the end:
X#		"End of shell archive."
X# Contents:  dofiles dogids douids init_kuang kuang.csh
X#
XPATH=/bin:/usr/bin:/usr/ucb ; export PATH
Xif test -f 'dofiles' -a "${1}" != "-c" ; then 
X  echo shar: Will not clobber existing file \"'dofiles'\"
Xelse
Xecho shar: Extracting \"'dofiles'\" \(1564 characters\)
Xsed "s/^X//" >'dofiles' <<'END_OF_FILE'
XX# /* Copyright 1985 Robert W. Baldwin */
XX# /* Copyright 1986 Robert W. Baldwin */
XXset notice85="Copyright 1985 Robert W. Baldwin"
XXset notice86="Copyright 1986 Robert W. Baldwin"
XX
XX#
XX# A list of file names is read from successive lines of stdin.
XX# Each file is examined for ways to access it.
XX# The input format is:
XX#    <filename> <whitespace> <mode> <comments>
XX# The <mode> is either "write" or "replace".
XX#
XXecho Called dofiles.						#>/dev/tty
XXwhile ( 1 )
XX	set nextfile = ( `echo $<` )
XX	if ( $#nextfile == 0 )  break;
XX#
XX	set file = $nextfile[1]
XX	set mode = $nextfile[2]
XX	echo "    File $file, mode $mode"			#>/dev/tty
XX#
XX# Rules converting filename goals into UserName or GroupName goals.
XX#
XX	set writers = ( `filewriters $file` )
XX	if ( $#writers == 3 ) then
XX		set owner = $writers[1]
XX		set group = $writers[2]
XX		set other = $writers[3]
XX		echo "        Writers are $owner $group $other"	#>/dev/tty
XX		addto uids $owner $mode $file $nextfile[3-]
XX		if ( $group != "NONE" ) then
XX			addto gids $group $mode $file $nextfile[3-]
XX		endif
XX		if ( $other != "NONE" ) then
XX			addto uids $other $mode $file $nextfile[3-]
XX		endif
XX	else
XX		echo "        $file does not exist"		#>/dev/tty
XX		continue
XX	endif
XX#
XX# Rules converting filename goals into other filename goals.
XX#
XX	if ($mode != "replace" ) then
XX		continue
XX	endif
XX#
XX	set parent = "$file:h"
XX	set basename = "$file:t"
XX#	echo -n "       " Parent directory is $parent		#>/dev/tty
XX#	echo ", " basename is $basename				#>/dev/tty
XX	if ( "$parent" != "" ) then
XX		addto files $parent write replace $basename $nextfile[3-]
XX	endif
XXend
XX
XEND_OF_FILE
Xif test 1564 -ne `wc -c <'dofiles'`; then
X    echo shar: \"'dofiles'\" unpacked with wrong size!
Xfi
X# end of 'dofiles'
Xfi
Xif test -f 'dogids' -a "${1}" != "-c" ; then 
X  echo shar: Will not clobber existing file \"'dogids'\"
Xelse
Xecho shar: Extracting \"'dogids'\" \(668 characters\)
Xsed "s/^X//" >'dogids' <<'END_OF_FILE'
XX# /* Copyright 1985 Robert W. Baldwin */
XX# /* Copyright 1986 Robert W. Baldwin */
XXset notice85="Copyright 1985 Robert W. Baldwin"
XXset notice86="Copyright 1986 Robert W. Baldwin"
XX
XX#
XX# Process a list of gids from stdin.
XX# Usage: dogids
XX#    Input format is:
XX#	GroupName Comments
XX#
XXecho Called dogids						#>/dev/tty
XXwhile ( 1 )
XX	set nextgid = ( `echo $<` )
XX	if ( $#nextgid == 0 )  break;
XX	set group = $nextgid[1]
XX	echo "   " Group $group					#>/dev/tty
XX#
XX# Rules mapping gids to uids.
XX#
XX	foreach user ( `members $group` )
XX		addto uids $user grant $group $nextgid[2-]
XX	end
XX#
XX# Rules mapping gids to files.
XX#
XX	addto files /etc/group replace grant $group $nextgid[2-]
XXend
XX
XEND_OF_FILE
Xif test 668 -ne `wc -c <'dogids'`; then
X    echo shar: \"'dogids'\" unpacked with wrong size!
Xfi
X# end of 'dogids'
Xfi
Xif test -f 'douids' -a "${1}" != "-c" ; then 
X  echo shar: Will not clobber existing file \"'douids'\"
Xelse
Xecho shar: Extracting \"'douids'\" \(1539 characters\)
Xsed "s/^X//" >'douids' <<'END_OF_FILE'
XX# /* Copyright 1985 Robert W. Baldwin */
XX# /* Copyright 1986 Robert W. Baldwin */
XXset notice85="Copyright 1985 Robert W. Baldwin"
XXset notice86="Copyright 1986 Robert W. Baldwin"
XX
XX#
XX# Process a list of uids from stdin.
XX# Usage: douids username comments
XX#
XXecho Called douids						#>/dev/tty
XXwhile ( 1 )
XX	set nextuid = ( `echo $<` )
XX	if ( $#nextuid == 0 )  break;
XX	set user = $nextuid[1]
XX	echo "   " User $user					#>/dev/tty
XX#
XX# Rules mapping uids to other uids.
XX#
XX
XX#
XX# Rules mapping uids to files.
XX#
XX	addto files /etc/passwd replace grant $user $nextuid[2-]
XX	addto files /usr/lib/aliases replace trojan $user $nextuid[2-]
XX
XX	if ( -e ~${user}/.rhosts )  then
XX		addto files ~${user}/.rhosts write grant $user $nextuid[2-]
XX	endif
XX
XX	if (-e ~${user}/.login)  then
XX		addto files ~${user}/.login replace trojan $user $nextuid[2-]
XX	endif
XX
XX	if (-e ~${user}/.cshrc)  then
XX		addto files ~${user}/.cshrc replace trojan $user $nextuid[2-]
XX	endif
XX
XX	if (-e ~${user}/.profile)  then
XX		addto files ~${user}/.profile replace trojan $user $nextuid[2-]
XX	endif
XX
XX	if (${user} == "root")  then
XX		addto files /usr/lib/crontab replace create supershell\
XX				$nextuid[2-]
XX		addto files /etc/rc replace trojan $user $nextuid[2-]
XX		addto files /etc/rc.local replace trojan $user $nextuid[2-]
XX	endif
XX
XX	if (${user} != "root")  then
XX		addto files /etc/hosts.equiv replace allow rlogin $nextuid[2-]
XX	endif
XX
XX	if ((${user} != "root") && (-e /etc/hosts.equiv) && \
XX	    !(-z /etc/hosts.equiv))  then
XX		addto files /etc/hosts replace fake HostAddress $nextuid[2-]
XX	endif
XX
XXend
XX
XEND_OF_FILE
Xif test 1539 -ne `wc -c <'douids'`; then
X    echo shar: \"'douids'\" unpacked with wrong size!
Xfi
X# end of 'douids'
Xfi
Xif test -f 'init_kuang' -a "${1}" != "-c" ; then 
X  echo shar: Will not clobber existing file \"'init_kuang'\"
Xelse
Xecho shar: Extracting \"'init_kuang'\" \(836 characters\)
Xsed "s/^X//" >'init_kuang' <<'END_OF_FILE'
XX# /* Copyright 1985 Robert W. Baldwin */
XX# /* Copyright 1986 Robert W. Baldwin */
XXset notice85="Copyright 1985 Robert W. Baldwin"
XXset notice86="Copyright 1986 Robert W. Baldwin"
XX
XX###############################################
XX# Kuang: Rule based computer security checker.
XX###############################################
XX#
XX#
XX# Initialization.
XX#
XXclearfiles
XX#
XX# First setup what we have access to.
XX# The uids.k file must include the user 'OTHER' meaning the world access bits.
XX# Add any other UIDs accessible to the attacker (e.g., ftp, daemon).
XX#
XX# Directly accessible user IDs.
XXcat >uids.k <<END
XXOTHER
XXEND
XX#
XX# Directly accessible group IDs.
XX# This usually includes a group like 'users', which most users are in.
XX#
XXcat >gids.k <<END
XXEND
XX#
XX# Setup the primary goal(s).
XX#
XXecho Setting up goal						#>/dev/tty
XXaddto uids root DO ANYTHING
XX
XEND_OF_FILE
Xif test 836 -ne `wc -c <'init_kuang'`; then
X    echo shar: \"'init_kuang'\" unpacked with wrong size!
Xfi
X# end of 'init_kuang'
Xfi
Xif test -f 'kuang.csh' -a "${1}" != "-c" ; then 
X  echo shar: Will not clobber existing file \"'kuang.csh'\"
Xelse
Xecho shar: Extracting \"'kuang.csh'\" \(704 characters\)
Xsed "s/^X//" >'kuang.csh' <<'END_OF_FILE'
XX# /* Copyright 1985 Robert W. Baldwin */
XX# /* Copyright 1986 Robert W. Baldwin */
XXset notice85="Copyright 1985 Robert W. Baldwin"
XXset notice86="Copyright 1986 Robert W. Baldwin"
XX
XX###############################################
XX# Kuang: Rule based computer security checker.
XX###############################################
XX#
XX#
XX# Initialization.
XX#
XXcsh -f init_kuang
XX#
XX# Main loop
XX#
XXecho Starting main loop						#>/dev/tty
XXwhile ( -e uids.n || -e gids.n || -e files.n )
XX	if ( -e uids.n ) then
XX		mv uids.n uids.x
XX		csh -f douids < uids.x
XX		endif
XX	if ( -e gids.n ) then
XX		mv gids.n gids.x
XX		csh -f dogids < gids.x
XX		endif
XX
XX	if ( -e files.n ) then
XX		mv files.n files.x
XX		csh -f dofiles < files.x
XX		endif
XX	end
XX
XEND_OF_FILE
Xif test 704 -ne `wc -c <'kuang.csh'`; then
X    echo shar: \"'kuang.csh'\" unpacked with wrong size!
Xfi
X# end of 'kuang.csh'
Xfi
Xecho shar: End of shell archive.
Xexit 0
END_OF_FILE
if test 7758 -ne `wc -c <'kuang.orig'`; then
    echo shar: \"'kuang.orig'\" unpacked with wrong size!
fi
# end of 'kuang.orig'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(21 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X#define PATCHLEVEL 1
END_OF_FILE
if test 21 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
echo shar: End of shell archive.
exit 0

exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.