If I had brains, I'd be a fuckin' menace.
[unix-history] / usr / src / etc / security
CommitLineData
525ea79f
KB
1#!/bin/sh -
2#
07576f30 3# @(#)security 5.15 (Berkeley) %G%
525ea79f 4#
07576f30
KB
5
6# Script to check basic system security. Checks included are:
7# Users with uid's of 0.
8# Users without passwords.
9# Accounts that have been turned off, but still have valid shells.
10# Special users that have .rhosts files.
11# Home directory and dot-file ownership and permissions.
12# Mailbox ownership and permissions.
13# File list from /etc/mtree/flist.secure.
14# Dot appearing in root user's path.
15# NFS file systems globally exported to the world.
16# Changes in setuid and device files.
17# Block and character disk device ownership and permissions.
18# System binaries as described by files in /etc/mtree.
19
fd70cf43 20PATH=/sbin:/usr/sbin:/bin:/usr/bin
525ea79f 21
383148a3
KB
22umask 22
23
40835542
KB
24ERR=/tmp/_secure1.$$
25TMP1=/tmp/_secure2.$$
26TMP2=/tmp/_secure3.$$
27LIST=/tmp/_secure4.$$
fd70cf43 28
48e0a733 29trap 'rm -f $ERR $TMP1 $TMP2 $LIST' 0
fd70cf43 30
07576f30 31# Check uids. Only root and toor should have a uid of 0.
8e55538e
KB
32echo ""
33echo "Checking for uids of 0:"
07576f30 34awk -F: "\$3 == 0 && \$1 != \"root\" && \$1 != \"toor\" \
48e0a733 35 { print \"user \" \$1 \" has a uid of \" \$3 }" /etc/master.passwd
8e55538e 36
07576f30 37# Check for missing passwords.
8e55538e
KB
38echo ""
39echo "Checking for uids without passwords:"
48e0a733
KB
40awk -F: "\$2 == \"\" \
41 { print \"user \" \$1 \" has no password\" }" /etc/master.passwd
42
07576f30 43# If the account is turned off, the shell should be invalid.
48e0a733
KB
44echo ""
45echo "Checking for turned-off accounts with valid shells:"
07576f30 46awk -F: "length(\$2) != 13 && (\$10 ~ /.*sh$/ || \$10 == \"\") \
48e0a733
KB
47 { print \"user \" \$1 \" account turned off with valid shell.\" }" \
48 /etc/master.passwd
49
07576f30
KB
50# Check for special users with .rhosts files. Only root and toor should
51# have a .rhosts files.
48e0a733
KB
52echo ""
53echo "Checking for special users with .rhosts files."
07576f30
KB
54awk -F: "\$1 != \"root\" && \$1 != \"toor\" && \
55 (\$3 < 100 || \$1 == \"ftp\" || \$1 == \"uucp\") \
48e0a733
KB
56 { print \$1 \" \" \$6 }" /etc/passwd | \
57 while read uid homedir; do
58 if [ -f ${homedir}/.rhosts ] ; then
07576f30 59 rhost=`ls -ldgT ${homedir}/.rhosts`
48e0a733
KB
60 echo "$uid: $rhost"
61 fi
62 done
63
64# Check home directories.
65echo ""
66echo "Checking user's home directories."
07576f30
KB
67# Directories should not be owned by someone else or writeable.
68awk -F: "{ print \$1 \" \" \$6 }" /etc/passwd | \
69while read uid homedir; do
70 if [ -d ${homedir}/ ] ; then
71 file=`ls -ldgT ${homedir}`
72 echo "$uid $file"
73 fi
74done | awk \
75 "\$1 != \$4 && \$4 != \"root\" \
76 { print \"user \" \$1 \"'s home directory is owned by \" \$4 } \
77 \$2 ~ /^-....w/ \
78 { print \"user \" \$1 \"'s home directory is group writeable\" } \
79 \$2 ~ /^-.......w/ \
80 { print \"user \" \$1 \"'s home directory is other writeable\" }"
81
82echo ""
83echo "Checking .netrc, .rhosts files."
48e0a733
KB
84# Files that should not be owned by someone else or readable.
85awk -F: "{ print \$1 \" \" \$6 }" /etc/passwd | \
86while read uid homedir; do
87 if [ -f ${homedir}/.netrc ] ; then
07576f30 88 file=`ls -ldgT ${homedir}/.netrc`
48e0a733
KB
89 echo "$uid .netrc $file"
90 fi
91 if [ -f ${homedir}/.rhosts ] ; then
07576f30 92 file=`ls -ldgT ${homedir}/.rhosts`
48e0a733
KB
93 echo "$uid .rhosts $file"
94 fi
95done | awk \
96 "\$1 != \$5 && \$5 != \"root\" \
97 { print \"user \" \$1 \"'s \" \$2 \" file is owned by \" \$5 } \
98 \$3 ~ /^-...r/ \
99 { print \"user \" \$1 \"'s \" \$2 \" file is group readable\" } \
100 \$3 ~ /^-......r/ \
101 { print \"user \" \$1 \"'s \" \$2 \" file is other readable\" } \
102 \$3 ~ /^-....w/ \
103 { print \"user \" \$1 \"'s \" \$2 \" file is group writeable\" } \
104 \$3 ~ /^-.......w/ \
105 { print \"user \" \$1 \"'s \" \$2 \" file is other writeable\" }"
106
107# Files that should not be owned by someone else or writeable.
108echo ""
07576f30 109echo "Checking .cshrc, .klogin, .login, .profile files."
48e0a733
KB
110awk -F: "{ print \$1 \" \" \$6 }" /etc/passwd | \
111while read uid homedir; do
112 if [ -f ${homedir}/.cshrc ] ; then
07576f30 113 file=`ls -ldgT ${homedir}/.cshrc`
48e0a733
KB
114 echo "$uid .cshrc $file"
115 fi
116 if [ -f ${homedir}/.klogin ] ; then
07576f30 117 file=`ls -ldgT ${homedir}/.klogin`
48e0a733
KB
118 echo "$uid .klogin $file"
119 fi
120 if [ -f ${homedir}/.login ] ; then
07576f30 121 file=`ls -ldgT ${homedir}/.login`
48e0a733
KB
122 echo "$uid .login $file"
123 fi
124 if [ -f ${homedir}/.profile ] ; then
07576f30 125 file=`ls -ldgT ${homedir}/.profile`
48e0a733
KB
126 echo "$uid .profile $file"
127 fi
128done | awk \
129 "\$1 != \$5 && \$5 != \"root\" \
130 { print \"user \" \$1 \"'s \" \$2 \" file is owned by \" \$5 } \
131 \$3 ~ /^-....w/ \
132 { print \"user \" \$1 \"'s \" \$2 \" file is group writeable\" } \
133 \$3 ~ /^-.......w/ \
134 { print \"user \" \$1 \"'s \" \$2 \" file is other writeable\" }"
135
136# Check mailbox ownership and permissions.
137echo ""
138echo "Checking mailbox ownership."
139ls -l /var/mail | \
140awk "\$3 != \$9 \
141 { print \"user \" \$9 \"'s mailbox is owned by \" \$3 } \
142 \$2 ~ /^-...r/ \
143 { print \"user \" \$1 \"'s mailbox is group readable\" } \
144 \$2 ~ /^-......r/ \
145 { print \"user \" \$1 \"'s mailbox is other readable\" } \
146 \$2 ~ /^-....w/ \
147 { print \"user \" \$1 \"'s mailbox is group writeable\" } \
148 \$2 ~ /^-.......w/ \
149 { print \"user \" \$1 \"'s mailbox is other writeable\" }"
150
151# Check for special files.
152echo ""
153echo "Checking dangerous files and directories."
154mtree -e -p / -f /etc/mtree/flist.secure
155
156# Check for bad paths in root startup files.
157echo ""
158echo "Checking root paths (csh startup files)."
159rhome=/root
160for i in /etc/csh.cshrc /etc/csh.login ${rhome}/.cshrc ${rhome}/.login ; do
161 echo "$i:"
162 if [ -f $i ] ; then
163 if egrep -h -i 'path.*[^a-z]\.[^a-z]' $i > /dev/null ; then
164 echo "Root's path appears to include ."
165 fi
166 egrep -h -i path $i | \
167 awk "{ for (i = 1; i <= NF; ++i) print \$i }" | \
168 while read dir; do
169 if [ -d $dir ] ; then
170 echo `ls -ldgT $dir`
171 fi
172 done | \
173 awk "\$1 ~ /^d....w/ \
174 { print \"Root path directory \" \$10 \" is group writeable.\" } \
175 \$1 ~ /^d.......w/ \
176 { print \"Root path directory \" \$10 \" is other writeable.\" }"
177 fi
178done
179
180echo ""
181echo "Checking root paths (sh startup files)."
182for i in ${rhome}/.profile ${rhome}/.klogin ; do
183 echo "$i:"
184 if [ -f $i ] ; then
185 if egrep -h -i 'path.*:\.:' $i > /dev/null ; then
186 echo "Root's path appears to include ."
187 fi
188 egrep -h -i 'path.*:' $i | \
189 awk -F: "{ for (i = 1; i <= NF; ++i) print \$i }" | \
190 while read dir; do
191 if [ -d $dir ] ; then
192 echo `ls -ldgT $dir`
193 fi
194 done | \
195 awk "\$1 ~ /^d....w/ \
196 { print \"Root path directory \" \$10 \" is group writeable.\" } \
197 \$1 ~ /^d.......w/ \
198 { print \"Root path directory \" \$10 \" is other writeable.\" }"
199 fi
200done
8e55538e 201
07576f30
KB
202# Check for globally exported file systems.
203echo ""
204echo "Checking for globally exported file systems."
205awk '{
206 readonly = 0;
207 for (i = 2; i <= NF; ++i) {
208 if ($i ~ /-ro/)
209 readonly = 1;
210 else if ($i !~ /^-/)
211 next;
212 }
213 if (readonly)
214 print "File system " $1 " globally exported, read-only."
215 else
216 print "File system " $1 " globally exported, read-write."
217}' < /etc/exports
218
40835542 219# Display setuid and device changes.
32e3fbdd 220echo ""
773dea30 221echo "Checking setuid files and devices:"
07576f30 222(find /dev ! -fstype local -a -prune -o \
8e55538e 223 \( -perm -u+s -o -perm -g+s -o ! -type d -a ! -type f -a ! -type l \) | \
07576f30 224 sort | sed -e 's/^/ls -ldgT /' | sh >$TMP1) 2>$ERR
383148a3 225
40835542
KB
226# Display any errors that occurred during system file walk.
227if [ -s $ERR ] ; then
228 echo "Setuid/device find errors:"
229 cat $ERR
8e55538e 230 echo ""
383148a3
KB
231fi
232
40835542
KB
233# Display any changes in the setuid file list.
234egrep -v '^[bc]' $TMP1 > $LIST
8e55538e 235if [ -s $LIST ] ; then
40835542
KB
236 CUR=/var/log/setuid.current
237 BACK=/var/log/setuid.backup
383148a3 238
40835542
KB
239 if [ -s $CUR ] ; then
240 if cmp -s $CUR $LIST ; then
8e55538e
KB
241 :
242 else
40835542
KB
243 :> $TMP1
244 join -110 -210 -v2 $CUR $LIST >$TMP2
245 if [ -s $TMP2 ] ; then
246 echo "Setuid additions:"
247 tee -a $TMP1 < $TMP2
8e55538e
KB
248 echo ""
249 fi
250
40835542
KB
251 join -110 -210 -v1 $CUR $LIST >$TMP2
252 if [ -s $TMP2 ] ; then
253 echo "Setuid deletions:"
254 tee -a $TMP1 < $TMP2
8e55538e
KB
255 echo ""
256 fi
257
40835542
KB
258 sort +9 $TMP1 $CUR $LIST | \
259 sed -e 's/[ ][ ]*/ /g' | uniq -u >$TMP2
260 if [ -s $TMP2 ] ; then
261 echo "Setuid changes:"
262 column $TMP2
8e55538e
KB
263 echo ""
264 fi
265
40835542
KB
266 mv $CUR $BACK
267 mv $LIST $CUR
8e55538e
KB
268 fi
269 else
40835542 270 echo "Setuid additions:"
8e55538e
KB
271 cat $LIST
272 echo ""
40835542 273 mv $LIST $CUR
8e55538e 274 fi
525ea79f 275fi
525ea79f 276
07576f30
KB
277# Check for readable/writeable block and character disk devices.
278echo ""
279echo "Checking disk device ownership and permissions."
280egrep '^b' $TMP1 > $LIST
281egrep '^c.*/rdk[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
282egrep '^c.*/rfd[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
283egrep '^c.*/rhd[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
284egrep '^c.*/rhk[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
285egrep '^c.*/rhp[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
286egrep '^c.*/rjb[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
287egrep '^c.*/rkra[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
288egrep '^c.*/rra[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
289egrep '^c.*/rrb[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
290egrep '^c.*/rrd[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
291egrep '^c.*/rrl[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
292egrep '^c.*/rrx[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
293egrep '^c.*/rrz[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
294egrep '^c.*/rsd[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
295egrep '^c.*/rup[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
296egrep '^c.*/rwd[0-9][0-9]*[a-h]$' $TMP1 >> $LIST
297
298awk "\$4 != \"operator\" \
299 { print \"Device \" \$11 \" not owned by group operator.\" }" < $LIST
300awk "\$1 ~ /^c....w/ \
301 { print \"Device \" \$11 \" is group writeable.\" } \
302\$1 ~ /^c.......w/ \
303 { print \"Device \" \$11 \" is other writeable.\" }" < $LIST
304
305egrep '^[bcs]' $TMP1 > $LIST
40835542 306# Display any changes in the device file list.
40835542
KB
307if [ -s $LIST ] ; then
308 CUR=/var/log/device.current
309 BACK=/var/log/device.backup
310
311 if [ -s $CUR ] ; then
312 if cmp -s $CUR $LIST ; then
313 :
314 else
315 :> $TMP1
316 join -111 -211 -v2 $CUR $LIST >$TMP2
317 if [ -s $TMP2 ] ; then
318 echo "Device additions:"
319 tee -a $TMP1 < $TMP2
320 echo ""
321 fi
322
323 join -111 -211 -v1 $CUR $LIST >$TMP2
324 if [ -s $TMP2 ] ; then
325 echo "Device deletions:"
326 tee -a $TMP1 < $TMP2
327 echo ""
328 fi
329
330 sort +10 $TMP1 $CUR $LIST | \
331 sed -e 's/[ ][ ]*/ /g' | uniq -u >$TMP2
332 if [ -s $TMP2 ] ; then
333 echo "Device changes:"
334 column $TMP2
335 echo ""
336 fi
337
338 mv $CUR $BACK
339 mv $LIST $CUR
340 fi
341 else
342 echo "Device additions:"
343 cat $LIST
344 echo ""
345 mv $LIST $CUR
346 fi
347fi
40835542 348
fd70cf43
KB
349# Check the system binaries.
350# Create the mtree tree specifications using:
351#
48e0a733
KB
352# mtree -cx -pDIR -kcksum,gid,mode,nlink,size,link,time,uid
353# DIR.secure
fd70cf43
KB
354# chown bin.bin DIR.SECURE
355# chmod 444 DIR.SECURE
356#
357# Note, this is not complete protection against Trojan horsed binaries, as
358# the hacker can modify the tree specification to match the replaced binary.
359# For details on really protecting yourself against modified binaries, see
360# the mtree(8) manual page.
fd70cf43
KB
361if cd /etc/mtree; then
362 echo ""
363 echo "Checking system binaries:"
364 for file in *.secure; do
365 tree=`sed -n -e '3s/.* //p' -e 3q $file`
366 echo ""
367 echo "Checking $tree:"
368 mtree -f $file -p $tree
369 done
370fi