rlm@1
|
1 #!/bin/bash
|
rlm@1
|
2 # Copyright (c) 2004 Matthias S. Benkmann <article AT winterdrache DOT de>
|
rlm@1
|
3 # You may do everything with this code except misrepresent its origin.
|
rlm@1
|
4 # PROVIDED `AS IS' WITH ABSOLUTELY NO WARRANTY OF ANY KIND!
|
rlm@1
|
5
|
rlm@1
|
6 #The following list should contain the mount points of all filesystems
|
rlm@1
|
7 #that are to be scanned as a space-separated list within parentheses.
|
rlm@1
|
8 #/ will usually be in this list and if you have /usr
|
rlm@1
|
9 #on a separate partition, it will also be in this list. Other non-special
|
rlm@1
|
10 #filesystems where suspicious files could be located should also be put in
|
rlm@1
|
11 #this list.
|
rlm@1
|
12 #Mount points whose filesystems are special, such as procfs or sysfs should
|
rlm@1
|
13 #not be in this list.
|
rlm@1
|
14 fs_to_scan=(/)
|
rlm@1
|
15
|
rlm@1
|
16 #Files with a path prefix found in the following list are ignored.
|
rlm@1
|
17 #DO !!!!NOT!!! PUT /usr/src OR WHATEVER THE HOME DIRECTORY prefix is for your
|
rlm@1
|
18 #package users into this list!!! You DO want to scan those directories in
|
rlm@1
|
19 #order to spot e.g. world-writable tarballs and other abominations that
|
rlm@1
|
20 #may have crept in.
|
rlm@1
|
21 #Ideally, this list should be empty.
|
rlm@1
|
22 prune_prefixes=() #NO TRAILING SLASHES!!!
|
rlm@1
|
23
|
rlm@1
|
24 #If the following variable is set to "yes", then files that contain
|
rlm@1
|
25 #control characters or other non-printable characters (except for space)
|
rlm@1
|
26 #will be reported as suspicious.
|
rlm@1
|
27 #This test slows down the search considerably!
|
rlm@1
|
28 enable_illchars=yes
|
rlm@1
|
29
|
rlm@1
|
30
|
rlm@1
|
31 #suppress ugly debug output from shell
|
rlm@1
|
32 trap ':' SIGPIPE
|
rlm@1
|
33
|
rlm@1
|
34 #"-false" as 1st argument is used when called by list_suspicious_files_from
|
rlm@1
|
35 if [ $# -ge 1 -a "$1" != "-false" ]; then
|
rlm@1
|
36 echo 1>&2
|
rlm@1
|
37 echo 1>&2 "USAGE: ${0##*/}"
|
rlm@1
|
38 echo 1>&2
|
rlm@1
|
39 echo 1>&2 ' Outputs a categorized list of files and directories with properties'
|
rlm@1
|
40 echo 1>&2 ' that could mean trouble and should be investigated.'
|
rlm@1
|
41 echo 1>&2
|
rlm@1
|
42 exit 1
|
rlm@1
|
43 fi
|
rlm@1
|
44
|
rlm@1
|
45
|
rlm@1
|
46 usergroupmatch=(-true)
|
rlm@1
|
47 if [ "$1" = "-false" ]; then
|
rlm@1
|
48 usergroupmatch=(\( "$@" \))
|
rlm@1
|
49 fi
|
rlm@1
|
50
|
rlm@1
|
51 #construct find commands that match the prune_prefixes. Each prefix will be
|
rlm@1
|
52 #matched as -path <prefix> -or -path <prefix>/*
|
rlm@1
|
53 #so that the directory itself and all subdirectories are matched.
|
rlm@1
|
54 y=(\( -false)
|
rlm@1
|
55 for ((i=0; $i<${#prune_prefixes[@]}; i=$i+1))
|
rlm@1
|
56 do
|
rlm@1
|
57 y[${#y[@]}]='-or'
|
rlm@1
|
58 y[${#y[@]}]=-path
|
rlm@1
|
59 y[${#y[@]}]="${prune_prefixes[$i]}"
|
rlm@1
|
60 y[${#y[@]}]='-or'
|
rlm@1
|
61 y[${#y[@]}]=-path
|
rlm@1
|
62 y[${#y[@]}]="${prune_prefixes[$i]}/*"
|
rlm@1
|
63 done
|
rlm@1
|
64 y[${#y[@]}]=')'
|
rlm@1
|
65
|
rlm@1
|
66 illchars=( $'\x1' $'\x2' $'\x3' $'\x4' $'\x5' $'\x6' $'\x7' $'\x8'
|
rlm@1
|
67 $'\x9' $'\xA' $'\xB' $'\xC' $'\xD' $'\xE' $'\xF' $'\x10' $'\x11'
|
rlm@1
|
68 $'\x12' $'\x13' $'\x14' $'\x15' $'\x16' $'\x17' $'\x18' $'\x19'
|
rlm@1
|
69 $'\x1A' $'\x1B' $'\x1C' $'\x1D' $'\x1E' $'\x1F' $'\x7f' $'\x80'
|
rlm@1
|
70 $'\x81' $'\x82' $'\x83' $'\x84' $'\x85' $'\x86' $'\x87' $'\x88'
|
rlm@1
|
71 $'\x89' $'\x8A' $'\x8B' $'\x8C' $'\x8D' $'\x8E' $'\x8F' $'\x90'
|
rlm@1
|
72 $'\x91' $'\x92' $'\x93' $'\x94' $'\x95' $'\x96' $'\x97' $'\x98'
|
rlm@1
|
73 $'\x99' $'\x9A' $'\x9B' $'\x9C' $'\x9D' $'\x9E' $'\x9F' )
|
rlm@1
|
74
|
rlm@1
|
75
|
rlm@1
|
76 if [ "$enable_illchars" = yes ]; then
|
rlm@1
|
77
|
rlm@1
|
78 illname=(\( -false)
|
rlm@1
|
79 for ((i=0; $i<${#illchars[@]}; i=$i+1))
|
rlm@1
|
80 do
|
rlm@1
|
81 #handle bash \x7f error
|
rlm@1
|
82 if [ "*${illchars[$i]}*" = "**" ]; then
|
rlm@1
|
83 illchars[$i]=$'\x80' #'
|
rlm@1
|
84 fi
|
rlm@1
|
85 illname[${#illname[@]}]='-or'
|
rlm@1
|
86 illname[${#illname[@]}]=-name
|
rlm@1
|
87 illname[${#illname[@]}]="*${illchars[$i]}*"
|
rlm@1
|
88 done
|
rlm@1
|
89 illname[${#illname[@]}]=')'
|
rlm@1
|
90
|
rlm@1
|
91 illlink=(\( -false)
|
rlm@1
|
92 for ((i=0; $i<${#illchars[@]}; i=$i+1))
|
rlm@1
|
93 do
|
rlm@1
|
94 illlink[${#illlink[@]}]='-or'
|
rlm@1
|
95 illlink[${#illlink[@]}]=-lname
|
rlm@1
|
96 illlink[${#illlink[@]}]="*${illchars[$i]}*"
|
rlm@1
|
97 done
|
rlm@1
|
98 illlink[${#illlink[@]}]=')'
|
rlm@1
|
99 else #if [ "$enable_illchars" = no ]
|
rlm@1
|
100 illlink=(-false)
|
rlm@1
|
101 illname=(-false)
|
rlm@1
|
102 fi
|
rlm@1
|
103
|
rlm@1
|
104 # $1=section heading
|
rlm@1
|
105 # $2=inode message
|
rlm@1
|
106 report()
|
rlm@1
|
107 {
|
rlm@1
|
108 echo -printf "increment_code_here"
|
rlm@1
|
109 echo -printf
|
rlm@1
|
110 echo "1 ${1}\\n" | sed 's/ /\\040/g'
|
rlm@1
|
111 echo -printf "insert_code_here"
|
rlm@1
|
112
|
rlm@1
|
113 if [ -n "$2" ]; then
|
rlm@1
|
114 echo -printf
|
rlm@1
|
115 echo "2 %i 1 ${2}\\n" | sed 's/ /\\040/g'
|
rlm@1
|
116 echo -printf "insert_code_here"
|
rlm@1
|
117 echo -printf
|
rlm@1
|
118 echo "2 %i 2 " | sed 's/ /\\040/g'
|
rlm@1
|
119 else
|
rlm@1
|
120 echo -printf "2\\040"
|
rlm@1
|
121 fi
|
rlm@1
|
122
|
rlm@1
|
123 echo -exec ls -T 0 -ladQ {} \;
|
rlm@1
|
124 }
|
rlm@1
|
125
|
rlm@1
|
126
|
rlm@1
|
127 filegoodperm=(\( -perm 644 -or -perm 755 -or -perm 555 -or -perm 444 -or -perm 600 -or -perm 700 -or -perm 640 \))
|
rlm@1
|
128 dirgoodperm=(\( -perm 755 -or -perm 555 -or -perm 700 -or -perm 750 \))
|
rlm@1
|
129
|
rlm@1
|
130 good=( \(
|
rlm@1
|
131 -not \( -not -type d -links +1 \)
|
rlm@1
|
132 -not -nouser -not -nogroup
|
rlm@1
|
133 -not \( "${illname[@]}" \)
|
rlm@1
|
134 -not \( "${illlink[@]}" \)
|
rlm@1
|
135 \)
|
rlm@1
|
136 -and
|
rlm@1
|
137 \(
|
rlm@1
|
138 \( -type f -not -group install "${filegoodperm[@]}" \)
|
rlm@1
|
139 -or \( -type d -not -group install "${dirgoodperm[@]}" \)
|
rlm@1
|
140 -or \( -type d -group install \( -perm 1775 \) \)
|
rlm@1
|
141 -or \( -type d -group root -user root -path "/tmp" \( -perm 1777 \) \)
|
rlm@1
|
142 -or \( -type d -group root -user root -path "/var/tmp" \( -perm 1777 \) \)
|
rlm@1
|
143 -or \( -not -type d -not -type f -not -type l -path "/dev/*" \)
|
rlm@1
|
144 -or \( -type l \( -xtype b -or -xtype c -or -xtype d -or -xtype p -or -xtype f \) \)
|
rlm@1
|
145 \)
|
rlm@1
|
146 )
|
rlm@1
|
147
|
rlm@1
|
148 bad=(
|
rlm@1
|
149 \( "${illname[@]}" $(report "NON-PRINTABLE CHAR IN NAME") \)
|
rlm@1
|
150 OP \( "${illlink[@]}" $(report "NON-PRINTABLE-CHAR IN LINK-TARGET") \)
|
rlm@1
|
151 OP \( -type f -perm -4000 $(report "SETUID FILES") \)
|
rlm@1
|
152 OP \( -type f -perm -2000 $(report "SETGID FILES") \)
|
rlm@1
|
153 OP \( -type f -perm -1000 $(report "STICKY FILES") \)
|
rlm@1
|
154 OP \( -type d -perm -2000 $(report "GROUP-KEEPING DIRECTORIES") \)
|
rlm@1
|
155 OP \( -type d -not -group install -perm -1000 $(report "STICKY DIRECTORIES") \)
|
rlm@1
|
156 OP \( -type f -perm -g+w $(report "GROUP-WRITABLE FILES") \)
|
rlm@1
|
157 OP \( -type f -perm -o+w $(report "WORLD-WRITABLE FILES") \)
|
rlm@1
|
158 OP \( -type d -perm -g+w $(report "GROUP-WRITABLE DIRECTORIES") \)
|
rlm@1
|
159 OP \( -type d -perm -o+w $(report "WORLD-WRITABLE DIRECTORIES") \)
|
rlm@1
|
160 OP \( -not \( -type f -or -type l -or -type d \) -not -path "/dev/*" $(report "SPECIAL FILES OUTSIDE /dev") \)
|
rlm@1
|
161 OP \( -type d -group install -not -perm 1755 $(report "INSTALL DIRECTORIES WITH UNUSUAL PERMISSIONS") \)
|
rlm@1
|
162 OP \( -type f -group install $(report "FILES ASSIGNED TO GROUP INSTALL") \)
|
rlm@1
|
163 OP \( -type l -not \( -xtype b -or -xtype c -or -xtype d -or -xtype p -or -xtype f \) $(report "SYMLINKS POSSIBLY BROKEN OR LOOP") \)
|
rlm@1
|
164 OP \( -not -type d -links +1 $(report "HARDLINKED FILES" "Inode %i is shared by %n files, including") \)
|
rlm@1
|
165 OP \( -nouser $(report "THINGS HAVING UID WITH NO ASSIGNED USER NAME") \)
|
rlm@1
|
166 OP \( -nogroup $(report "THINGS HAVING GID WITH NO ASSIGNED GROUP NAME") \)
|
rlm@1
|
167 OP \( -type f -not -group install -not "${filegoodperm[@]}" $(report "FILES WITH UNUSUAL PERMISSIONS") \)
|
rlm@1
|
168 OP \( -type d -not -group install -not "${dirgoodperm[@]}" $(report "DIRECTORIES WITH UNUSUAL PERMISSIONS") \)
|
rlm@1
|
169 )
|
rlm@1
|
170
|
rlm@1
|
171 #insert unique codes for the messages
|
rlm@1
|
172 code=100
|
rlm@1
|
173 for ((i=0; $i<${#bad[@]}; i=$i+1))
|
rlm@1
|
174 do
|
rlm@1
|
175 if [ "${bad[$i]}" = "increment_code_here" ]; then
|
rlm@1
|
176 code=$(($code + 1))
|
rlm@1
|
177 bad[$i]=$code
|
rlm@1
|
178 elif [ "${bad[$i]}" = "insert_code_here" ]; then
|
rlm@1
|
179 bad[$i]=$code
|
rlm@1
|
180 fi
|
rlm@1
|
181 done
|
rlm@1
|
182
|
rlm@1
|
183 allbad=() #all bad matches are reported
|
rlm@1
|
184 onebad=() #only the first bad match is reported
|
rlm@1
|
185 for ((i=0; $i<${#bad[@]}; i=$i+1))
|
rlm@1
|
186 do
|
rlm@1
|
187 if [ "${bad[$i]}" = "OP" ]; then
|
rlm@1
|
188 allbad[$i]=","
|
rlm@1
|
189 onebad[$i]="-or"
|
rlm@1
|
190 else
|
rlm@1
|
191 allbad[$i]="${bad[$i]}"
|
rlm@1
|
192 onebad[$i]="${bad[$i]}"
|
rlm@1
|
193 fi
|
rlm@1
|
194 done
|
rlm@1
|
195
|
rlm@1
|
196 #Add a default case to onebad.
|
rlm@1
|
197 #This should never be hit, because the explicit cases should catch all
|
rlm@1
|
198 #files, but just in case I've missed something, this will catch it.
|
rlm@1
|
199 onebad=("${onebad[@]}" -or $(report "WEIRD SHIT") )
|
rlm@1
|
200
|
rlm@1
|
201 #make allbad always return false
|
rlm@1
|
202 allbad=("${allbad[@]}" , -false)
|
rlm@1
|
203
|
rlm@1
|
204 cmd=( "${usergroupmatch[@]}" -and
|
rlm@1
|
205 \( \( "${good[@]}" \) -or \( "${allbad[@]}" \) -or \( "${onebad[@]}" \) \)
|
rlm@1
|
206 )
|
rlm@1
|
207
|
rlm@1
|
208 #In the following find command, the part
|
rlm@1
|
209 # -not ( ( "${y[@]}" -prune ) -or "${y[@]}" )
|
rlm@1
|
210 #is responsible for preventing the files that match prune_prefixes from
|
rlm@1
|
211 #being processed. The 2nd "${y[@]}" may seem redundant, but it isn't, because
|
rlm@1
|
212 #-prune has no effect and is always false when -depth is used.
|
rlm@1
|
213 find "${fs_to_scan[@]}" -xdev -noleaf \
|
rlm@1
|
214 -not \( \( "${y[@]}" -prune \) -or "${y[@]}" \) \
|
rlm@1
|
215 -and \( "${cmd[@]}" \) |
|
rlm@1
|
216 sed 's/^\(...2\) \([0-9]\+ 2 \)\?\([^ ]\+\) \+[^ ]\+ \+\([^ ]\+\) \+\([^ ]\+\) \+[^"]\+\(".\+\)/\1 \2\3 \6 \4:\5/' |
|
rlm@1
|
217 sort -u |
|
rlm@1
|
218 sed 's/^...1 /\'$'\n''/;s/^...2 [0-9]\+ 1 /\'$'\n'' /;s/^...2 [0-9]\+ 2 / /;s/^...2 / /'
|