Commit 4c37c7a52c80a2f865e376af6acc01a86ecf887c
1 parent
d109192c79
Exists in
master
added checksec script
Showing 1 changed file with 882 additions and 0 deletions Inline Diff
scripts/checksec.sh
View file @
4c37c7a
File was created | 1 | #!/bin/bash | ||
2 | # | |||
3 | # The BSD License (http://www.opensource.org/licenses/bsd-license.php) | |||
4 | # specifies the terms and conditions of use for checksec.sh: | |||
5 | # | |||
6 | # Copyright (c) 2009-2011, Tobias Klein. | |||
7 | # All rights reserved. | |||
8 | # | |||
9 | # Redistribution and use in source and binary forms, with or without | |||
10 | # modification, are permitted provided that the following conditions | |||
11 | # are met: | |||
12 | # | |||
13 | # * Redistributions of source code must retain the above copyright | |||
14 | # notice, this list of conditions and the following disclaimer. | |||
15 | # * Redistributions in binary form must reproduce the above copyright | |||
16 | # notice, this list of conditions and the following disclaimer in | |||
17 | # the documentation and/or other materials provided with the | |||
18 | # distribution. | |||
19 | # * Neither the name of Tobias Klein nor the name of trapkit.de may be | |||
20 | # used to endorse or promote products derived from this software | |||
21 | # without specific prior written permission. | |||
22 | # | |||
23 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||
24 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||
25 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |||
26 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |||
27 | # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
28 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |||
29 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | |||
30 | # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |||
31 | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
32 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF | |||
33 | # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH | |||
34 | # DAMAGE. | |||
35 | # | |||
36 | # Name : checksec.sh | |||
37 | # Version : 1.5 | |||
38 | # Author : Tobias Klein | |||
39 | # Date : November 2011 | |||
40 | # Download: http://www.trapkit.de/tools/checksec.html | |||
41 | # Changes : http://www.trapkit.de/tools/checksec_changes.txt | |||
42 | # | |||
43 | # Description: | |||
44 | # | |||
45 | # Modern Linux distributions offer some mitigation techniques to make it | |||
46 | # harder to exploit software vulnerabilities reliably. Mitigations such | |||
47 | # as RELRO, NoExecute (NX), Stack Canaries, Address Space Layout | |||
48 | # Randomization (ASLR) and Position Independent Executables (PIE) have | |||
49 | # made reliably exploiting any vulnerabilities that do exist far more | |||
50 | # challenging. The checksec.sh script is designed to test what *standard* | |||
51 | # Linux OS and PaX (http://pax.grsecurity.net/) security features are being | |||
52 | # used. | |||
53 | # | |||
54 | # As of version 1.3 the script also lists the status of various Linux kernel | |||
55 | # protection mechanisms. | |||
56 | # | |||
57 | # Credits: | |||
58 | # | |||
59 | # Thanks to Brad Spengler (grsecurity.net) for the PaX support. | |||
60 | # Thanks to Jon Oberheide (jon.oberheide.org) for the kernel support. | |||
61 | # Thanks to Ollie Whitehouse (Research In Motion) for rpath/runpath support. | |||
62 | # | |||
63 | # Others that contributed to checksec.sh (in no particular order): | |||
64 | # | |||
65 | # Simon Ruderich, Denis Scherbakov, Stefan Kuttler, Radoslaw Madej, | |||
66 | # Anthony G. Basile, Martin Vaeth and Brian Davis. | |||
67 | # | |||
68 | ||||
69 | # global vars | |||
70 | have_readelf=1 | |||
71 | verbose=false | |||
72 | ||||
73 | # FORTIFY_SOURCE vars | |||
74 | FS_end=_chk | |||
75 | FS_cnt_total=0 | |||
76 | FS_cnt_checked=0 | |||
77 | FS_cnt_unchecked=0 | |||
78 | FS_chk_func_libc=0 | |||
79 | FS_functions=0 | |||
80 | FS_libc=0 | |||
81 | ||||
82 | # version information | |||
83 | version() { | |||
84 | echo "checksec v1.5, Tobias Klein, www.trapkit.de, November 2011" | |||
85 | echo | |||
86 | } | |||
87 | ||||
88 | # help | |||
89 | help() { | |||
90 | echo "Usage: checksec [OPTION]" | |||
91 | echo | |||
92 | echo "Options:" | |||
93 | echo | |||
94 | echo " --file <executable-file>" | |||
95 | echo " --dir <directory> [-v]" | |||
96 | echo " --proc <process name>" | |||
97 | echo " --proc-all" | |||
98 | echo " --proc-libs <process ID>" | |||
99 | echo " --kernel" | |||
100 | echo " --fortify-file <executable-file>" | |||
101 | echo " --fortify-proc <process ID>" | |||
102 | echo " --version" | |||
103 | echo " --help" | |||
104 | echo | |||
105 | echo "For more information, see:" | |||
106 | echo " http://www.trapkit.de/tools/checksec.html" | |||
107 | echo | |||
108 | } | |||
109 | ||||
110 | # check if command exists | |||
111 | command_exists () { | |||
112 | type $1 > /dev/null 2>&1; | |||
113 | } | |||
114 | ||||
115 | # check if directory exists | |||
116 | dir_exists () { | |||
117 | if [ -d $1 ] ; then | |||
118 | return 0 | |||
119 | else | |||
120 | return 1 | |||
121 | fi | |||
122 | } | |||
123 | ||||
124 | # check user privileges | |||
125 | root_privs () { | |||
126 | if [ $(/usr/bin/id -u) -eq 0 ] ; then | |||
127 | return 0 | |||
128 | else | |||
129 | return 1 | |||
130 | fi | |||
131 | } | |||
132 | ||||
133 | # check if input is numeric | |||
134 | isNumeric () { | |||
135 | echo "$@" | grep -q -v "[^0-9]" | |||
136 | } | |||
137 | ||||
138 | # check if input is a string | |||
139 | isString () { | |||
140 | echo "$@" | grep -q -v "[^A-Za-z]" | |||
141 | } | |||
142 | ||||
143 | # check file(s) | |||
144 | filecheck() { | |||
145 | # check for RELRO support | |||
146 | if readelf -l $1 2>/dev/null | grep -q 'GNU_RELRO'; then | |||
147 | if readelf -d $1 2>/dev/null | grep -q 'BIND_NOW'; then | |||
148 | echo -n -e '\033[32mFull RELRO \033[m ' | |||
149 | else | |||
150 | echo -n -e '\033[33mPartial RELRO\033[m ' | |||
151 | fi | |||
152 | else | |||
153 | echo -n -e '\033[31mNo RELRO \033[m ' | |||
154 | fi | |||
155 | ||||
156 | # check for stack canary support | |||
157 | if readelf -s $1 2>/dev/null | grep -q '__stack_chk_fail'; then | |||
158 | echo -n -e '\033[32mCanary found \033[m ' | |||
159 | else | |||
160 | echo -n -e '\033[31mNo canary found\033[m ' | |||
161 | fi | |||
162 | ||||
163 | # check for NX support | |||
164 | if readelf -W -l $1 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then | |||
165 | echo -n -e '\033[31mNX disabled\033[m ' | |||
166 | else | |||
167 | echo -n -e '\033[32mNX enabled \033[m ' | |||
168 | fi | |||
169 | ||||
170 | # check for PIE support | |||
171 | if readelf -h $1 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then | |||
172 | echo -n -e '\033[31mNo PIE \033[m ' | |||
173 | elif readelf -h $1 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then | |||
174 | if readelf -d $1 2>/dev/null | grep -q '(DEBUG)'; then | |||
175 | echo -n -e '\033[32mPIE enabled \033[m ' | |||
176 | else | |||
177 | echo -n -e '\033[33mDSO \033[m ' | |||
178 | fi | |||
179 | else | |||
180 | echo -n -e '\033[33mNot an ELF file\033[m ' | |||
181 | fi | |||
182 | ||||
183 | # check for rpath / run path | |||
184 | if readelf -d $1 2>/dev/null | grep -q 'rpath'; then | |||
185 | echo -n -e '\033[31mRPATH \033[m ' | |||
186 | else | |||
187 | echo -n -e '\033[32mNo RPATH \033[m ' | |||
188 | fi | |||
189 | ||||
190 | if readelf -d $1 2>/dev/null | grep -q 'runpath'; then | |||
191 | echo -n -e '\033[31mRUNPATH \033[m ' | |||
192 | else | |||
193 | echo -n -e '\033[32mNo RUNPATH \033[m ' | |||
194 | fi | |||
195 | } | |||
196 | ||||
197 | # check process(es) | |||
198 | proccheck() { | |||
199 | # check for RELRO support | |||
200 | if readelf -l $1/exe 2>/dev/null | grep -q 'Program Headers'; then | |||
201 | if readelf -l $1/exe 2>/dev/null | grep -q 'GNU_RELRO'; then | |||
202 | if readelf -d $1/exe 2>/dev/null | grep -q 'BIND_NOW'; then | |||
203 | echo -n -e '\033[32mFull RELRO \033[m ' | |||
204 | else | |||
205 | echo -n -e '\033[33mPartial RELRO \033[m ' | |||
206 | fi | |||
207 | else | |||
208 | echo -n -e '\033[31mNo RELRO \033[m ' | |||
209 | fi | |||
210 | else | |||
211 | echo -n -e '\033[31mPermission denied (please run as root)\033[m\n' | |||
212 | exit 1 | |||
213 | fi | |||
214 | ||||
215 | # check for stack canary support | |||
216 | if readelf -s $1/exe 2>/dev/null | grep -q 'Symbol table'; then | |||
217 | if readelf -s $1/exe 2>/dev/null | grep -q '__stack_chk_fail'; then | |||
218 | echo -n -e '\033[32mCanary found \033[m ' | |||
219 | else | |||
220 | echo -n -e '\033[31mNo canary found \033[m ' | |||
221 | fi | |||
222 | else | |||
223 | if [ "$1" != "1" ] ; then | |||
224 | echo -n -e '\033[33mPermission denied \033[m ' | |||
225 | else | |||
226 | echo -n -e '\033[33mNo symbol table found\033[m ' | |||
227 | fi | |||
228 | fi | |||
229 | ||||
230 | # first check for PaX support | |||
231 | if cat $1/status 2> /dev/null | grep -q 'PaX:'; then | |||
232 | pageexec=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b6) ) | |||
233 | segmexec=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b10) ) | |||
234 | mprotect=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b8) ) | |||
235 | randmmap=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b9) ) | |||
236 | if [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "M" && "$randmmap" = "R" ]] ; then | |||
237 | echo -n -e '\033[32mPaX enabled\033[m ' | |||
238 | elif [[ "$pageexec" = "p" && "$segmexec" = "s" && "$randmmap" = "R" ]] ; then | |||
239 | echo -n -e '\033[33mPaX ASLR only\033[m ' | |||
240 | elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "m" && "$randmmap" = "R" ]] ; then | |||
241 | echo -n -e '\033[33mPaX mprot off \033[m' | |||
242 | elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "M" && "$randmmap" = "r" ]] ; then | |||
243 | echo -n -e '\033[33mPaX ASLR off\033[m ' | |||
244 | elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "m" && "$randmmap" = "r" ]] ; then | |||
245 | echo -n -e '\033[33mPaX NX only\033[m ' | |||
246 | else | |||
247 | echo -n -e '\033[31mPaX disabled\033[m ' | |||
248 | fi | |||
249 | # fallback check for NX support | |||
250 | elif readelf -W -l $1/exe 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then | |||
251 | echo -n -e '\033[31mNX disabled\033[m ' | |||
252 | else | |||
253 | echo -n -e '\033[32mNX enabled \033[m ' | |||
254 | fi | |||
255 | ||||
256 | # check for PIE support | |||
257 | if readelf -h $1/exe 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then | |||
258 | echo -n -e '\033[31mNo PIE \033[m ' | |||
259 | elif readelf -h $1/exe 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then | |||
260 | if readelf -d $1/exe 2>/dev/null | grep -q '(DEBUG)'; then | |||
261 | echo -n -e '\033[32mPIE enabled \033[m ' | |||
262 | else | |||
263 | echo -n -e '\033[33mDynamic Shared Object\033[m ' | |||
264 | fi | |||
265 | else | |||
266 | echo -n -e '\033[33mNot an ELF file \033[m ' | |||
267 | fi | |||
268 | } | |||
269 | ||||
270 | # check mapped libraries | |||
271 | libcheck() { | |||
272 | libs=( $(awk '{ print $6 }' /proc/$1/maps | grep '/' | sort -u | xargs file | grep ELF | awk '{ print $1 }' | sed 's/:/ /') ) | |||
273 | ||||
274 | printf "\n* Loaded libraries (file information, # of mapped files: ${#libs[@]}):\n\n" | |||
275 | ||||
276 | for element in $(seq 0 $((${#libs[@]} - 1))) | |||
277 | do | |||
278 | echo " ${libs[$element]}:" | |||
279 | echo -n " " | |||
280 | filecheck ${libs[$element]} | |||
281 | printf "\n\n" | |||
282 | done | |||
283 | } | |||
284 | ||||
285 | # check for system-wide ASLR support | |||
286 | aslrcheck() { | |||
287 | # PaX ASLR support | |||
288 | if !(cat /proc/1/status 2> /dev/null | grep -q 'Name:') ; then | |||
289 | echo -n -e ':\033[33m insufficient privileges for PaX ASLR checks\033[m\n' | |||
290 | echo -n -e ' Fallback to standard Linux ASLR check' | |||
291 | fi | |||
292 | ||||
293 | if cat /proc/1/status 2> /dev/null | grep -q 'PaX:'; then | |||
294 | printf ": " | |||
295 | if cat /proc/1/status 2> /dev/null | grep 'PaX:' | grep -q 'R'; then | |||
296 | echo -n -e '\033[32mPaX ASLR enabled\033[m\n\n' | |||
297 | else | |||
298 | echo -n -e '\033[31mPaX ASLR disabled\033[m\n\n' | |||
299 | fi | |||
300 | else | |||
301 | # standard Linux 'kernel.randomize_va_space' ASLR support | |||
302 | # (see the kernel file 'Documentation/sysctl/kernel.txt' for a detailed description) | |||
303 | printf " (kernel.randomize_va_space): " | |||
304 | if /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 1'; then | |||
305 | echo -n -e '\033[33mOn (Setting: 1)\033[m\n\n' | |||
306 | printf " Description - Make the addresses of mmap base, stack and VDSO page randomized.\n" | |||
307 | printf " This, among other things, implies that shared libraries will be loaded to \n" | |||
308 | printf " random addresses. Also for PIE-linked binaries, the location of code start\n" | |||
309 | printf " is randomized. Heap addresses are *not* randomized.\n\n" | |||
310 | elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 2'; then | |||
311 | echo -n -e '\033[32mOn (Setting: 2)\033[m\n\n' | |||
312 | printf " Description - Make the addresses of mmap base, heap, stack and VDSO page randomized.\n" | |||
313 | printf " This, among other things, implies that shared libraries will be loaded to random \n" | |||
314 | printf " addresses. Also for PIE-linked binaries, the location of code start is randomized.\n\n" | |||
315 | elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 0'; then | |||
316 | echo -n -e '\033[31mOff (Setting: 0)\033[m\n' | |||
317 | else | |||
318 | echo -n -e '\033[31mNot supported\033[m\n' | |||
319 | fi | |||
320 | printf " See the kernel file 'Documentation/sysctl/kernel.txt' for more details.\n\n" | |||
321 | fi | |||
322 | } | |||
323 | ||||
324 | # check cpu nx flag | |||
325 | nxcheck() { | |||
326 | if grep -q nx /proc/cpuinfo; then | |||
327 | echo -n -e '\033[32mYes\033[m\n\n' | |||
328 | else | |||
329 | echo -n -e '\033[31mNo\033[m\n\n' | |||
330 | fi | |||
331 | } | |||
332 | ||||
333 | # check for kernel protection mechanisms | |||
334 | kernelcheck() { | |||
335 | printf " Description - List the status of kernel protection mechanisms. Rather than\n" | |||
336 | printf " inspect kernel mechanisms that may aid in the prevention of exploitation of\n" | |||
337 | printf " userspace processes, this option lists the status of kernel configuration\n" | |||
338 | printf " options that harden the kernel itself against attack.\n\n" | |||
339 | printf " Kernel config: " | |||
340 | ||||
341 | if [ -f /proc/config.gz ] ; then | |||
342 | kconfig="zcat /proc/config.gz" | |||
343 | printf "\033[32m/proc/config.gz\033[m\n\n" | |||
344 | elif [ -f /boot/config-`uname -r` ] ; then | |||
345 | kconfig="cat /boot/config-`uname -r`" | |||
346 | printf "\033[33m/boot/config-`uname -r`\033[m\n\n" | |||
347 | printf " Warning: The config on disk may not represent running kernel config!\n\n"; | |||
348 | elif [ -f "${KBUILD_OUTPUT:-/usr/src/linux}"/.config ] ; then | |||
349 | kconfig="cat ${KBUILD_OUTPUT:-/usr/src/linux}/.config" | |||
350 | printf "\033[33m%s\033[m\n\n" "${KBUILD_OUTPUT:-/usr/src/linux}/.config" | |||
351 | printf " Warning: The config on disk may not represent running kernel config!\n\n"; | |||
352 | else | |||
353 | printf "\033[31mNOT FOUND\033[m\n\n" | |||
354 | exit 0 | |||
355 | fi | |||
356 | ||||
357 | printf " GCC stack protector support: " | |||
358 | if $kconfig | grep -qi 'CONFIG_CC_STACKPROTECTOR=y'; then | |||
359 | printf "\033[32mEnabled\033[m\n" | |||
360 | else | |||
361 | printf "\033[31mDisabled\033[m\n" | |||
362 | fi | |||
363 | ||||
364 | printf " Strict user copy checks: " | |||
365 | if $kconfig | grep -qi 'CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y'; then | |||
366 | printf "\033[32mEnabled\033[m\n" | |||
367 | else | |||
368 | printf "\033[31mDisabled\033[m\n" | |||
369 | fi | |||
370 | ||||
371 | printf " Enforce read-only kernel data: " | |||
372 | if $kconfig | grep -qi 'CONFIG_DEBUG_RODATA=y'; then | |||
373 | printf "\033[32mEnabled\033[m\n" | |||
374 | else | |||
375 | printf "\033[31mDisabled\033[m\n" | |||
376 | fi | |||
377 | printf " Restrict /dev/mem access: " | |||
378 | if $kconfig | grep -qi 'CONFIG_STRICT_DEVMEM=y'; then | |||
379 | printf "\033[32mEnabled\033[m\n" | |||
380 | else | |||
381 | printf "\033[31mDisabled\033[m\n" | |||
382 | fi | |||
383 | ||||
384 | printf " Restrict /dev/kmem access: " | |||
385 | if $kconfig | grep -qi 'CONFIG_DEVKMEM=y'; then | |||
386 | printf "\033[31mDisabled\033[m\n" | |||
387 | else | |||
388 | printf "\033[32mEnabled\033[m\n" | |||
389 | fi | |||
390 | ||||
391 | printf "\n" | |||
392 | printf "* grsecurity / PaX: " | |||
393 | ||||
394 | if $kconfig | grep -qi 'CONFIG_GRKERNSEC=y'; then | |||
395 | if $kconfig | grep -qi 'CONFIG_GRKERNSEC_HIGH=y'; then | |||
396 | printf "\033[32mHigh GRKERNSEC\033[m\n\n" | |||
397 | elif $kconfig | grep -qi 'CONFIG_GRKERNSEC_MEDIUM=y'; then | |||
398 | printf "\033[33mMedium GRKERNSEC\033[m\n\n" | |||
399 | elif $kconfig | grep -qi 'CONFIG_GRKERNSEC_LOW=y'; then | |||
400 | printf "\033[31mLow GRKERNSEC\033[m\n\n" | |||
401 | else | |||
402 | printf "\033[33mCustom GRKERNSEC\033[m\n\n" | |||
403 | fi | |||
404 | ||||
405 | printf " Non-executable kernel pages: " | |||
406 | if $kconfig | grep -qi 'CONFIG_PAX_KERNEXEC=y'; then | |||
407 | printf "\033[32mEnabled\033[m\n" | |||
408 | else | |||
409 | printf "\033[31mDisabled\033[m\n" | |||
410 | fi | |||
411 | ||||
412 | printf " Prevent userspace pointer deref: " | |||
413 | if $kconfig | grep -qi 'CONFIG_PAX_MEMORY_UDEREF=y'; then | |||
414 | printf "\033[32mEnabled\033[m\n" | |||
415 | else | |||
416 | printf "\033[31mDisabled\033[m\n" | |||
417 | fi | |||
418 | ||||
419 | printf " Prevent kobject refcount overflow: " | |||
420 | if $kconfig | grep -qi 'CONFIG_PAX_REFCOUNT=y'; then | |||
421 | printf "\033[32mEnabled\033[m\n" | |||
422 | else | |||
423 | printf "\033[31mDisabled\033[m\n" | |||
424 | fi | |||
425 | ||||
426 | printf " Bounds check heap object copies: " | |||
427 | if $kconfig | grep -qi 'CONFIG_PAX_USERCOPY=y'; then | |||
428 | printf "\033[32mEnabled\033[m\n" | |||
429 | else | |||
430 | printf "\033[31mDisabled\033[m\n" | |||
431 | fi | |||
432 | ||||
433 | printf " Disable writing to kmem/mem/port: " | |||
434 | if $kconfig | grep -qi 'CONFIG_GRKERNSEC_KMEM=y'; then | |||
435 | printf "\033[32mEnabled\033[m\n" | |||
436 | else | |||
437 | printf "\033[31mDisabled\033[m\n" | |||
438 | fi | |||
439 | ||||
440 | printf " Disable privileged I/O: " | |||
441 | if $kconfig | grep -qi 'CONFIG_GRKERNSEC_IO=y'; then | |||
442 | printf "\033[32mEnabled\033[m\n" | |||
443 | else | |||
444 | printf "\033[31mDisabled\033[m\n" | |||
445 | fi | |||
446 | ||||
447 | printf " Harden module auto-loading: " | |||
448 | if $kconfig | grep -qi 'CONFIG_GRKERNSEC_MODHARDEN=y'; then | |||
449 | printf "\033[32mEnabled\033[m\n" | |||
450 | else | |||
451 | printf "\033[31mDisabled\033[m\n" | |||
452 | fi | |||
453 | ||||
454 | printf " Hide kernel symbols: " | |||
455 | if $kconfig | grep -qi 'CONFIG_GRKERNSEC_HIDESYM=y'; then | |||
456 | printf "\033[32mEnabled\033[m\n" | |||
457 | else | |||
458 | printf "\033[31mDisabled\033[m\n" | |||
459 | fi | |||
460 | else | |||
461 | printf "\033[31mNo GRKERNSEC\033[m\n\n" | |||
462 | printf " The grsecurity / PaX patchset is available here:\n" | |||
463 | printf " http://grsecurity.net/\n" | |||
464 | fi | |||
465 | ||||
466 | printf "\n" | |||
467 | printf "* Kernel Heap Hardening: " | |||
468 | ||||
469 | if $kconfig | grep -qi 'CONFIG_KERNHEAP=y'; then | |||
470 | if $kconfig | grep -qi 'CONFIG_KERNHEAP_FULLPOISON=y'; then | |||
471 | printf "\033[32mFull KERNHEAP\033[m\n\n" | |||
472 | else | |||
473 | printf "\033[33mPartial KERNHEAP\033[m\n\n" | |||
474 | fi | |||
475 | else | |||
476 | printf "\033[31mNo KERNHEAP\033[m\n\n" | |||
477 | printf " The KERNHEAP hardening patchset is available here:\n" | |||
478 | printf " https://www.subreption.com/kernheap/\n\n" | |||
479 | fi | |||
480 | } | |||
481 | ||||
482 | # --- FORTIFY_SOURCE subfunctions (start) --- | |||
483 | ||||
484 | # is FORTIFY_SOURCE supported by libc? | |||
485 | FS_libc_check() { | |||
486 | printf "* FORTIFY_SOURCE support available (libc) : " | |||
487 | ||||
488 | if [ "${#FS_chk_func_libc[@]}" != "0" ] ; then | |||
489 | printf "\033[32mYes\033[m\n" | |||
490 | else | |||
491 | printf "\033[31mNo\033[m\n" | |||
492 | exit 1 | |||
493 | fi | |||
494 | } | |||
495 | ||||
496 | # was the binary compiled with FORTIFY_SOURCE? | |||
497 | FS_binary_check() { | |||
498 | printf "* Binary compiled with FORTIFY_SOURCE support: " | |||
499 | ||||
500 | for FS_elem_functions in $(seq 0 $((${#FS_functions[@]} - 1))) | |||
501 | do | |||
502 | if [[ ${FS_functions[$FS_elem_functions]} =~ _chk ]] ; then | |||
503 | printf "\033[32mYes\033[m\n" | |||
504 | return | |||
505 | fi | |||
506 | done | |||
507 | printf "\033[31mNo\033[m\n" | |||
508 | exit 1 | |||
509 | } | |||
510 | ||||
511 | FS_comparison() { | |||
512 | echo | |||
513 | printf " ------ EXECUTABLE-FILE ------- . -------- LIBC --------\n" | |||
514 | printf " FORTIFY-able library functions | Checked function names\n" | |||
515 | printf " -------------------------------------------------------\n" | |||
516 | ||||
517 | for FS_elem_libc in $(seq 0 $((${#FS_chk_func_libc[@]} - 1))) | |||
518 | do | |||
519 | for FS_elem_functions in $(seq 0 $((${#FS_functions[@]} - 1))) | |||
520 | do | |||
521 | FS_tmp_func=${FS_functions[$FS_elem_functions]} | |||
522 | FS_tmp_libc=${FS_chk_func_libc[$FS_elem_libc]} | |||
523 | ||||
524 | if [[ $FS_tmp_func =~ ^$FS_tmp_libc$ ]] ; then | |||
525 | printf " \033[31m%-30s\033[m | __%s%s\n" $FS_tmp_func $FS_tmp_libc $FS_end | |||
526 | let FS_cnt_total++ | |||
527 | let FS_cnt_unchecked++ | |||
528 | elif [[ $FS_tmp_func =~ ^$FS_tmp_libc(_chk) ]] ; then | |||
529 | printf " \033[32m%-30s\033[m | __%s%s\n" $FS_tmp_func $FS_tmp_libc $FS_end | |||
530 | let FS_cnt_total++ | |||
531 | let FS_cnt_checked++ | |||
532 | fi | |||
533 | ||||
534 | done | |||
535 | done | |||
536 | } | |||
537 | ||||
538 | FS_summary() { | |||
539 | echo | |||
540 | printf "SUMMARY:\n\n" | |||
541 | printf "* Number of checked functions in libc : ${#FS_chk_func_libc[@]}\n" | |||
542 | printf "* Total number of library functions in the executable: ${#FS_functions[@]}\n" | |||
543 | printf "* Number of FORTIFY-able functions in the executable : %s\n" $FS_cnt_total | |||
544 | printf "* Number of checked functions in the executable : \033[32m%s\033[m\n" $FS_cnt_checked | |||
545 | printf "* Number of unchecked functions in the executable : \033[31m%s\033[m\n" $FS_cnt_unchecked | |||
546 | echo | |||
547 | } | |||
548 | ||||
549 | # --- FORTIFY_SOURCE subfunctions (end) --- | |||
550 | ||||
551 | if !(command_exists readelf) ; then | |||
552 | printf "\033[31mWarning: 'readelf' not found! It's required for most checks.\033[m\n\n" | |||
553 | have_readelf=0 | |||
554 | fi | |||
555 | ||||
556 | # parse command-line arguments | |||
557 | case "$1" in | |||
558 | ||||
559 | --version) | |||
560 | version | |||
561 | exit 0 | |||
562 | ;; | |||
563 | ||||
564 | --help) | |||
565 | help | |||
566 | exit 0 | |||
567 | ;; | |||
568 | ||||
569 | --dir) | |||
570 | if [ "$3" = "-v" ] ; then | |||
571 | verbose=true | |||
572 | fi | |||
573 | if [ $have_readelf -eq 0 ] ; then | |||
574 | exit 1 | |||
575 | fi | |||
576 | if [ -z "$2" ] ; then | |||
577 | printf "\033[31mError: Please provide a valid directory.\033[m\n\n" | |||
578 | exit 1 | |||
579 | fi | |||
580 | # remove trailing slashes | |||
581 | tempdir=`echo $2 | sed -e "s/\/*$//"` | |||
582 | if [ ! -d $tempdir ] ; then | |||
583 | printf "\033[31mError: The directory '$tempdir' does not exist.\033[m\n\n" | |||
584 | exit 1 | |||
585 | fi | |||
586 | cd $tempdir | |||
587 | printf "RELRO STACK CANARY NX PIE RPATH RUNPATH FILE\n" | |||
588 | for N in [A-Za-z]*; do | |||
589 | if [ "$N" != "[A-Za-z]*" ]; then | |||
590 | # read permissions? | |||
591 | if [ ! -r $N ]; then | |||
592 | printf "\033[31mError: No read permissions for '$tempdir/$N' (run as root).\033[m\n" | |||
593 | else | |||
594 | # ELF executable? | |||
595 | out=`file $N` | |||
596 | if [[ ! $out =~ ELF ]] ; then | |||
597 | if [ "$verbose" = "true" ] ; then | |||
598 | printf "\033[34m*** Not an ELF file: $tempdir/" | |||
599 | file $N | |||
600 | printf "\033[m" | |||
601 | fi | |||
602 | else | |||
603 | filecheck $N | |||
604 | if [ `find $tempdir/$N \( -perm -004000 -o -perm -002000 \) -type f -print` ]; then | |||
605 | printf "\033[37;41m%s%s\033[m" $2 $N | |||
606 | else | |||
607 | printf "%s%s" $tempdir/ $N | |||
608 | fi | |||
609 | echo | |||
610 | fi | |||
611 | fi | |||
612 | fi | |||
613 | done | |||
614 | exit 0 | |||
615 | ;; | |||
616 | ||||
617 | --file) | |||
618 | if [ $have_readelf -eq 0 ] ; then | |||
619 | exit 1 | |||
620 | fi | |||
621 | if [ -z "$2" ] ; then | |||
622 | printf "\033[31mError: Please provide a valid file.\033[m\n\n" | |||
623 | exit 1 | |||
624 | fi | |||
625 | # does the file exist? | |||
626 | if [ ! -e $2 ] ; then | |||
627 | printf "\033[31mError: The file '$2' does not exist.\033[m\n\n" | |||
628 | exit 1 | |||
629 | fi | |||
630 | # read permissions? | |||
631 | if [ ! -r $2 ] ; then | |||
632 | printf "\033[31mError: No read permissions for '$2' (run as root).\033[m\n\n" | |||
633 | exit 1 | |||
634 | fi | |||
635 | # ELF executable? | |||
636 | out=`file $2` | |||
637 | if [[ ! $out =~ ELF ]] ; then | |||
638 | printf "\033[31mError: Not an ELF file: " | |||
639 | file $2 | |||
640 | printf "\033[m\n" | |||
641 | exit 1 | |||
642 | fi | |||
643 | printf "RELRO STACK CANARY NX PIE RPATH RUNPATH FILE\n" | |||
644 | filecheck $2 | |||
645 | if [ `find $2 \( -perm -004000 -o -perm -002000 \) -type f -print` ] ; then | |||
646 | printf "\033[37;41m%s%s\033[m" $2 $N | |||
647 | else | |||
648 | printf "%s" $2 | |||
649 | fi | |||
650 | echo | |||
651 | exit 0 | |||
652 | ;; | |||
653 | ||||
654 | --proc-all) | |||
655 | if [ $have_readelf -eq 0 ] ; then | |||
656 | exit 1 | |||
657 | fi | |||
658 | cd /proc | |||
659 | printf "* System-wide ASLR" | |||
660 | aslrcheck | |||
661 | printf "* Does the CPU support NX: " | |||
662 | nxcheck | |||
663 | printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" | |||
664 | for N in [1-9]*; do | |||
665 | if [ $N != $$ ] && readlink -q $N/exe > /dev/null; then | |||
666 | printf "%16s" `head -1 $N/status | cut -b 7-` | |||
667 | printf "%7d " $N | |||
668 | proccheck $N | |||
669 | echo | |||
670 | fi | |||
671 | done | |||
672 | if [ ! -e /usr/bin/id ] ; then | |||
673 | printf "\n\033[33mNote: If you are running 'checksec.sh' as an unprivileged user, you\n" | |||
674 | printf " will not see all processes. Please run the script as root.\033[m\n\n" | |||
675 | else | |||
676 | if !(root_privs) ; then | |||
677 | printf "\n\033[33mNote: You are running 'checksec.sh' as an unprivileged user.\n" | |||
678 | printf " Too see all processes, please run the script as root.\033[m\n\n" | |||
679 | fi | |||
680 | fi | |||
681 | exit 0 | |||
682 | ;; | |||
683 | ||||
684 | --proc) | |||
685 | if [ $have_readelf -eq 0 ] ; then | |||
686 | exit 1 | |||
687 | fi | |||
688 | if [ -z "$2" ] ; then | |||
689 | printf "\033[31mError: Please provide a valid process name.\033[m\n\n" | |||
690 | exit 1 | |||
691 | fi | |||
692 | if !(isString "$2") ; then | |||
693 | printf "\033[31mError: Please provide a valid process name.\033[m\n\n" | |||
694 | exit 1 | |||
695 | fi | |||
696 | cd /proc | |||
697 | printf "* System-wide ASLR" | |||
698 | aslrcheck | |||
699 | printf "* Does the CPU support NX: " | |||
700 | nxcheck | |||
701 | printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" | |||
702 | for N in `ps -Ao pid,comm | grep $2 | cut -b1-6`; do | |||
703 | if [ -d $N ] ; then | |||
704 | printf "%16s" `head -1 $N/status | cut -b 7-` | |||
705 | printf "%7d " $N | |||
706 | # read permissions? | |||
707 | if [ ! -r $N/exe ] ; then | |||
708 | if !(root_privs) ; then | |||
709 | printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" | |||
710 | exit 1 | |||
711 | fi | |||
712 | if [ ! `readlink $N/exe` ] ; then | |||
713 | printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" | |||
714 | exit 1 | |||
715 | fi | |||
716 | exit 1 | |||
717 | fi | |||
718 | proccheck $N | |||
719 | echo | |||
720 | fi | |||
721 | done | |||
722 | exit 0 | |||
723 | ;; | |||
724 | ||||
725 | --proc-libs) | |||
726 | if [ $have_readelf -eq 0 ] ; then | |||
727 | exit 1 | |||
728 | fi | |||
729 | if [ -z "$2" ] ; then | |||
730 | printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" | |||
731 | exit 1 | |||
732 | fi | |||
733 | if !(isNumeric "$2") ; then | |||
734 | printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" | |||
735 | exit 1 | |||
736 | fi | |||
737 | cd /proc | |||
738 | printf "* System-wide ASLR" | |||
739 | aslrcheck | |||
740 | printf "* Does the CPU support NX: " | |||
741 | nxcheck | |||
742 | printf "* Process information:\n\n" | |||
743 | printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" | |||
744 | N=$2 | |||
745 | if [ -d $N ] ; then | |||
746 | printf "%16s" `head -1 $N/status | cut -b 7-` | |||
747 | printf "%7d " $N | |||
748 | # read permissions? | |||
749 | if [ ! -r $N/exe ] ; then | |||
750 | if !(root_privs) ; then | |||
751 | printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" | |||
752 | exit 1 | |||
753 | fi | |||
754 | if [ ! `readlink $N/exe` ] ; then | |||
755 | printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" | |||
756 | exit 1 | |||
757 | fi | |||
758 | exit 1 | |||
759 | fi | |||
760 | proccheck $N | |||
761 | echo | |||
762 | libcheck $N | |||
763 | fi | |||
764 | exit 0 | |||
765 | ;; | |||
766 | ||||
767 | --kernel) | |||
768 | cd /proc | |||
769 | printf "* Kernel protection information:\n\n" | |||
770 | kernelcheck | |||
771 | exit 0 | |||
772 | ;; | |||
773 | ||||
774 | --fortify-file) | |||
775 | if [ $have_readelf -eq 0 ] ; then | |||
776 | exit 1 | |||
777 | fi | |||
778 | if [ -z "$2" ] ; then | |||
779 | printf "\033[31mError: Please provide a valid file.\033[m\n\n" | |||
780 | exit 1 | |||
781 | fi | |||
782 | # does the file exist? | |||
783 | if [ ! -e $2 ] ; then | |||
784 | printf "\033[31mError: The file '$2' does not exist.\033[m\n\n" | |||
785 | exit 1 | |||
786 | fi | |||
787 | # read permissions? | |||
788 | if [ ! -r $2 ] ; then | |||
789 | printf "\033[31mError: No read permissions for '$2' (run as root).\033[m\n\n" | |||
790 | exit 1 | |||
791 | fi | |||
792 | # ELF executable? | |||
793 | out=`file $2` | |||
794 | if [[ ! $out =~ ELF ]] ; then | |||
795 | printf "\033[31mError: Not an ELF file: " | |||
796 | file $2 | |||
797 | printf "\033[m\n" | |||
798 | exit 1 | |||
799 | fi | |||
800 | if [ -e /lib/libc.so.6 ] ; then | |||
801 | FS_libc=/lib/libc.so.6 | |||
802 | elif [ -e /lib64/libc.so.6 ] ; then | |||
803 | FS_libc=/lib64/libc.so.6 | |||
804 | elif [ -e /lib/i386-linux-gnu/libc.so.6 ] ; then | |||
805 | FS_libc=/lib/i386-linux-gnu/libc.so.6 | |||
806 | elif [ -e /lib/x86_64-linux-gnu/libc.so.6 ] ; then | |||
807 | FS_libc=/lib/x86_64-linux-gnu/libc.so.6 | |||
808 | else | |||
809 | printf "\033[31mError: libc not found.\033[m\n\n" | |||
810 | exit 1 | |||
811 | fi |