diff options
author | Armin Kuster <akuster@mvista.com> | 2014-07-06 22:27:10 -0700 |
---|---|---|
committer | Armin Kuster <akuster@mvista.com> | 2014-08-06 07:57:16 -0700 |
commit | f20ff5c45c2b6b2f5e699581eb0f997b892cc09d (patch) | |
tree | b406378c3813a58bd79ec0117f01fef752e5501e | |
parent | 6a4b2849a131242e564518c5c36633e0d23ef63d (diff) | |
download | meta-security-f20ff5c45c2b6b2f5e699581eb0f997b892cc09d.tar.gz |
checksec: Add new alsr pic pie test script
Signed-off-by: Armin Kuster <akuster@mvista.com>
-rw-r--r-- | recipes-security/checksec/checksec_1.5.bb | 16 | ||||
-rw-r--r-- | recipes-security/checksec/files/checksec.sh | 882 |
2 files changed, 898 insertions, 0 deletions
diff --git a/recipes-security/checksec/checksec_1.5.bb b/recipes-security/checksec/checksec_1.5.bb new file mode 100644 index 0000000..49ecc28 --- /dev/null +++ b/recipes-security/checksec/checksec_1.5.bb | |||
@@ -0,0 +1,16 @@ | |||
1 | SUMMARY = "Program radominization" | ||
2 | DESCRIPTION = "The checksec.sh script is designed to test what standard Linux OS and PaX security features are being used." | ||
3 | SECTION = "security" | ||
4 | LICENSE = "BSD" | ||
5 | HOMEPAGE="http://www.trapkit.de/tools/checksec.html" | ||
6 | |||
7 | LIC_FILES_CHKSUM = "file://checksec.sh;md5=075996be339ab16ad7b94d6de3ee07bd" | ||
8 | |||
9 | SRC_URI = "file://checksec.sh" | ||
10 | |||
11 | S = "${WORKDIR}" | ||
12 | |||
13 | do_install() { | ||
14 | install -d ${D}${bindir} | ||
15 | install -m 0755 ${WORKDIR}/checksec.sh ${D}${bindir} | ||
16 | } | ||
diff --git a/recipes-security/checksec/files/checksec.sh b/recipes-security/checksec/files/checksec.sh new file mode 100644 index 0000000..dd1f72e --- /dev/null +++ b/recipes-security/checksec/files/checksec.sh | |||
@@ -0,0 +1,882 @@ | |||
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 | ||
812 | |||
813 | FS_chk_func_libc=( $(readelf -s $FS_libc | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') ) | ||
814 | FS_functions=( $(readelf -s $2 | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') ) | ||
815 | |||
816 | FS_libc_check | ||
817 | FS_binary_check | ||
818 | FS_comparison | ||
819 | FS_summary | ||
820 | |||
821 | exit 0 | ||
822 | ;; | ||
823 | |||
824 | --fortify-proc) | ||
825 | if [ $have_readelf -eq 0 ] ; then | ||
826 | exit 1 | ||
827 | fi | ||
828 | if [ -z "$2" ] ; then | ||
829 | printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" | ||
830 | exit 1 | ||
831 | fi | ||
832 | if !(isNumeric "$2") ; then | ||
833 | printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" | ||
834 | exit 1 | ||
835 | fi | ||
836 | cd /proc | ||
837 | N=$2 | ||
838 | if [ -d $N ] ; then | ||
839 | # read permissions? | ||
840 | if [ ! -r $N/exe ] ; then | ||
841 | if !(root_privs) ; then | ||
842 | printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" | ||
843 | exit 1 | ||
844 | fi | ||
845 | if [ ! `readlink $N/exe` ] ; then | ||
846 | printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" | ||
847 | exit 1 | ||
848 | fi | ||
849 | exit 1 | ||
850 | fi | ||
851 | if [ -e /lib/libc.so.6 ] ; then | ||
852 | FS_libc=/lib/libc.so.6 | ||
853 | elif [ -e /lib64/libc.so.6 ] ; then | ||
854 | FS_libc=/lib64/libc.so.6 | ||
855 | elif [ -e /lib/i386-linux-gnu/libc.so.6 ] ; then | ||
856 | FS_libc=/lib/i386-linux-gnu/libc.so.6 | ||
857 | elif [ -e /lib/x86_64-linux-gnu/libc.so.6 ] ; then | ||
858 | FS_libc=/lib/x86_64-linux-gnu/libc.so.6 | ||
859 | else | ||
860 | printf "\033[31mError: libc not found.\033[m\n\n" | ||
861 | exit 1 | ||
862 | fi | ||
863 | printf "* Process name (PID) : %s (%d)\n" `head -1 $N/status | cut -b 7-` $N | ||
864 | FS_chk_func_libc=( $(readelf -s $FS_libc | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') ) | ||
865 | FS_functions=( $(readelf -s $2/exe | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') ) | ||
866 | |||
867 | FS_libc_check | ||
868 | FS_binary_check | ||
869 | FS_comparison | ||
870 | FS_summary | ||
871 | fi | ||
872 | exit 0 | ||
873 | ;; | ||
874 | |||
875 | *) | ||
876 | if [ "$#" != "0" ] ; then | ||
877 | printf "\033[31mError: Unknown option '$1'.\033[m\n\n" | ||
878 | fi | ||
879 | help | ||
880 | exit 1 | ||
881 | ;; | ||
882 | esac | ||