#! /bin/sh
#
#   secure_sun - check/fix fourteen common Sun security holes
#
#               Written by David Safford (saff@cssun.tamu.edu)
#		This program has been tested to handle most
#		common setups; if you find a configuration
#		that it does not handle, please let me know.
#		This version is specific to SunOS 4.0.3. 4.1
#

#   Introduction
clear
echo This program checks for 14 common SunOS configuration security loopholes.
echo It has been tested only on SunOS4.0.3 on  Sun4, Sun3, and Sun386i machines.
echo Each test reports its findings, and will offer to fix any problem found.
echo The program must be run as root if you want it to fix any of the problems,
echo but it can be run from any account if you reply \'n\' to any fix requests.
echo The 14 checks made are:
echo "   " 1. Fix ttytab to disable b -s problem
echo "   " 2. Check /etc/hosts.equiv either null or at least no +
echo "   " 3. Disable tftp \(nonserver\), or add secure switch \(server\)
echo "   " 4. Fix rcp hole
echo "   " 5. Check root\'s path for .
echo "   " 6. Check dirs in root\'s path not writeable by others
echo "   " 7. Check that /etc/passwd on ypserver does not have client line
echo "   " 8. Check that uucp decode alias is removed from /etc/aliases
echo "   " 9. Check /etc/utmp not world writeable
echo "   " 10. Check that rexd is disabled in /etc/inetd.conf
echo "   " 11. Disable login shell for uucp
echo "   " 12. Check for null /.rhosts
echo "   " 13. Check for accounts with no password
echo "   " 14. Check for backdoor root accounts
echo
echo -n press enter to continue
read YN
clear

#
#    1. check_boot - check for single user boot forced login
#
echo TEST 1: Checking for secure single user boot...
if grep -s "secure" /etc/ttytab
then
	echo -n "   "  ttytab is not secure: fix it \(y/n\)?
	read YN
	if test $YN = "y" 
	then
		ed - \/etc/ttytab <<- !
			g/secure/s/secure//
			w
			q
		!
		ed - \/.profile <<- !
			g/login root/d
			w
			q
		!
	fi
else
	echo "   "  "/etc/ttytab" is correct
fi
echo -n press enter to continue
read YN
clear
#
#    2. check_hosts.equiv - check for non-null or + /etc/hosts.equiv
#
echo TEST 2: Checking for non-null hosts.equiv ...
if test -s "/etc/hosts.equiv"
then
	cat /etc/hosts.equiv
	echo -n "   "  "/etc/hosts.equiv" is not null. Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		mv "/etc/hosts.equiv" "/etc/hosts.equiv.bak"
	else
		if grep -s "^+$" /etc/hosts.equiv
		then
			echo -n "   " hosts.equiv has a + line!!! Fix \(y/n\)?
			read YN
			if test $YN = "y"
			then
				ed - /etc/hosts.equiv <<- !
					g/^+$/d
					w
					q
				!
				
			fi
		fi
	fi
else
	echo "   "  "/etc/hosts.equiv" is correct.
fi
echo -n press enter to continue
read YN
clear
#
#	3. check_tftpd - check that tftpd is either disabled or secure
#
echo TEST 3: Checking /etc/inetd.conf for secure tftpd entry
if test -d /tftpboot
then
	if grep -s "in.tftpd -s" /etc/inetd.conf
	then
		echo "   " secure for server
	else
		echo -n "   "  Tftp not secure for server. Fix \(y/n\)?
		read YN
		if test $YN = "y"
		then
			ed - /etc/inetd.conf <<- !
				g/^tftp/s/in\.tftpd$/in.tftpd -s tftpboot/
				w
				q
			!
		fi
	fi
else
	if grep -s "^#tftp" /etc/inetd.conf
	then
		echo "   " secure nonserver
	else
		echo -n "   "  Tftp not secure for nonserver. Fix \(y/n\)?
		read YN
		if test $YN = "y"
		then
			ed - /etc/inetd.conf <<- !
				g/^tftp/s/tftp/#tftp/
				w
				q
			!
		fi
	fi
fi
echo -n press enter to continue
read YN
clear
#
#  4. check rcp - ensure rcp hole disabled
#
echo Test 4: checking that rcp hole disabled
echo "   " Testing /etc/passwd
if grep "^nobody:\*:-2" /etc/passwd |grep -s ':$'
then
	echo -n "   "  rcp hole not disabled. Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		ed - /etc/passwd <<- !
		/^nobody/s/-2:-2::\/:/32767:32767:disable:\/disable:\/disable/
		w
		q
		!
	fi
else
	echo "   " rcp hole disabled in passwd
fi
if test -s /etc/yppasswd
then
echo "   " Testing /etc/yppasswd
if grep "^nobody:\*:-2" /etc/yppasswd |grep -s ':$'
then
	echo -n "   "  rcp hole not disabled. Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		ed - /etc/yppasswd <<- !
		/^nobody/s/-2:-2::\/:/32767:32767:disable:\/disable:\/disable/
		w
		q
		!
	fi
