Commit 4c37c7a52c80a2f865e376af6acc01a86ecf887c

Authored by Ian Foster
1 parent d109192c79
Exists in master

added checksec script

Showing 1 changed file with 882 additions and 0 deletions Side-by-side Diff

scripts/checksec.sh View file @ 4c37c7a
  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