![sean+zkbot@leastauthority.com](/assets/img/avatar_default.png)
11 changed files with 1200 additions and 14 deletions
@ -0,0 +1,181 @@ |
|||
#!/usr/bin/python2 |
|||
''' |
|||
Perform basic ELF security checks on a series of executables. |
|||
Exit status will be 0 if successful, and the program will be silent. |
|||
Otherwise the exit status will be 1 and it will log which executables failed which checks. |
|||
Needs `readelf` (for ELF) and `objdump` (for PE). |
|||
''' |
|||
from __future__ import division,print_function,unicode_literals |
|||
import subprocess |
|||
import sys |
|||
import os |
|||
|
|||
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf') |
|||
OBJDUMP_CMD = os.getenv('OBJDUMP', '/usr/bin/objdump') |
|||
|
|||
def check_ELF_PIE(executable): |
|||
''' |
|||
Check for position independent executable (PIE), allowing for address space randomization. |
|||
''' |
|||
p = subprocess.Popen([READELF_CMD, '-h', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) |
|||
(stdout, stderr) = p.communicate() |
|||
if p.returncode: |
|||
raise IOError('Error opening file') |
|||
|
|||
ok = False |
|||
for line in stdout.split(b'\n'): |
|||
line = line.split() |
|||
if len(line)>=2 and line[0] == b'Type:' and line[1] == b'DYN': |
|||
ok = True |
|||
return ok |
|||
|
|||
def get_ELF_program_headers(executable): |
|||
'''Return type and flags for ELF program headers''' |
|||
p = subprocess.Popen([READELF_CMD, '-l', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) |
|||
(stdout, stderr) = p.communicate() |
|||
if p.returncode: |
|||
raise IOError('Error opening file') |
|||
in_headers = False |
|||
count = 0 |
|||
headers = [] |
|||
for line in stdout.split(b'\n'): |
|||
if line.startswith(b'Program Headers:'): |
|||
in_headers = True |
|||
if line == b'': |
|||
in_headers = False |
|||
if in_headers: |
|||
if count == 1: # header line |
|||
ofs_typ = line.find(b'Type') |
|||
ofs_offset = line.find(b'Offset') |
|||
ofs_flags = line.find(b'Flg') |
|||
ofs_align = line.find(b'Align') |
|||
if ofs_typ == -1 or ofs_offset == -1 or ofs_flags == -1 or ofs_align == -1: |
|||
raise ValueError('Cannot parse elfread -lW output') |
|||
elif count > 1: |
|||
typ = line[ofs_typ:ofs_offset].rstrip() |
|||
flags = line[ofs_flags:ofs_align].rstrip() |
|||
headers.append((typ, flags)) |
|||
count += 1 |
|||
return headers |
|||
|
|||
def check_ELF_NX(executable): |
|||
''' |
|||
Check that no sections are writable and executable (including the stack) |
|||
''' |
|||
have_wx = False |
|||
have_gnu_stack = False |
|||
for (typ, flags) in get_ELF_program_headers(executable): |
|||
if typ == b'GNU_STACK': |
|||
have_gnu_stack = True |
|||
if b'W' in flags and b'E' in flags: # section is both writable and executable |
|||
have_wx = True |
|||
return have_gnu_stack and not have_wx |
|||
|
|||
def check_ELF_RELRO(executable): |
|||
''' |
|||
Check for read-only relocations. |
|||
GNU_RELRO program header must exist |
|||
Dynamic section must have BIND_NOW flag |
|||
''' |
|||
have_gnu_relro = False |
|||
for (typ, flags) in get_ELF_program_headers(executable): |
|||
# Note: not checking flags == 'R': here as linkers set the permission differently |
|||
# This does not affect security: the permission flags of the GNU_RELRO program header are ignored, the PT_LOAD header determines the effective permissions. |
|||
# However, the dynamic linker need to write to this area so these are RW. |
|||
# Glibc itself takes care of mprotecting this area R after relocations are finished. |
|||
# See also http://permalink.gmane.org/gmane.comp.gnu.binutils/71347 |
|||
if typ == b'GNU_RELRO': |
|||
have_gnu_relro = True |
|||
|
|||
have_bindnow = False |
|||
p = subprocess.Popen([READELF_CMD, '-d', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) |
|||
(stdout, stderr) = p.communicate() |
|||
if p.returncode: |
|||
raise IOError('Error opening file') |
|||
for line in stdout.split(b'\n'): |
|||
tokens = line.split() |
|||
if len(tokens)>1 and tokens[1] == b'(BIND_NOW)' or (len(tokens)>2 and tokens[1] == b'(FLAGS)' and b'BIND_NOW' in tokens[2]): |
|||
have_bindnow = True |
|||
return have_gnu_relro and have_bindnow |
|||
|
|||
def check_ELF_Canary(executable): |
|||
''' |
|||
Check for use of stack canary |
|||
''' |
|||
p = subprocess.Popen([READELF_CMD, '--dyn-syms', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) |
|||
(stdout, stderr) = p.communicate() |
|||
if p.returncode: |
|||
raise IOError('Error opening file') |
|||
ok = False |
|||
for line in stdout.split(b'\n'): |
|||
if b'__stack_chk_fail' in line: |
|||
ok = True |
|||
return ok |
|||
|
|||
def get_PE_dll_characteristics(executable): |
|||
''' |
|||
Get PE DllCharacteristics bits |
|||
''' |
|||
p = subprocess.Popen([OBJDUMP_CMD, '-x', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) |
|||
(stdout, stderr) = p.communicate() |
|||
if p.returncode: |
|||
raise IOError('Error opening file') |
|||
for line in stdout.split('\n'): |
|||
tokens = line.split() |
|||
if len(tokens)>=2 and tokens[0] == 'DllCharacteristics': |
|||
return int(tokens[1],16) |
|||
return 0 |
|||
|
|||
|
|||
def check_PE_PIE(executable): |
|||
'''PIE: DllCharacteristics bit 0x40 signifies dynamicbase (ASLR)''' |
|||
return bool(get_PE_dll_characteristics(executable) & 0x40) |
|||
|
|||
def check_PE_NX(executable): |
|||
'''NX: DllCharacteristics bit 0x100 signifies nxcompat (DEP)''' |
|||
return bool(get_PE_dll_characteristics(executable) & 0x100) |
|||
|
|||
CHECKS = { |
|||
'ELF': [ |
|||
('PIE', check_ELF_PIE), |
|||
('NX', check_ELF_NX), |
|||
('RELRO', check_ELF_RELRO), |
|||
('Canary', check_ELF_Canary) |
|||
], |
|||
'PE': [ |
|||
('PIE', check_PE_PIE), |
|||
('NX', check_PE_NX) |
|||
] |
|||
} |
|||
|
|||
def identify_executable(executable): |
|||
with open(filename, 'rb') as f: |
|||
magic = f.read(4) |
|||
if magic.startswith(b'MZ'): |
|||
return 'PE' |
|||
elif magic.startswith(b'\x7fELF'): |
|||
return 'ELF' |
|||
return None |
|||
|
|||
if __name__ == '__main__': |
|||
retval = 0 |
|||
for filename in sys.argv[1:]: |
|||
try: |
|||
etype = identify_executable(filename) |
|||
if etype is None: |
|||
print('%s: unknown format' % filename) |
|||
retval = 1 |
|||
continue |
|||
|
|||
failed = [] |
|||
for (name, func) in CHECKS[etype]: |
|||
if not func(filename): |
|||
failed.append(name) |
|||
if failed: |
|||
print('%s: failed %s' % (filename, ' '.join(failed))) |
|||
retval = 1 |
|||
except IOError: |
|||
print('%s: cannot open' % filename) |
|||
retval = 1 |
|||
exit(retval) |
|||
|
@ -0,0 +1,60 @@ |
|||
#!/usr/bin/python2 |
|||
''' |
|||
Test script for security-check.py |
|||
''' |
|||
from __future__ import division,print_function |
|||
import subprocess |
|||
import sys |
|||
import unittest |
|||
|
|||
def write_testcode(filename): |
|||
with open(filename, 'w') as f: |
|||
f.write(''' |
|||
#include <stdio.h> |
|||
int main() |
|||
{ |
|||
printf("the quick brown fox jumps over the lazy god\\n"); |
|||
return 0; |
|||
} |
|||
''') |
|||
|
|||
def call_security_check(cc, source, executable, options): |
|||
subprocess.check_call([cc,source,'-o',executable] + options) |
|||
p = subprocess.Popen(['./security-check.py',executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) |
|||
(stdout, stderr) = p.communicate() |
|||
return (p.returncode, stdout.rstrip()) |
|||
|
|||
class TestSecurityChecks(unittest.TestCase): |
|||
def test_ELF(self): |
|||
source = 'test1.c' |
|||
executable = 'test1' |
|||
cc = 'gcc' |
|||
write_testcode(source) |
|||
|
|||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-zexecstack','-fno-stack-protector','-Wl,-znorelro']), |
|||
(1, executable+': failed PIE NX RELRO Canary')) |
|||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fno-stack-protector','-Wl,-znorelro']), |
|||
(1, executable+': failed PIE RELRO Canary')) |
|||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro']), |
|||
(1, executable+': failed PIE RELRO')) |
|||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-znorelro','-pie','-fPIE']), |
|||
(1, executable+': failed RELRO')) |
|||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,-znoexecstack','-fstack-protector-all','-Wl,-zrelro','-Wl,-z,now','-pie','-fPIE']), |
|||
(0, '')) |
|||
|
|||
def test_PE(self): |
|||
source = 'test1.c' |
|||
executable = 'test1.exe' |
|||
cc = 'i686-w64-mingw32-gcc' |
|||
write_testcode(source) |
|||
|
|||
self.assertEqual(call_security_check(cc, source, executable, []), |
|||
(1, executable+': failed PIE NX')) |
|||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat']), |
|||
(1, executable+': failed PIE')) |
|||
self.assertEqual(call_security_check(cc, source, executable, ['-Wl,--nxcompat','-Wl,--dynamicbase']), |
|||
(0, '')) |
|||
|
|||
if __name__ == '__main__': |
|||
unittest.main() |
|||
|
@ -0,0 +1,46 @@ |
|||
#!/bin/bash |
|||
|
|||
set -e |
|||
|
|||
REPOROOT="$(readlink -f "$(dirname "$0")"/../../)" |
|||
|
|||
function test_rpath_runpath { |
|||
if "${REPOROOT}/qa/zcash/checksec.sh" --file "$1" | grep -q "No RPATH.*No RUNPATH"; then |
|||
echo PASS: "$1" has no RPATH or RUNPATH. |
|||
return 0 |
|||
else |
|||
echo FAIL: "$1" has an RPATH or a RUNPATH. |
|||
"${REPOROOT}/qa/zcash/checksec.sh" --file "$1" |
|||
return 1 |
|||
fi |
|||
} |
|||
|
|||
function test_fortify_source { |
|||
if { "${REPOROOT}/qa/zcash/checksec.sh" --fortify-file "$1" | grep -q "FORTIFY_SOURCE support available.*Yes"; } && |
|||
{ "${REPOROOT}/qa/zcash/checksec.sh" --fortify-file "$1" | grep -q "Binary compiled with FORTIFY_SOURCE support.*Yes"; }; then |
|||
echo PASS: "$1" has FORTIFY_SOURCE. |
|||
return 0 |
|||
else |
|||
echo FAIL: "$1" is missing FORTIFY_SOURCE. |
|||
return 1 |
|||
fi |
|||
} |
|||
|
|||
# PIE, RELRO, Canary, and NX are tested by make check-security. |
|||
make -C "$REPOROOT/src" check-security |
|||
|
|||
test_rpath_runpath "${REPOROOT}/src/zcashd" |
|||
test_rpath_runpath "${REPOROOT}/src/zcash-cli" |
|||
test_rpath_runpath "${REPOROOT}/src/zcash-gtest" |
|||
test_rpath_runpath "${REPOROOT}/src/bitcoin-tx" |
|||
test_rpath_runpath "${REPOROOT}/src/test/test_bitcoin" |
|||
test_rpath_runpath "${REPOROOT}/src/zcash/GenerateParams" |
|||
|
|||
# NOTE: checksec.sh does not reliably determine whether FORTIFY_SOURCE is |
|||
# enabled for the entire binary. See issue #915. |
|||
test_fortify_source "${REPOROOT}/src/zcashd" |
|||
test_fortify_source "${REPOROOT}/src/zcash-cli" |
|||
test_fortify_source "${REPOROOT}/src/zcash-gtest" |
|||
test_fortify_source "${REPOROOT}/src/bitcoin-tx" |
|||
test_fortify_source "${REPOROOT}/src/test/test_bitcoin" |
|||
test_fortify_source "${REPOROOT}/src/zcash/GenerateParams" |
@ -0,0 +1,882 @@ |
|||
#!/bin/bash |
|||
# |
|||
# The BSD License (http://www.opensource.org/licenses/bsd-license.php) |
|||
# specifies the terms and conditions of use for checksec.sh: |
|||
# |
|||
# Copyright (c) 2009-2011, Tobias Klein. |
|||
# All rights reserved. |
|||
# |
|||
# Redistribution and use in source and binary forms, with or without |
|||
# modification, are permitted provided that the following conditions |
|||
# are met: |
|||
# |
|||
# * Redistributions of source code must retain the above copyright |
|||
# notice, this list of conditions and the following disclaimer. |
|||
# * Redistributions in binary form must reproduce the above copyright |
|||
# notice, this list of conditions and the following disclaimer in |
|||
# the documentation and/or other materials provided with the |
|||
# distribution. |
|||
# * Neither the name of Tobias Klein nor the name of trapkit.de may be |
|||
# used to endorse or promote products derived from this software |
|||
# without specific prior written permission. |
|||
# |
|||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
|||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
|||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
|||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
|||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
|||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF |
|||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
|||
# DAMAGE. |
|||
# |
|||
# Name : checksec.sh |
|||
# Version : 1.5 |
|||
# Author : Tobias Klein |
|||
# Date : November 2011 |
|||
# Download: http://www.trapkit.de/tools/checksec.html |
|||
# Changes : http://www.trapkit.de/tools/checksec_changes.txt |
|||
# |
|||
# Description: |
|||
# |
|||
# Modern Linux distributions offer some mitigation techniques to make it |
|||
# harder to exploit software vulnerabilities reliably. Mitigations such |
|||
# as RELRO, NoExecute (NX), Stack Canaries, Address Space Layout |
|||
# Randomization (ASLR) and Position Independent Executables (PIE) have |
|||
# made reliably exploiting any vulnerabilities that do exist far more |
|||
# challenging. The checksec.sh script is designed to test what *standard* |
|||
# Linux OS and PaX (http://pax.grsecurity.net/) security features are being |
|||
# used. |
|||
# |
|||
# As of version 1.3 the script also lists the status of various Linux kernel |
|||
# protection mechanisms. |
|||
# |
|||
# Credits: |
|||
# |
|||
# Thanks to Brad Spengler (grsecurity.net) for the PaX support. |
|||
# Thanks to Jon Oberheide (jon.oberheide.org) for the kernel support. |
|||
# Thanks to Ollie Whitehouse (Research In Motion) for rpath/runpath support. |
|||
# |
|||
# Others that contributed to checksec.sh (in no particular order): |
|||
# |
|||
# Simon Ruderich, Denis Scherbakov, Stefan Kuttler, Radoslaw Madej, |
|||
# Anthony G. Basile, Martin Vaeth and Brian Davis. |
|||
# |
|||
|
|||
# global vars |
|||
have_readelf=1 |
|||
verbose=false |
|||
|
|||
# FORTIFY_SOURCE vars |
|||
FS_end=_chk |
|||
FS_cnt_total=0 |
|||
FS_cnt_checked=0 |
|||
FS_cnt_unchecked=0 |
|||
FS_chk_func_libc=0 |
|||
FS_functions=0 |
|||
FS_libc=0 |
|||
|
|||
# version information |
|||
version() { |
|||
echo "checksec v1.5, Tobias Klein, www.trapkit.de, November 2011" |
|||
echo |
|||
} |
|||
|
|||
# help |
|||
help() { |
|||
echo "Usage: checksec [OPTION]" |
|||
echo |
|||
echo "Options:" |
|||
echo |
|||
echo " --file <executable-file>" |
|||
echo " --dir <directory> [-v]" |
|||
echo " --proc <process name>" |
|||
echo " --proc-all" |
|||
echo " --proc-libs <process ID>" |
|||
echo " --kernel" |
|||
echo " --fortify-file <executable-file>" |
|||
echo " --fortify-proc <process ID>" |
|||
echo " --version" |
|||
echo " --help" |
|||
echo |
|||
echo "For more information, see:" |
|||
echo " http://www.trapkit.de/tools/checksec.html" |
|||
echo |
|||
} |
|||
|
|||
# check if command exists |
|||
command_exists () { |
|||
type $1 > /dev/null 2>&1; |
|||
} |
|||
|
|||
# check if directory exists |
|||
dir_exists () { |
|||
if [ -d $1 ] ; then |
|||
return 0 |
|||
else |
|||
return 1 |
|||
fi |
|||
} |
|||
|
|||
# check user privileges |
|||
root_privs () { |
|||
if [ $(/usr/bin/id -u) -eq 0 ] ; then |
|||
return 0 |
|||
else |
|||
return 1 |
|||
fi |
|||
} |
|||
|
|||
# check if input is numeric |
|||
isNumeric () { |
|||
echo "$@" | grep -q -v "[^0-9]" |
|||
} |
|||
|
|||
# check if input is a string |
|||
isString () { |
|||
echo "$@" | grep -q -v "[^A-Za-z]" |
|||
} |
|||
|
|||
# check file(s) |
|||
filecheck() { |
|||
# check for RELRO support |
|||
if readelf -l $1 2>/dev/null | grep -q 'GNU_RELRO'; then |
|||
if readelf -d $1 2>/dev/null | grep -q 'BIND_NOW'; then |
|||
echo -n -e '\033[32mFull RELRO \033[m ' |
|||
else |
|||
echo -n -e '\033[33mPartial RELRO\033[m ' |
|||
fi |
|||
else |
|||
echo -n -e '\033[31mNo RELRO \033[m ' |
|||
fi |
|||
|
|||
# check for stack canary support |
|||
if readelf -s $1 2>/dev/null | grep -q '__stack_chk_fail'; then |
|||
echo -n -e '\033[32mCanary found \033[m ' |
|||
else |
|||
echo -n -e '\033[31mNo canary found\033[m ' |
|||
fi |
|||
|
|||
# check for NX support |
|||
if readelf -W -l $1 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then |
|||
echo -n -e '\033[31mNX disabled\033[m ' |
|||
else |
|||
echo -n -e '\033[32mNX enabled \033[m ' |
|||
fi |
|||
|
|||
# check for PIE support |
|||
if readelf -h $1 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then |
|||
echo -n -e '\033[31mNo PIE \033[m ' |
|||
elif readelf -h $1 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then |
|||
if readelf -d $1 2>/dev/null | grep -q '(DEBUG)'; then |
|||
echo -n -e '\033[32mPIE enabled \033[m ' |
|||
else |
|||
echo -n -e '\033[33mDSO \033[m ' |
|||
fi |
|||
else |
|||
echo -n -e '\033[33mNot an ELF file\033[m ' |
|||
fi |
|||
|
|||
# check for rpath / run path |
|||
if readelf -d $1 2>/dev/null | grep -q 'rpath'; then |
|||
echo -n -e '\033[31mRPATH \033[m ' |
|||
else |
|||
echo -n -e '\033[32mNo RPATH \033[m ' |
|||
fi |
|||
|
|||
if readelf -d $1 2>/dev/null | grep -q 'runpath'; then |
|||
echo -n -e '\033[31mRUNPATH \033[m ' |
|||
else |
|||
echo -n -e '\033[32mNo RUNPATH \033[m ' |
|||
fi |
|||
} |
|||
|
|||
# check process(es) |
|||
proccheck() { |
|||
# check for RELRO support |
|||
if readelf -l $1/exe 2>/dev/null | grep -q 'Program Headers'; then |
|||
if readelf -l $1/exe 2>/dev/null | grep -q 'GNU_RELRO'; then |
|||
if readelf -d $1/exe 2>/dev/null | grep -q 'BIND_NOW'; then |
|||
echo -n -e '\033[32mFull RELRO \033[m ' |
|||
else |
|||
echo -n -e '\033[33mPartial RELRO \033[m ' |
|||
fi |
|||
else |
|||
echo -n -e '\033[31mNo RELRO \033[m ' |
|||
fi |
|||
else |
|||
echo -n -e '\033[31mPermission denied (please run as root)\033[m\n' |
|||
exit 1 |
|||
fi |
|||
|
|||
# check for stack canary support |
|||
if readelf -s $1/exe 2>/dev/null | grep -q 'Symbol table'; then |
|||
if readelf -s $1/exe 2>/dev/null | grep -q '__stack_chk_fail'; then |
|||
echo -n -e '\033[32mCanary found \033[m ' |
|||
else |
|||
echo -n -e '\033[31mNo canary found \033[m ' |
|||
fi |
|||
else |
|||
if [ "$1" != "1" ] ; then |
|||
echo -n -e '\033[33mPermission denied \033[m ' |
|||
else |
|||
echo -n -e '\033[33mNo symbol table found\033[m ' |
|||
fi |
|||
fi |
|||
|
|||
# first check for PaX support |
|||
if cat $1/status 2> /dev/null | grep -q 'PaX:'; then |
|||
pageexec=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b6) ) |
|||
segmexec=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b10) ) |
|||
mprotect=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b8) ) |
|||
randmmap=( $(cat $1/status 2> /dev/null | grep 'PaX:' | cut -b9) ) |
|||
if [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "M" && "$randmmap" = "R" ]] ; then |
|||
echo -n -e '\033[32mPaX enabled\033[m ' |
|||
elif [[ "$pageexec" = "p" && "$segmexec" = "s" && "$randmmap" = "R" ]] ; then |
|||
echo -n -e '\033[33mPaX ASLR only\033[m ' |
|||
elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "m" && "$randmmap" = "R" ]] ; then |
|||
echo -n -e '\033[33mPaX mprot off \033[m' |
|||
elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "M" && "$randmmap" = "r" ]] ; then |
|||
echo -n -e '\033[33mPaX ASLR off\033[m ' |
|||
elif [[ "$pageexec" = "P" || "$segmexec" = "S" ]] && [[ "$mprotect" = "m" && "$randmmap" = "r" ]] ; then |
|||
echo -n -e '\033[33mPaX NX only\033[m ' |
|||
else |
|||
echo -n -e '\033[31mPaX disabled\033[m ' |
|||
fi |
|||
# fallback check for NX support |
|||
elif readelf -W -l $1/exe 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then |
|||
echo -n -e '\033[31mNX disabled\033[m ' |
|||
else |
|||
echo -n -e '\033[32mNX enabled \033[m ' |
|||
fi |
|||
|
|||
# check for PIE support |
|||
if readelf -h $1/exe 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then |
|||
echo -n -e '\033[31mNo PIE \033[m ' |
|||
elif readelf -h $1/exe 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then |
|||
if readelf -d $1/exe 2>/dev/null | grep -q '(DEBUG)'; then |
|||
echo -n -e '\033[32mPIE enabled \033[m ' |
|||
else |
|||
echo -n -e '\033[33mDynamic Shared Object\033[m ' |
|||
fi |
|||
else |
|||
echo -n -e '\033[33mNot an ELF file \033[m ' |
|||
fi |
|||
} |
|||
|
|||
# check mapped libraries |
|||
libcheck() { |
|||
libs=( $(awk '{ print $6 }' /proc/$1/maps | grep '/' | sort -u | xargs file | grep ELF | awk '{ print $1 }' | sed 's/:/ /') ) |
|||
|
|||
printf "\n* Loaded libraries (file information, # of mapped files: ${#libs[@]}):\n\n" |
|||
|
|||
for element in $(seq 0 $((${#libs[@]} - 1))) |
|||
do |
|||
echo " ${libs[$element]}:" |
|||
echo -n " " |
|||
filecheck ${libs[$element]} |
|||
printf "\n\n" |
|||
done |
|||
} |
|||
|
|||
# check for system-wide ASLR support |
|||
aslrcheck() { |
|||
# PaX ASLR support |
|||
if !(cat /proc/1/status 2> /dev/null | grep -q 'Name:') ; then |
|||
echo -n -e ':\033[33m insufficient privileges for PaX ASLR checks\033[m\n' |
|||
echo -n -e ' Fallback to standard Linux ASLR check' |
|||
fi |
|||
|
|||
if cat /proc/1/status 2> /dev/null | grep -q 'PaX:'; then |
|||
printf ": " |
|||
if cat /proc/1/status 2> /dev/null | grep 'PaX:' | grep -q 'R'; then |
|||
echo -n -e '\033[32mPaX ASLR enabled\033[m\n\n' |
|||
else |
|||
echo -n -e '\033[31mPaX ASLR disabled\033[m\n\n' |
|||
fi |
|||
else |
|||
# standard Linux 'kernel.randomize_va_space' ASLR support |
|||
# (see the kernel file 'Documentation/sysctl/kernel.txt' for a detailed description) |
|||
printf " (kernel.randomize_va_space): " |
|||
if /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 1'; then |
|||
echo -n -e '\033[33mOn (Setting: 1)\033[m\n\n' |
|||
printf " Description - Make the addresses of mmap base, stack and VDSO page randomized.\n" |
|||
printf " This, among other things, implies that shared libraries will be loaded to \n" |
|||
printf " random addresses. Also for PIE-linked binaries, the location of code start\n" |
|||
printf " is randomized. Heap addresses are *not* randomized.\n\n" |
|||
elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 2'; then |
|||
echo -n -e '\033[32mOn (Setting: 2)\033[m\n\n' |
|||
printf " Description - Make the addresses of mmap base, heap, stack and VDSO page randomized.\n" |
|||
printf " This, among other things, implies that shared libraries will be loaded to random \n" |
|||
printf " addresses. Also for PIE-linked binaries, the location of code start is randomized.\n\n" |
|||
elif /sbin/sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 0'; then |
|||
echo -n -e '\033[31mOff (Setting: 0)\033[m\n' |
|||
else |
|||
echo -n -e '\033[31mNot supported\033[m\n' |
|||
fi |
|||
printf " See the kernel file 'Documentation/sysctl/kernel.txt' for more details.\n\n" |
|||
fi |
|||
} |
|||
|
|||
# check cpu nx flag |
|||
nxcheck() { |
|||
if grep -q nx /proc/cpuinfo; then |
|||
echo -n -e '\033[32mYes\033[m\n\n' |
|||
else |
|||
echo -n -e '\033[31mNo\033[m\n\n' |
|||
fi |
|||
} |
|||
|
|||
# check for kernel protection mechanisms |
|||
kernelcheck() { |
|||
printf " Description - List the status of kernel protection mechanisms. Rather than\n" |
|||
printf " inspect kernel mechanisms that may aid in the prevention of exploitation of\n" |
|||
printf " userspace processes, this option lists the status of kernel configuration\n" |
|||
printf " options that harden the kernel itself against attack.\n\n" |
|||
printf " Kernel config: " |
|||
|
|||
if [ -f /proc/config.gz ] ; then |
|||
kconfig="zcat /proc/config.gz" |
|||
printf "\033[32m/proc/config.gz\033[m\n\n" |
|||
elif [ -f /boot/config-`uname -r` ] ; then |
|||
kconfig="cat /boot/config-`uname -r`" |
|||
printf "\033[33m/boot/config-`uname -r`\033[m\n\n" |
|||
printf " Warning: The config on disk may not represent running kernel config!\n\n"; |
|||
elif [ -f "${KBUILD_OUTPUT:-/usr/src/linux}"/.config ] ; then |
|||
kconfig="cat ${KBUILD_OUTPUT:-/usr/src/linux}/.config" |
|||
printf "\033[33m%s\033[m\n\n" "${KBUILD_OUTPUT:-/usr/src/linux}/.config" |
|||
printf " Warning: The config on disk may not represent running kernel config!\n\n"; |
|||
else |
|||
printf "\033[31mNOT FOUND\033[m\n\n" |
|||
exit 0 |
|||
fi |
|||
|
|||
printf " GCC stack protector support: " |
|||
if $kconfig | grep -qi 'CONFIG_CC_STACKPROTECTOR=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
|
|||
printf " Strict user copy checks: " |
|||
if $kconfig | grep -qi 'CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
|
|||
printf " Enforce read-only kernel data: " |
|||
if $kconfig | grep -qi 'CONFIG_DEBUG_RODATA=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
printf " Restrict /dev/mem access: " |
|||
if $kconfig | grep -qi 'CONFIG_STRICT_DEVMEM=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
|
|||
printf " Restrict /dev/kmem access: " |
|||
if $kconfig | grep -qi 'CONFIG_DEVKMEM=y'; then |
|||
printf "\033[31mDisabled\033[m\n" |
|||
else |
|||
printf "\033[32mEnabled\033[m\n" |
|||
fi |
|||
|
|||
printf "\n" |
|||
printf "* grsecurity / PaX: " |
|||
|
|||
if $kconfig | grep -qi 'CONFIG_GRKERNSEC=y'; then |
|||
if $kconfig | grep -qi 'CONFIG_GRKERNSEC_HIGH=y'; then |
|||
printf "\033[32mHigh GRKERNSEC\033[m\n\n" |
|||
elif $kconfig | grep -qi 'CONFIG_GRKERNSEC_MEDIUM=y'; then |
|||
printf "\033[33mMedium GRKERNSEC\033[m\n\n" |
|||
elif $kconfig | grep -qi 'CONFIG_GRKERNSEC_LOW=y'; then |
|||
printf "\033[31mLow GRKERNSEC\033[m\n\n" |
|||
else |
|||
printf "\033[33mCustom GRKERNSEC\033[m\n\n" |
|||
fi |
|||
|
|||
printf " Non-executable kernel pages: " |
|||
if $kconfig | grep -qi 'CONFIG_PAX_KERNEXEC=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
|
|||
printf " Prevent userspace pointer deref: " |
|||
if $kconfig | grep -qi 'CONFIG_PAX_MEMORY_UDEREF=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
|
|||
printf " Prevent kobject refcount overflow: " |
|||
if $kconfig | grep -qi 'CONFIG_PAX_REFCOUNT=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
|
|||
printf " Bounds check heap object copies: " |
|||
if $kconfig | grep -qi 'CONFIG_PAX_USERCOPY=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
|
|||
printf " Disable writing to kmem/mem/port: " |
|||
if $kconfig | grep -qi 'CONFIG_GRKERNSEC_KMEM=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
|
|||
printf " Disable privileged I/O: " |
|||
if $kconfig | grep -qi 'CONFIG_GRKERNSEC_IO=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
|
|||
printf " Harden module auto-loading: " |
|||
if $kconfig | grep -qi 'CONFIG_GRKERNSEC_MODHARDEN=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
|
|||
printf " Hide kernel symbols: " |
|||
if $kconfig | grep -qi 'CONFIG_GRKERNSEC_HIDESYM=y'; then |
|||
printf "\033[32mEnabled\033[m\n" |
|||
else |
|||
printf "\033[31mDisabled\033[m\n" |
|||
fi |
|||
else |
|||
printf "\033[31mNo GRKERNSEC\033[m\n\n" |
|||
printf " The grsecurity / PaX patchset is available here:\n" |
|||
printf " http://grsecurity.net/\n" |
|||
fi |
|||
|
|||
printf "\n" |
|||
printf "* Kernel Heap Hardening: " |
|||
|
|||
if $kconfig | grep -qi 'CONFIG_KERNHEAP=y'; then |
|||
if $kconfig | grep -qi 'CONFIG_KERNHEAP_FULLPOISON=y'; then |
|||
printf "\033[32mFull KERNHEAP\033[m\n\n" |
|||
else |
|||
printf "\033[33mPartial KERNHEAP\033[m\n\n" |
|||
fi |
|||
else |
|||
printf "\033[31mNo KERNHEAP\033[m\n\n" |
|||
printf " The KERNHEAP hardening patchset is available here:\n" |
|||
printf " https://www.subreption.com/kernheap/\n\n" |
|||
fi |
|||
} |
|||
|
|||
# --- FORTIFY_SOURCE subfunctions (start) --- |
|||
|
|||
# is FORTIFY_SOURCE supported by libc? |
|||
FS_libc_check() { |
|||
printf "* FORTIFY_SOURCE support available (libc) : " |
|||
|
|||
if [ "${#FS_chk_func_libc[@]}" != "0" ] ; then |
|||
printf "\033[32mYes\033[m\n" |
|||
else |
|||
printf "\033[31mNo\033[m\n" |
|||
exit 1 |
|||
fi |
|||
} |
|||
|
|||
# was the binary compiled with FORTIFY_SOURCE? |
|||
FS_binary_check() { |
|||
printf "* Binary compiled with FORTIFY_SOURCE support: " |
|||
|
|||
for FS_elem_functions in $(seq 0 $((${#FS_functions[@]} - 1))) |
|||
do |
|||
if [[ ${FS_functions[$FS_elem_functions]} =~ _chk ]] ; then |
|||
printf "\033[32mYes\033[m\n" |
|||
return |
|||
fi |
|||
done |
|||
printf "\033[31mNo\033[m\n" |
|||
exit 1 |
|||
} |
|||
|
|||
FS_comparison() { |
|||
echo |
|||
printf " ------ EXECUTABLE-FILE ------- . -------- LIBC --------\n" |
|||
printf " FORTIFY-able library functions | Checked function names\n" |
|||
printf " -------------------------------------------------------\n" |
|||
|
|||
for FS_elem_libc in $(seq 0 $((${#FS_chk_func_libc[@]} - 1))) |
|||
do |
|||
for FS_elem_functions in $(seq 0 $((${#FS_functions[@]} - 1))) |
|||
do |
|||
FS_tmp_func=${FS_functions[$FS_elem_functions]} |
|||
FS_tmp_libc=${FS_chk_func_libc[$FS_elem_libc]} |
|||
|
|||
if [[ $FS_tmp_func =~ ^$FS_tmp_libc$ ]] ; then |
|||
printf " \033[31m%-30s\033[m | __%s%s\n" $FS_tmp_func $FS_tmp_libc $FS_end |
|||
let FS_cnt_total++ |
|||
let FS_cnt_unchecked++ |
|||
elif [[ $FS_tmp_func =~ ^$FS_tmp_libc(_chk) ]] ; then |
|||
printf " \033[32m%-30s\033[m | __%s%s\n" $FS_tmp_func $FS_tmp_libc $FS_end |
|||
let FS_cnt_total++ |
|||
let FS_cnt_checked++ |
|||
fi |
|||
|
|||
done |
|||
done |
|||
} |
|||
|
|||
FS_summary() { |
|||
echo |
|||
printf "SUMMARY:\n\n" |
|||
printf "* Number of checked functions in libc : ${#FS_chk_func_libc[@]}\n" |
|||
printf "* Total number of library functions in the executable: ${#FS_functions[@]}\n" |
|||
printf "* Number of FORTIFY-able functions in the executable : %s\n" $FS_cnt_total |
|||
printf "* Number of checked functions in the executable : \033[32m%s\033[m\n" $FS_cnt_checked |
|||
printf "* Number of unchecked functions in the executable : \033[31m%s\033[m\n" $FS_cnt_unchecked |
|||
echo |
|||
} |
|||
|
|||
# --- FORTIFY_SOURCE subfunctions (end) --- |
|||
|
|||
if !(command_exists readelf) ; then |
|||
printf "\033[31mWarning: 'readelf' not found! It's required for most checks.\033[m\n\n" |
|||
have_readelf=0 |
|||
fi |
|||
|
|||
# parse command-line arguments |
|||
case "$1" in |
|||
|
|||
--version) |
|||
version |
|||
exit 0 |
|||
;; |
|||
|
|||
--help) |
|||
help |
|||
exit 0 |
|||
;; |
|||
|
|||
--dir) |
|||
if [ "$3" = "-v" ] ; then |
|||
verbose=true |
|||
fi |
|||
if [ $have_readelf -eq 0 ] ; then |
|||
exit 1 |
|||
fi |
|||
if [ -z "$2" ] ; then |
|||
printf "\033[31mError: Please provide a valid directory.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
# remove trailing slashes |
|||
tempdir=`echo $2 | sed -e "s/\/*$//"` |
|||
if [ ! -d $tempdir ] ; then |
|||
printf "\033[31mError: The directory '$tempdir' does not exist.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
cd $tempdir |
|||
printf "RELRO STACK CANARY NX PIE RPATH RUNPATH FILE\n" |
|||
for N in [A-Za-z]*; do |
|||
if [ "$N" != "[A-Za-z]*" ]; then |
|||
# read permissions? |
|||
if [ ! -r $N ]; then |
|||
printf "\033[31mError: No read permissions for '$tempdir/$N' (run as root).\033[m\n" |
|||
else |
|||
# ELF executable? |
|||
out=`file $N` |
|||
if [[ ! $out =~ ELF ]] ; then |
|||
if [ "$verbose" = "true" ] ; then |
|||
printf "\033[34m*** Not an ELF file: $tempdir/" |
|||
file $N |
|||
printf "\033[m" |
|||
fi |
|||
else |
|||
filecheck $N |
|||
if [ `find $tempdir/$N \( -perm -004000 -o -perm -002000 \) -type f -print` ]; then |
|||
printf "\033[37;41m%s%s\033[m" $2 $N |
|||
else |
|||
printf "%s%s" $tempdir/ $N |
|||
fi |
|||
echo |
|||
fi |
|||
fi |
|||
fi |
|||
done |
|||
exit 0 |
|||
;; |
|||
|
|||
--file) |
|||
if [ $have_readelf -eq 0 ] ; then |
|||
exit 1 |
|||
fi |
|||
if [ -z "$2" ] ; then |
|||
printf "\033[31mError: Please provide a valid file.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
# does the file exist? |
|||
if [ ! -e $2 ] ; then |
|||
printf "\033[31mError: The file '$2' does not exist.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
# read permissions? |
|||
if [ ! -r $2 ] ; then |
|||
printf "\033[31mError: No read permissions for '$2' (run as root).\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
# ELF executable? |
|||
out=`file $2` |
|||
if [[ ! $out =~ ELF ]] ; then |
|||
printf "\033[31mError: Not an ELF file: " |
|||
file $2 |
|||
printf "\033[m\n" |
|||
exit 1 |
|||
fi |
|||
printf "RELRO STACK CANARY NX PIE RPATH RUNPATH FILE\n" |
|||
filecheck $2 |
|||
if [ `find $2 \( -perm -004000 -o -perm -002000 \) -type f -print` ] ; then |
|||
printf "\033[37;41m%s%s\033[m" $2 $N |
|||
else |
|||
printf "%s" $2 |
|||
fi |
|||
echo |
|||
exit 0 |
|||
;; |
|||
|
|||
--proc-all) |
|||
if [ $have_readelf -eq 0 ] ; then |
|||
exit 1 |
|||
fi |
|||
cd /proc |
|||
printf "* System-wide ASLR" |
|||
aslrcheck |
|||
printf "* Does the CPU support NX: " |
|||
nxcheck |
|||
printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" |
|||
for N in [1-9]*; do |
|||
if [ $N != $$ ] && readlink -q $N/exe > /dev/null; then |
|||
printf "%16s" `head -1 $N/status | cut -b 7-` |
|||
printf "%7d " $N |
|||
proccheck $N |
|||
echo |
|||
fi |
|||
done |
|||
if [ ! -e /usr/bin/id ] ; then |
|||
printf "\n\033[33mNote: If you are running 'checksec.sh' as an unprivileged user, you\n" |
|||
printf " will not see all processes. Please run the script as root.\033[m\n\n" |
|||
else |
|||
if !(root_privs) ; then |
|||
printf "\n\033[33mNote: You are running 'checksec.sh' as an unprivileged user.\n" |
|||
printf " Too see all processes, please run the script as root.\033[m\n\n" |
|||
fi |
|||
fi |
|||
exit 0 |
|||
;; |
|||
|
|||
--proc) |
|||
if [ $have_readelf -eq 0 ] ; then |
|||
exit 1 |
|||
fi |
|||
if [ -z "$2" ] ; then |
|||
printf "\033[31mError: Please provide a valid process name.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
if !(isString "$2") ; then |
|||
printf "\033[31mError: Please provide a valid process name.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
cd /proc |
|||
printf "* System-wide ASLR" |
|||
aslrcheck |
|||
printf "* Does the CPU support NX: " |
|||
nxcheck |
|||
printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" |
|||
for N in `ps -Ao pid,comm | grep $2 | cut -b1-6`; do |
|||
if [ -d $N ] ; then |
|||
printf "%16s" `head -1 $N/status | cut -b 7-` |
|||
printf "%7d " $N |
|||
# read permissions? |
|||
if [ ! -r $N/exe ] ; then |
|||
if !(root_privs) ; then |
|||
printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
if [ ! `readlink $N/exe` ] ; then |
|||
printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
exit 1 |
|||
fi |
|||
proccheck $N |
|||
echo |
|||
fi |
|||
done |
|||
exit 0 |
|||
;; |
|||
|
|||
--proc-libs) |
|||
if [ $have_readelf -eq 0 ] ; then |
|||
exit 1 |
|||
fi |
|||
if [ -z "$2" ] ; then |
|||
printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
if !(isNumeric "$2") ; then |
|||
printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
cd /proc |
|||
printf "* System-wide ASLR" |
|||
aslrcheck |
|||
printf "* Does the CPU support NX: " |
|||
nxcheck |
|||
printf "* Process information:\n\n" |
|||
printf " COMMAND PID RELRO STACK CANARY NX/PaX PIE\n" |
|||
N=$2 |
|||
if [ -d $N ] ; then |
|||
printf "%16s" `head -1 $N/status | cut -b 7-` |
|||
printf "%7d " $N |
|||
# read permissions? |
|||
if [ ! -r $N/exe ] ; then |
|||
if !(root_privs) ; then |
|||
printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
if [ ! `readlink $N/exe` ] ; then |
|||
printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
exit 1 |
|||
fi |
|||
proccheck $N |
|||
echo |
|||
libcheck $N |
|||
fi |
|||
exit 0 |
|||
;; |
|||
|
|||
--kernel) |
|||
cd /proc |
|||
printf "* Kernel protection information:\n\n" |
|||
kernelcheck |
|||
exit 0 |
|||
;; |
|||
|
|||
--fortify-file) |
|||
if [ $have_readelf -eq 0 ] ; then |
|||
exit 1 |
|||
fi |
|||
if [ -z "$2" ] ; then |
|||
printf "\033[31mError: Please provide a valid file.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
# does the file exist? |
|||
if [ ! -e $2 ] ; then |
|||
printf "\033[31mError: The file '$2' does not exist.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
# read permissions? |
|||
if [ ! -r $2 ] ; then |
|||
printf "\033[31mError: No read permissions for '$2' (run as root).\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
# ELF executable? |
|||
out=`file $2` |
|||
if [[ ! $out =~ ELF ]] ; then |
|||
printf "\033[31mError: Not an ELF file: " |
|||
file $2 |
|||
printf "\033[m\n" |
|||
exit 1 |
|||
fi |
|||
if [ -e /lib/libc.so.6 ] ; then |
|||
FS_libc=/lib/libc.so.6 |
|||
elif [ -e /lib64/libc.so.6 ] ; then |
|||
FS_libc=/lib64/libc.so.6 |
|||
elif [ -e /lib/i386-linux-gnu/libc.so.6 ] ; then |
|||
FS_libc=/lib/i386-linux-gnu/libc.so.6 |
|||
elif [ -e /lib/x86_64-linux-gnu/libc.so.6 ] ; then |
|||
FS_libc=/lib/x86_64-linux-gnu/libc.so.6 |
|||
else |
|||
printf "\033[31mError: libc not found.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
|
|||
FS_chk_func_libc=( $(readelf -s $FS_libc | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') ) |
|||
FS_functions=( $(readelf -s $2 | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') ) |
|||
|
|||
FS_libc_check |
|||
FS_binary_check |
|||
FS_comparison |
|||
FS_summary |
|||
|
|||
exit 0 |
|||
;; |
|||
|
|||
--fortify-proc) |
|||
if [ $have_readelf -eq 0 ] ; then |
|||
exit 1 |
|||
fi |
|||
if [ -z "$2" ] ; then |
|||
printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
if !(isNumeric "$2") ; then |
|||
printf "\033[31mError: Please provide a valid process ID.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
cd /proc |
|||
N=$2 |
|||
if [ -d $N ] ; then |
|||
# read permissions? |
|||
if [ ! -r $N/exe ] ; then |
|||
if !(root_privs) ; then |
|||
printf "\033[31mNo read permissions for '/proc/$N/exe' (run as root).\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
if [ ! `readlink $N/exe` ] ; then |
|||
printf "\033[31mPermission denied. Requested process ID belongs to a kernel thread.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
exit 1 |
|||
fi |
|||
if [ -e /lib/libc.so.6 ] ; then |
|||
FS_libc=/lib/libc.so.6 |
|||
elif [ -e /lib64/libc.so.6 ] ; then |
|||
FS_libc=/lib64/libc.so.6 |
|||
elif [ -e /lib/i386-linux-gnu/libc.so.6 ] ; then |
|||
FS_libc=/lib/i386-linux-gnu/libc.so.6 |
|||
elif [ -e /lib/x86_64-linux-gnu/libc.so.6 ] ; then |
|||
FS_libc=/lib/x86_64-linux-gnu/libc.so.6 |
|||
else |
|||
printf "\033[31mError: libc not found.\033[m\n\n" |
|||
exit 1 |
|||
fi |
|||
printf "* Process name (PID) : %s (%d)\n" `head -1 $N/status | cut -b 7-` $N |
|||
FS_chk_func_libc=( $(readelf -s $FS_libc | grep _chk@@ | awk '{ print $8 }' | cut -c 3- | sed -e 's/_chk@.*//') ) |
|||
FS_functions=( $(readelf -s $2/exe | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') ) |
|||
|
|||
FS_libc_check |
|||
FS_binary_check |
|||
FS_comparison |
|||
FS_summary |
|||
fi |
|||
exit 0 |
|||
;; |
|||
|
|||
*) |
|||
if [ "$#" != "0" ] ; then |
|||
printf "\033[31mError: Unknown option '$1'.\033[m\n\n" |
|||
fi |
|||
help |
|||
exit 1 |
|||
;; |
|||
esac |
Loading…
Reference in new issue