else
	echo "   " rcp hole disabled in yppasswd
fi
fi
echo -n press enter to continue
read YN
clear
#
#    5. check_path - check root's path for .
#
echo TEST 5: Checking root\'s path for "." ...
if grep -i -s "path[^\.]*\." /.login
then
	echo -n "   "  "/.login" path contains "." Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		if grep -s " path" /.login
		then
			ed - "/.login" <<- !
				/ path/
				s/\.//
				w
				q
			!
		elif grep -s "PATH" /.login
		then
			ed - "/.login" <<- !
				/PATH/
				s/\.//
				w
				q
			!
		fi
	fi
else
	echo "   "  "/.login" path is correct
fi
if grep -i -s "path[^\.]*\." /.cshrc
then
	echo -n "   "  "/.cshrc" path contains "." Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		if grep -s " path" /.cshrc
		then
			ed - "/.cshrc" <<- !
				/ path/
				s/\.//
				w
				q
			!
		elif grep -s "PATH" /.cshrc
		then
			ed - "/.cshrc" <<- !
				/PATH/
				s/\.//
				w
				q
			!
		fi
	fi
else
	echo "   "  "/.cshrc" path is correct
fi
if grep -i -s "path[^\.]*\." /.profile
then
	echo -n "   "  "/.profile" path contains "." Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		if grep -s " path" /.profile
		then
			ed - "/.profile" <<- !
				/ path/
				s/\.//
				w
				q
			!
		elif grep -s "PATH" /.profile
		then
			ed - "/.profile" <<- !
				/PATH/
				s/\.//
				w
				q
			!
		fi
	fi
else
	echo "   "  "/.profile" path is correct
fi
echo -n press enter to continue
read YN
clear
#
#    6. check_write - check directories in roots path for writeability
#
echo TEST 6: Checking your path for user writeable directories...
IFS=:
for DIR in $PATH
do
	if test -d $DIR
	then
		cd $DIR
		if ls -dl . | grep -s "^........w"  
		then
			echo -n "   "  $DIR is writeable by world. FIX \(y/n\)?
			read YN
			if test $YN = "y"
			then
				chmod o-w .
			fi
		else
			echo "   "  $DIR is not writable by world.
		fi
		if ls -dl . | grep -s "^.....w"  
		then
			echo -n "   "  $DIR is writeable by group. FIX \(y/n\)?
			read YN
			if test $YN = "y"
			then
				chmod g-w .
			fi
		else
			echo "   "  $DIR is not writeable by group.
		fi
	else
		echo "   "  $DIR is not a directory!
	fi
done
echo -n press enter to continue
read YN
clear
#
#    7. check_ypserv - check passwd file for ypclient line on ypserver
#
echo The following test may be incompatible on the Sun 386i series.
echo It is probably safest to reply \'n\' if it reports a problem on a 386i.
echo TEST 7: Checking YP entries in /etc/passwd...
if ps -ax|grep ypserv|grep -s -v grep
then
	if grep -s "+::0:0:" /etc/passwd
	then
		echo "   " This machine is a ypserver, and has the ypclient
		echo -n "   " line in /etc/passwd. Fix \(y/n\)?
		read YN
		if test $YN = "y"
		then
			ed - /etc/passwd <<- !
				g/^+::0:0:/d
				w
				q
			!
		fi
	else
		echo "   " YP password entries correct.
	fi
else
	echo "   " YP password entries correct.
fi
echo -n press enter to continue
read YN
clear
#
#   8. check_/etc/aliases for decode alias, and remove
#
echo Test 8: checking that decode alias is removed
if grep -s "^decode" /etc/aliases
then
	echo -n "   "  decode not disabled. Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		ed - /etc/aliases <<- !
			g/^decode/d
			w
			q
		!
	fi
else
	echo "   " decode disabled
fi
echo -n press enter to continue
read YN
clear

#
#   9. check_/etc/utmp - if world writeable, fix
#
echo NOTE: the following fix will interefere with normal use of sunview.
echo       Apply this fix only on a server, or give all valid users
echo       group write access to /etc/utmp.
echo
echo Test 9: testing that /etc/utmp not writeable by world 
if ls -l /etc/utmp |grep -s "^........w"
then
	echo -n "   "  utmp writeable. Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		chmod o-w /etc/utmp
	fi
else
	echo "   " utmp correct.
fi
echo -n press enter to continue
read YN
clear

#
#  10. check_rexd - ensure rexd disabled in /etc/inetd.conf
#
echo Test 10: checking that rexd is disabled
if grep -s "^#rexd" /etc/inetd.conf
then
	echo "   " rexd disabled
else
	echo -n "   "  rexd not disabled. Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		ed - /etc/inetd.conf <<- !
			g/^rexd/s/rexd/#rexd/
			w
			q
		!
	fi
fi
echo -n press enter to continue
read YN
clear

#
#  11. check_uucp - ensure uucp login shell disabled
#
echo Test 11: checking that uucp login shell is disabled
echo "   " Testing /etc/passwd
if grep "^uucp" /etc/passwd |grep -s ':$'
then
	echo -n "   "  uucp login shell not disabled. Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		ed - /etc/passwd <<- !
			/^uucp
			a
			/disabled
			.
			/^uucp
			j
			w
			q
		!
	fi
else
	echo "   " uucp login shell disabled
fi
if test -s /etc/yppasswd
then
echo "   " Testing /etc/yppasswd
if grep "^uucp" /etc/yppasswd |grep -s ':$'
then
	echo -n "   "  uucp login shell not disabled. Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		ed - /etc/yppasswd <<- !
			/^uucp
			a
			/disabled
			.
			/^uucp
			j
			w
			q
		!
	fi
else
	echo "   " uucp login shell disabled
fi
fi
echo -n press enter to continue
read YN
clear
#
#   12. check_rhosts - check for non-null /.rhosts
#
echo TEST 12: Checking for non-null root .rhosts...
if test -s "/.rhosts"
then
	cat /.rhosts
	echo -n "   "  "/.rhosts" is not null. Fix \(y/n\)?
	read YN
	if test $YN = "y"
	then
		mv "/.rhosts" "/.rhosts.bak"
	else
		if grep -s "^+$" /.rhosts
		then
			echo -n "   " /.rhosts has a + line!!! Fix \(y/n\)?
			read YN
			if test $YN = "y"
			then
				ed - /.rhosts <<- !
					g/^+$/d
					w
					q
				!
				
			fi
		fi
	fi
else
	echo "   "  "/.rhosts" is correct.
fi
echo -n press enter to continue
read YN
clear
#
#    13. check_nopasswd - check that all accounts have passwords
#		      (except sync, which should have no password)
#
echo TEST 13: Checking accounts for passwords...
echo "   " Checking /etc/passwd
if grep "^[^:]*::" /etc/passwd |egrep -v '(sync:|ftp:|\+:)'
then
	echo -n "   "  The above are accounts with no password. Lock \(y/n\)?
	read YN
	if test $YN = "y"
	then
		ed - /etc/passwd <<- !
			g/^[^:]*::/s/::/:*:/
			g/^sync:*:/s/:\*:/::/
			w
			g/^+:/s/:\*/:/
			w
			g/^ftp:/s/:\*/:/
			w
			q
		!
	fi
else
	echo "   "  All accounts have passwords
fi
if test -s /etc/yppasswd
then
echo "   " Checking /etc/yppasswd
if grep "^[^:]*::" /etc/yppasswd |egrep -v '(sync:|ftp:|\+:)'
then
	echo -n "   "  The above are accounts with no password. Lock \(y/n\)?
	read YN
	if test $YN = "y"
	then
		ed - /etc/yppasswd <<- !
			g/^[^:]*::/s/::/:*:/
			g/^sync:*:/s/:\*:/::/
			w
			g/^+:/s/:\*/:/
			w
			g/^ftp:/s/:\*/:/
			w
			q
		!
	fi
else
	echo "   "  All accounts have passwords
fi
fi
echo -n press enter to continue
read YN
clear
#
#   14. check_backdoor - check passwd file for users with 0 pid
#		     (except root and sysdiag which must be 0)
#
echo TEST 14: Checking for backdoor accounts...
echo "   " Checking /etc/passwd
if grep  "^[^:]*:[^:]*:0:" /etc/passwd |egrep -v '(root:|sysdiag:|\+:)'
then
	echo -n "   "  The above are accounts with root id. Lock \(y/n\)?
	read YN
	if test $YN = "y"
	then
		ed - /etc/passwd <<- !
			g/^[^:]*:[^:]*:0:/s/:/:*/
			g/^root:/s/:\*/:/
			g/^sysdiag:/s/:\*/:/
			w
			g/^+:/s/:\*/:/
			w
			q
		!
	fi
else
	echo "   "  There are no back door accounts.
fi
if test -s /etc/yppasswd
then
echo "   " Checking /etc/yppasswd
if grep  "^[^:]*:[^:]*:0:" /etc/yppasswd |egrep -v '(root:|sysdiag:|\+:)'
then
	echo -n "   "  The above are accounts with root id. Lock \(y/n\)?
	read YN
	if test $YN = "y"
	then
		ed - /etc/yppasswd <<- !
			g/^[^:]*:[^:]*:0:/s/:/:*/
			g/^root:/s/:\*/:/
			g/^sysdiag:/s/:\*/:/
			w
			g/^+:/s/:\*/:/
			w
			q
		!
	fi
else
	echo "   "  There are no back door accounts.
fi
fi
echo If any fixes were made, and this machine is a ypserver, be sure
echo to run ypmake \(cd /var/yp\;make\)