checksec 90.9 KB
Newer Older
1
#!/usr/bin/env bash
Robin David's avatar
Robin David committed
2
#
3
# The BSD License (http://www.opensource.org/licenses/bsd-license.php)
Robin David's avatar
Robin David committed
4
5
# specifies the terms and conditions of use for checksec.sh:
#
6
# Copyright (c) 2014-2020, Brian Davis
slimm609's avatar
signed    
slimm609 committed
7
8
# Copyright (c) 2013, Robin David
# Copyright (c) 2009-2011, Tobias Klein
Robin David's avatar
Robin David committed
9
10
# All rights reserved.
#
11
12
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
Robin David's avatar
Robin David committed
13
# are met:
14
15
#
# * Redistributions of source code must retain the above copyright
Robin David's avatar
Robin David committed
16
#   notice, this list of conditions and the following disclaimer.
17
18
19
# * 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
Robin David's avatar
Robin David committed
20
#   distribution.
21
22
# * Neither the name of Tobias Klein nor the name of trapkit.de may be
#   used to endorse or promote products derived from this software
Robin David's avatar
Robin David committed
23
24
#   without specific prior written permission.
#
25
26
27
28
29
30
31
32
33
34
35
# 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
Robin David's avatar
Robin David committed
36
37
# DAMAGE.
#
38
# --- Modified Version ---
slimm609's avatar
slimm609 committed
39
# Name    : checksec.sh
slimm609's avatar
signed    
slimm609 committed
40
# Version : 1.7.0
41
# Author  : Brian Davis
slimm609's avatar
slimm609 committed
42
# Date    : Feburary 2014
43
44
# Download: https://github.com/slimm609/checksec.sh
#
Robin David's avatar
Robin David committed
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# --- Modified Version ---
# Name    : checksec.sh
# Version : based on 1.5
# Author  : Robin David
# Date    : October 2013
# Download: https://github.com/RobinDavid/checksec
#
# --- Original version ---
# 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

slimm609's avatar
signed    
slimm609 committed
60
61
#set global lang to C
export LC_ALL="C"
Robin David's avatar
Robin David committed
62
63

# global vars
slimm609's avatar
signed    
slimm609 committed
64
debug=false
Robin David's avatar
Robin David committed
65
66
verbose=false
format="cli"
slimm609's avatar
slimm609 committed
67
SCRIPT_NAME="checksec"
slimm609's avatar
slimm609 committed
68
SCRIPT_URL="https://github.com/slimm609/checksec.sh/raw/master/${SCRIPT_NAME}"
slimm609's avatar
slimm609 committed
69
SIG_URL="https://github.com/slimm609/checksec.sh/raw/master/$(basename ${SCRIPT_NAME} .sh).sig"
Brian Davis's avatar
Brian Davis committed
70
SCRIPT_VERSION=2020081501
slimm609's avatar
slimm609 committed
71
SCRIPT_MAJOR=2
Brian Davis's avatar
Brian Davis committed
72
SCRIPT_MINOR=4
Brian Davis's avatar
Brian Davis committed
73
SCRIPT_REVISION=0
slimm609's avatar
slimm609 committed
74
pkg_release=false
slimm609's avatar
slimm609 committed
75
76
commandsmissing=false
OPT=0
slimm609's avatar
slimm609 committed
77
extended_checks=false
slimm609's avatar
slimm609 committed
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# 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

# check for required files and deps first
# check if command exists
command_exists () {
  type "${1}"  > /dev/null 2>&1;
}

93
94
95
96
if [[ $(id -u) != 0 ]]; then
    export PATH=${PATH}:/sbin/:/usr/sbin/
fi

97
for command in cat awk sed sysctl uname mktemp openssl grep stat file find sort head ps readlink basename id which xargs; do
slimm609's avatar
slimm609 committed
98
    if ! (command_exists ${command}); then
irwincong's avatar
irwincong committed
99
       >&2 echo -e "\e[31mWARNING: '${command}' not found! It's required for most checks.\e[0m"
slimm609's avatar
slimm609 committed
100
101
102
103
       commandsmissing=true
    fi
done

104
if [[ ${commandsmissing} == true ]]; then
irwincong's avatar
irwincong committed
105
    >&2 echo -e "\n\e[31mWARNING: Not all necessary commands found. Some tests might not work!\e[0m\n"
slimm609's avatar
slimm609 committed
106
107
108
109
    sleep 2
fi

if (command_exists readelf); then
110
     readelf="readelf -W"
slimm609's avatar
slimm609 committed
111
elif (command_exists eu-readelf); then
112
     readelf="eu-readelf -W"
slimm609's avatar
slimm609 committed
113
elif (command_exists greadelf); then
114
     readelf="greadelf -W"
slimm609's avatar
slimm609 committed
115
116
117
118
119
else
    echo -e "\n\e[31mERROR: readelf is a required tool for almost all tests. Aborting...\e[0m\n"
    exit
fi

slimm609's avatar
signed    
slimm609 committed
120
sysarch=$(uname -m)
slimm609's avatar
slimm609 committed
121
if [[ "${sysarch}" == "x86_64" ]]; then
slimm609's avatar
signed    
slimm609 committed
122
    arch="64"
slimm609's avatar
slimm609 committed
123
elif [[ "${sysarch}" == "i?86" ]]; then
slimm609's avatar
signed    
slimm609 committed
124
    arch="32"
slimm609's avatar
slimm609 committed
125
elif [[ "${sysarch}" =~ "arm" ]]; then
slimm609's avatar
signed    
slimm609 committed
126
    arch="arm"
slimm609's avatar
slimm609 committed
127
elif [[ "${sysarch}" =~ "aarch64" ]]; then
Scott Ellis's avatar
Scott Ellis committed
128
    arch="aarch64"
slimm609's avatar
signed    
slimm609 committed
129
fi
slimm609's avatar
slimm609 committed
130
131

#openssl public key for verification of updates
slimm609's avatar
slimm609 committed
132
read -r PUBKEY <<EOF
slimm609's avatar
slimm609 committed
133
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF3Z25kcnk2WGJpNE8wR2w1T2UzSQp1eWRyMlZqR1hteDJFM0thd0wrK1F3a2FVT0RHOEVuT24weFZ1S1ZkZEphZjY3Rmxzd3pPYjh1RFRDTjdsWURnCnFKQXdmNllTOUFsdU5RRmlFQWhFRlgxL0dsMi9TSnFHYXhFVU9HTlV3NTI5a3BVR0MwNmN6SHhENEcvdWNBQlkKT05iWm9Vc1pIYmRnZUNueWs1dzZ0SWs3MEplNmZ2em5Da2JxbUZhS0UyQnhWTERLU0liSDBTak5XT3RSMmF6ZAp1V3p2RU1kVXFlZlZjYXErUDFjV0dLNy94VllSNkV3ME1aQTdWU0xkREhlRUVySW9Kc3UvM2VaeUR5ZDlaUlJvCmdpajM2R1N2SFREclU1ZVdXRlN0Q01UM29DRDhMSjVpbXBReWpWd3Z5M3Z4ZVNVYzVkdytZUDU0OU9jNHF2bzYKOXdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==
134
EOF
Robin David's avatar
Robin David committed
135

Brian Davis's avatar
Brian Davis committed
136
# Fetch the update
slimm609's avatar
slimm609 committed
137
fetch() {
slimm609's avatar
slimm609 committed
138
  if type wget > /dev/null 2>&1 ; then
slimm609's avatar
slimm609 committed
139
    ${debug} && echo "fetching update via wget"
slimm609's avatar
slimm609 committed
140
141
    wget --no-check-certificate -O "${2}" "${1}" >/dev/null 2>&1
  elif type curl > /dev/null 2>&1 ; then
slimm609's avatar
slimm609 committed
142
    ${debug} && echo "fetching update via curl"
slimm609's avatar
slimm609 committed
143
144
    curl --insecure --remote-name -o "${2}" "${1}" >/dev/null 2>&1
  else
145
    echo 'Warning: Neither wget nor curl is available. online updates unavailable' >&2
slimm609's avatar
slimm609 committed
146
147
    exit 1
  fi
slimm609's avatar
slimm609 committed
148
149
}

150
# Version compare
151
vercomp() {
slimm609's avatar
slimm609 committed
152
    if [[ "${1}" == "${2}" ]]
153
154
155
156
    then
        return 0
    fi
    local IFS=.
slimm609's avatar
slimm609 committed
157
    local i ver1="${1}" ver2="${2}"
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
    # fill empty fields in ver1 with zeros
    for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
    do
        ver1[i]=0
    done
    for ((i=0; i<${#ver1[@]}; i++))
    do
        if [[ -z ${ver2[i]} ]]
        then
            # fill empty fields in ver2 with zeros
            ver2[i]=0
        fi
        if ((10#${ver1[i]} > 10#${ver2[i]}))
        then
            return 1
        fi
        if ((10#${ver1[i]} < 10#${ver2[i]}))
        then
            return 2
        fi
    done
    return 0
}

slimm609's avatar
slimm609 committed
182
# Update/Upgrade
183
184
# shellcheck disable=SC2120
upgrade() {
slimm609's avatar
slimm609 committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  if ${pkg_release}; then
      printf "\033[31mError: Unknown option '%s'.\033[m\n\n" "${1}"
      help
      exit 1
    fi
  umask 027
  TMP_FILE=$(mktemp /tmp/checksec.XXXXXXXXXX)
  SIG_FILE=$(mktemp /tmp/checksec_sig.XXXXXXXX)
  PUBKEY_FILE=$(mktemp /tmp/checksec_pubkey.XXXXXXXXXX)
    fetch "${SCRIPT_URL}" "${TMP_FILE}"
    fetch "${SIG_URL}" "${SIG_FILE}"
  echo "${PUBKEY}" | base64 -d > "${PUBKEY_FILE}"
  if ! openssl dgst -sha256 -verify "${PUBKEY_FILE}" -signature "${SIG_FILE}" "${TMP_FILE}" >/dev/null 2>&1; then
    echo "file signature does not match. Update may be tampered"
    rm -f "${TMP_FILE}" "${SIG_FILE}" "${PUBKEY_FILE}" >/dev/null 2>&1
    exit 1
  fi
  UPDATE_VERSION=$(grep "^SCRIPT_VERSION" "${TMP_FILE}" | awk -F"=" '{ print $2 }')
  if [[ "${SCRIPT_VERSION}" != "${UPDATE_VERSION}" ]]; then
    PERMS=$(stat -c "%a" "$0")
    rm -f "${SIG_FILE}" "${PUBKEY_FILE}" >/dev/null 2>&1
    mv "${TMP_FILE}" "$0" >/dev/null 2>&1
    exit_status=$?
    if [[ "${exit_status}" -eq "0" ]]; then
      echo "checksec.sh updated - Rev. ${UPDATE_VERSION}"
      chmod "${PERMS}" "${0}"
    else
      echo "Error: Could not update... Please check permissions"
      rm -f "${TMP_FILE}" >/dev/null 2>&1
      exit 1
    fi
  else
    echo "checksec.sh not updated... Already on latest version"
    rm -f "${TMP_FILE}" "${SIG_FILE}" "${PUBKEY_FILE}" >/dev/null 2>&1
    exit 1
    fi
    exit 0
}
223

Robin David's avatar
Robin David committed
224
225
# version information
version() {
slimm609's avatar
slimm609 committed
226
  echo "checksec v${SCRIPT_MAJOR}.${SCRIPT_MINOR}.${SCRIPT_REVISION}, Brian Davis, github.com/slimm609/checksec.sh, Dec 2015"
227
  echo "Based off checksec v1.5, Tobias Klein, www.trapkit.de, November 2011"
228
  echo
Robin David's avatar
Robin David committed
229
230
231
232
}

# help
help() {
slimm609's avatar
slimm609 committed
233
  echo "Usage: checksec [--format={cli,csv,xml,json}] [OPTION]"
Robin David's avatar
Robin David committed
234
235
236
237
  echo
  echo
  echo "Options:"
  echo
slimm609's avatar
slimm609 committed
238
  echo " ## Checksec Options"
slimm609's avatar
slimm609 committed
239
240
  echo "  --file={file}"
  echo "  --dir={directory}"
David Suarez's avatar
David Suarez committed
241
  echo "  --listfile={text file with one file per line}"
slimm609's avatar
slimm609 committed
242
  echo "  --proc={process name}"
slimm609's avatar
slimm609 committed
243
  echo "  --proc-all"
slimm609's avatar
slimm609 committed
244
245
246
247
  echo "  --proc-libs={process ID}"
  echo "  --kernel[=kconfig]"
  echo "  --fortify-file={executable-file}"
  echo "  --fortify-proc={process ID}"
Robin David's avatar
Robin David committed
248
249
  echo "  --version"
  echo "  --help"
slimm609's avatar
slimm609 committed
250
251
  if ! ${pkg_release}; then
    echo "  --update or --upgrade"
slimm609's avatar
slimm609 committed
252
  fi
Robin David's avatar
Robin David committed
253
  echo
slimm609's avatar
slimm609 committed
254
255
256
  echo " ## Modifiers"
  echo "  --debug"
  echo "  --verbose"
slimm609's avatar
slimm609 committed
257
258
  echo "  --format={cli,csv,xml,json}"
  echo "  --output={cli,csv,xml,json}"
slimm609's avatar
slimm609 committed
259
  echo "  --extended"
slimm609's avatar
slimm609 committed
260
  echo
Robin David's avatar
Robin David committed
261
  echo "For more information, see:"
root's avatar
root committed
262
  echo "  http://github.com/slimm609/checksec.sh"
Robin David's avatar
Robin David committed
263
264
265
  echo
}

slimm609's avatar
slimm609 committed
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# format
format () {
  list="cli csv xml json"
  if [[ -n "${output_format}" ]]; then
    if [[ ! ${list} =~ ${output_format} ]]; then
  printf "\033[31mError: Please provide a valid format {cli, csv, xml, json}.\033[m\n\n"
  exit 1
    fi
  fi
  if [[ "${output_format}" == "xml" ]]; then
    echo '<?xml version="1.0" encoding="UTF-8"?>'
  fi
  format="${output_format}"
}

281
#run help if nothing is passed
slimm609's avatar
slimm609 committed
282
if [[ $# -lt 1 ]]; then
283
284
285
286
  help
  exit 1
fi

Robin David's avatar
Robin David committed
287
echo_message() {
slimm609's avatar
slimm609 committed
288
  if [[ ${format} == "csv" ]]; then
Robin David's avatar
Robin David committed
289
      echo -n -e "$2"
slimm609's avatar
slimm609 committed
290
  elif [[ ${format} == "xml" ]]; then
Robin David's avatar
Robin David committed
291
      echo -n -e "$3"
slimm609's avatar
slimm609 committed
292
  elif [[ ${format} == "json" ]]; then
293
      echo -n -e "$4"
294
  else #default to cli
slimm609's avatar
slimm609 committed
295
      echo -n -e "${1}"
Robin David's avatar
Robin David committed
296
297
298
  fi
}

Brian Davis's avatar
Brian Davis committed
299
# check selinux status
300
getsestatus() {
301
  local status
slimm609's avatar
slimm609 committed
302
  ${debug} && echo -e "\n***fuction getsestatus"
303
  if (command_exists getenforce); then
slimm609's avatar
slimm609 committed
304
    ${debug} && echo "***fuction getsestatus->getenforce"
305
    sestatus=$(getenforce)
slimm609's avatar
slimm609 committed
306
    if [[ "${sestatus}" == "Disabled" ]]; then
307
      status=0
slimm609's avatar
slimm609 committed
308
    elif [[ "${sestatus}" == "Permissive" ]]; then
slimm609's avatar
slimm609 committed
309
      status=1
slimm609's avatar
slimm609 committed
310
    elif [[ "${sestatus}" == "Enforcing" ]]; then
slimm609's avatar
slimm609 committed
311
312
      status=2
    fi
313
  elif (command_exists sestatus); then
slimm609's avatar
slimm609 committed
314
    ${debug} && echo "***fuction getsestatus->sestatus"
315
    sestatus=$(sestatus | grep "SELinux status" | awk '{ print $3}')
slimm609's avatar
slimm609 committed
316
    if [[ "${sestatus}" == "disabled" ]]; then
317
      status=0
slimm609's avatar
slimm609 committed
318
    elif [[ "${sestatus}" == "enabled" ]]; then
319
      sestatus2=$(sestatus | grep "Current" | awk '{ print $3}')
slimm609's avatar
slimm609 committed
320
      if [[ "${sestatus2}" == "permissive" ]]; then
321
        status=1
slimm609's avatar
slimm609 committed
322
      elif [[ "${sestatus2}" == "enforcing" ]]; then
323
324
325
        status=2
      fi
    fi
slimm609's avatar
slimm609 committed
326
  fi
slimm609's avatar
slimm609 committed
327
return ${status}
328
329
}

Robin David's avatar
Robin David committed
330
331
# check if directory exists
dir_exists () {
slimm609's avatar
slimm609 committed
332
333
  ${debug} && echo "fuction dir_exists"
  if [[ -d "${1}" ]] ; then
Robin David's avatar
Robin David committed
334
335
336
337
338
339
340
341
    return 0
  else
    return 1
  fi
}

# check user privileges
root_privs () {
slimm609's avatar
slimm609 committed
342
 ${debug} && echo "***function root_privs"
slimm609's avatar
slimm609 committed
343
  if [[ $(/usr/bin/id -u) -eq 0 ]] ; then
Robin David's avatar
Robin David committed
344
345
346
347
348
349
350
351
    return 0
  else
    return 1
  fi
}

# check if input is numeric
isNumeric () {
slimm609's avatar
slimm609 committed
352
  ${debug} && echo "***function isNumeric"
Robin David's avatar
Robin David committed
353
354
355
356
357
  echo "$@" | grep -q -v "[^0-9]"
}

# check if input is a string
isString () {
slimm609's avatar
slimm609 committed
358
  ${debug} && echo "***function isString"
359
  echo "$@" | grep -q -v "[^ A-Z_a-z]"
Robin David's avatar
Robin David committed
360
361
362
363
}

# check file(s)
filecheck() {
slimm609's avatar
slimm609 committed
364
  ${debug} && echo "***function filecheck"
Robin David's avatar
Robin David committed
365
  # check for RELRO support
slimm609's avatar
slimm609 committed
366
367
368
369
  ${debug} && echo "***function filecheck->RELRO"
  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_message '\033[32mFull RELRO   \033[m   ' 'Full RELRO,' '<file relro="full"' " \"${1}\": { \"relro\":\"full\","
Robin David's avatar
Robin David committed
370
    else
slimm609's avatar
slimm609 committed
371
      echo_message '\033[33mPartial RELRO\033[m   ' 'Partial RELRO,' '<file relro="partial"' " \"${1}\": { \"relro\":\"partial\","
Robin David's avatar
Robin David committed
372
373
    fi
  else
Brian Davis's avatar
Brian Davis committed
374
    echo_message '\033[31mNo RELRO     \033[m   ' 'No RELRO,' '<file relro="no"' " \"${1}\": { \"relro\":\"no\","
Robin David's avatar
Robin David committed
375
376
377
  fi

  # check for stack canary support
slimm609's avatar
slimm609 committed
378
379
  ${debug} && echo -e "\n***function filecheck->canary"
  if ${readelf} -s "${1}" 2>/dev/null | grep -Eq '__stack_chk_fail|__intel_security_cookie'; then
380
    echo_message '\033[32mCanary found   \033[m   ' 'Canary found,' ' canary="yes"' '"canary":"yes",'
Robin David's avatar
Robin David committed
381
  else
382
    echo_message '\033[31mNo canary found\033[m   ' 'No Canary found,' ' canary="no"' '"canary":"no",'
Robin David's avatar
Robin David committed
383
384
385
  fi

  # check for NX support
slimm609's avatar
slimm609 committed
386
  ${debug} && echo -e "\n***function filecheck->nx"
387
388
  if ${readelf} -l "${1}" 2>/dev/null | grep -q 'GNU_STACK'; then
    if ${readelf} -l "${1}" 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then
F3real's avatar
F3real committed
389
390
391
392
      echo_message '\033[31mNX disabled\033[m   ' 'NX disabled,' ' nx="no"' '"nx":"no",'
    else
      echo_message '\033[32mNX enabled \033[m   ' 'NX enabled,' ' nx="yes"' '"nx":"yes",'
    fi
Robin David's avatar
Robin David committed
393
  else
F3real's avatar
F3real committed
394
    echo_message '\033[31mNX disabled\033[m   ' 'NX disabled,' ' nx="no"' '"nx":"no",'
395
  fi
Robin David's avatar
Robin David committed
396
397

  # check for PIE support
slimm609's avatar
slimm609 committed
398
399
  ${debug} && echo -e "\n***function filecheck->pie"
  if ${readelf} -h "${1}" 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then
400
    echo_message '\033[31mNo PIE       \033[m   ' 'No PIE,' ' pie="no"' '"pie":"no",'
slimm609's avatar
slimm609 committed
401
402
  elif ${readelf} -h "${1}" 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then
    if ${readelf} -d "${1}" 2>/dev/null | grep -q 'DEBUG'; then
403
      echo_message '\033[32mPIE enabled  \033[m   ' 'PIE enabled,' ' pie="yes"' '"pie":"yes",'
404
    else
405
      echo_message '\033[33mDSO          \033[m   ' 'DSO,' ' pie="dso"' '"pie":"dso",'
Robin David's avatar
Robin David committed
406
    fi
Brian Davis's avatar
Brian Davis committed
407
408
  elif ${readelf} -h "${1}" 2>/dev/null | grep -q 'Type:[[:space:]]*REL'; then
    echo_message '\033[33mREL          \033[m   ' 'REL,' ' pie="rel"' '"pie":"rel",'
Robin David's avatar
Robin David committed
409
  else
410
    echo_message '\033[33mNot an ELF file\033[m   ' 'Not an ELF file,' ' pie="not_elf"' '"pie":"not_elf",'
411
  fi
Brian Davis's avatar
Brian Davis committed
412
413
414
415
416
417
418
419
420
  
  if ${extended_checks}; then
    # check for selfrando support
    ${debug} && echo -e "\n***function filecheck->selfrando"
    if ${readelf} -S "${1}" 2>/dev/null | grep -c txtrp | grep -q '1'; then
      echo_message '\033[32mSelfrando enabled  \033[m   '
    else
      echo_message '\033[31mNo Selfrando       \033[m   '
    fi
421
422
  fi

slimm609's avatar
slimm609 committed
423
424
425
426
  if ${extended_checks}; then
    # check if compiled with Clang CFI
    ${debug} && echo -e "\n***function filecheck->clangcfi"
    #if $readelf -s "$1" 2>/dev/null | grep -Eq '\.cfi'; then
427
    read -r cfifunc <<< "$($readelf -s "${1}" 2>/dev/null | grep .cfi | awk '{ print $8 }')"
slimm609's avatar
slimm609 committed
428
    func=${cfifunc/.cfi/}
429
    if [ -n "$cfifunc" ] && $readelf -s "$1" 2>/dev/null | grep -q "$func$"; then
slimm609's avatar
slimm609 committed
430
431
432
433
434
435
436
437
438
439
440
441
442
443
      echo_message '\033[32mClang CFI found   \033[m   ' 'with CFI,' ' clangcfi="yes"' '"clangcfi":"yes",'
    else
      echo_message '\033[31mNo Clang CFI found\033[m   ' 'without CFI,' ' clangcfi="no"' '"clangcfi":"no",'
    fi

    # check if compiled with Clang SafeStack
    ${debug} && echo -e "\n***function filecheck->safestack"
    if $readelf -s "$1" 2>/dev/null | grep -Eq '__safestack_init'; then
      echo_message '\033[32mSafeStack found   \033[m   ' 'with SafeStack,' ' safestack="yes"' '"safestack":"yes",'
    else
      echo_message '\033[31mNo SafeStack found\033[m   ' 'without SafeStack,' ' safestack="no"' '"safestack":"no",'
    fi
  fi

Robin David's avatar
Robin David committed
444
  # check for rpath / run path
slimm609's avatar
slimm609 committed
445
  ${debug} && echo -e "\n***function filecheck->rpath"
446
447
  # search for a line that matches RPATH and extract the colon-separated path list within brackets
  # example input: "0x000000000000000f (RPATH) Library rpath: [/lib/systemd:/lib/apparmor]"
448
  IFS=: read -r -a rpath_array <<< "$(${readelf} -d "${1}" 2>/dev/null | awk -F'[][]' '/RPATH/ {print $2}')"
449
  if [[ "${#rpath_array[@]}" -gt 0 ]]; then
450
    if xargs stat -c %A <<< "${rpath_array[*]}" 2>/dev/null | grep -q 'rw'; then
451
      echo_message '\033[31mRW-RPATH \033[m  ' 'RPATH,' ' rpath="yes"' '"rpath":"yes",'
452
    else
453
      echo_message '\033[31mRPATH   \033[m  ' 'RPATH,' ' rpath="yes"' '"rpath":"yes",'
454
    fi
Robin David's avatar
Robin David committed
455
  else
456
    echo_message '\033[32mNo RPATH \033[m  ' 'No RPATH,' ' rpath="no"' '"rpath":"no",'
Robin David's avatar
Robin David committed
457
458
  fi

slimm609's avatar
slimm609 committed
459
  ${debug} && echo -e "\n***function filecheck->runpath"
460
  # search for a line that matches RUNPATH and extract the colon-separated path list within brackets
461
  IFS=: read -r -a runpath_array <<< "$(${readelf} -d "${1}" 2>/dev/null | awk -F'[][]' '/RUNPATH/ {print $2}')"
462
  if [[ "${#runpath_array[@]}" -gt 0 ]]; then
463
    if xargs stat -c %A <<< "${runpath_array[*]}" 2>/dev/null | grep -q 'rw'; then
464
      echo_message '\033[31mRW-RUNPATH \033[m  ' 'RUNPATH,' ' runpath="yes"' '"runpath":"yes",'
465
    else
466
      echo_message '\033[31mRUNPATH   \033[m  ' 'RUNPATH,' ' runpath="yes"' '"runpath":"yes",'
467
    fi
Robin David's avatar
Robin David committed
468
  else
469
   echo_message '\033[32mNo RUNPATH \033[m  ' 'No RUNPATH,' ' runpath="no"' '"runpath":"no",'
Robin David's avatar
Robin David committed
470
  fi
471

472
  # check for stripped symbols in the binary
Brian Davis's avatar
Brian Davis committed
473
  IFS=" " read -r -a SYM_cnt <<< "$(${readelf} --symbols "${1}" 2>/dev/null | grep '\.symtab' | cut -d' ' -f5 | cut -d: -f1))"
slimm609's avatar
slimm609 committed
474
  if ${readelf} --symbols "${1}" 2>/dev/null | grep -q '\.symtab'; then
Brian Davis's avatar
Brian Davis committed
475
    echo_message "\033[31m${SYM_cnt[0]} Symbols\t\033[m  " 'Symbols,' ' symbols="yes"' '"symbols":"yes",'
476
  else
Brian Davis's avatar
Brian Davis committed
477
    echo_message '\033[32mNo Symbols\t\033[m  ' 'No Symbols,' ' symbols="no"' '"symbols":"no",'
478
479
  fi

480
  # check for FORTIFY SOURCE
slimm609's avatar
slimm609 committed
481
  ${debug} && echo "***function filecheck->fortify"
slimm609's avatar
slimm609 committed
482
  if [[ -e /lib/libc.so.6 ]] ; then
slimm609's avatar
slimm609 committed
483
    FS_libc=/lib/libc.so.6
484
485
  elif [[ -e /lib/libc.so.7 ]] ; then
    FS_libc=/lib/libc.so.7
slimm609's avatar
slimm609 committed
486
  elif [[ -e /lib/libc.so ]] ; then
rofl0r's avatar
rofl0r committed
487
    FS_libc=/lib/libc.so
slimm609's avatar
slimm609 committed
488
  elif [[ -e /lib64/libc.so.6 ]] ; then
slimm609's avatar
slimm609 committed
489
    FS_libc=/lib64/libc.so.6
slimm609's avatar
slimm609 committed
490
  elif [[ -e /lib/i386-linux-gnu/libc.so.6 ]] ; then
slimm609's avatar
slimm609 committed
491
    FS_libc=/lib/i386-linux-gnu/libc.so.6
slimm609's avatar
slimm609 committed
492
  elif [[ -e /lib/x86_64-linux-gnu/libc.so.6 ]] ; then
slimm609's avatar
slimm609 committed
493
    FS_libc=/lib/x86_64-linux-gnu/libc.so.6
Avamander's avatar
Avamander committed
494
495
496
497
  elif [[ -e /lib/arm-linux-gnueabihf/libc.so.6 ]] ; then
    FS_libc=/lib/arm-linux-gnueabihf/libc.so.6
  elif [[ -e /lib/aarch64-linux-gnu/libc.so.6 ]] ; then
    FS_libc=/lib/aarch64-linux-gnu/libc.so.6
slimm609's avatar
slimm609 committed
498
499
  elif [[ -e /usr/x86_64-gentoo-linux-musl/bin/ld ]] ; then
    FS_libc=/usr/x86_64-gentoo-linux-musl/bin/ld
slimm609's avatar
slimm609 committed
500
501
502
503
  else
    printf "\033[31mError: libc not found.\033[m\n\n"
    exit 1
  fi
504

slimm609's avatar
slimm609 committed
505
  FS_chk_func_libc="$(${readelf} -s $FS_libc 2>/dev/null | sed -ne 's/.*__\(.*_chk\)@@.*/\1/p')"
506
  FS_func_libc="${FS_chk_func_libc//_chk/}"
slimm609's avatar
slimm609 committed
507
  FS_functions="$(${readelf} --dyn-syms "${1}" 2>/dev/null | awk '{ print $8 }' | sed -e 's/_*//' -e 's/@.*//' -e '/^$/d')"
508
509
  FS_cnt_checked=$(grep -cFxf <(sort <<< "${FS_chk_func_libc}") <(sort <<< "${FS_functions}"))
  FS_cnt_unchecked=$(grep -cFxf <(sort <<< "${FS_func_libc}") <(sort <<< "${FS_functions}"))
510
  FS_cnt_total=$((FS_cnt_unchecked+FS_cnt_checked))
511

512
  if grep -q '_chk$' <<<"$FS_functions"; then
513
514
    echo_message '\033[32mYes\033[m' 'Yes,' ' fortify_source="yes" ' '"fortify_source":"yes",'
  else
slimm609's avatar
slimm609 committed
515
    echo_message "\033[31mNo\033[m" "No," ' fortify_source="no" ' '"fortify_source":"no",'
516
  fi
517
  echo_message "\t${FS_cnt_checked}\t" "${FS_cnt_checked}",  "fortified=\"${FS_cnt_checked}\" " "\"fortified\":\"${FS_cnt_checked}\","
518
  echo_message "\t${FS_cnt_total}\t\t" "${FS_cnt_total}" "fortify-able=\"${FS_cnt_total}\"" "\"fortify-able\":\"${FS_cnt_total}\""
Robin David's avatar
Robin David committed
519
520
521
522
}

# check process(es)
proccheck() {
slimm609's avatar
slimm609 committed
523
  ${debug} && echo -e "\n***function proccheck"
Robin David's avatar
Robin David committed
524
  # check for RELRO support
slimm609's avatar
slimm609 committed
525
526
527
528
  ${debug} && echo "***function proccheck->RELRO"
  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
slimm609's avatar
slimm609 committed
529
  echo_message '\033[32mFull RELRO   \033[m   ' 'Full RELRO,' ' relro="full"' '"relro":"full",'
Robin David's avatar
Robin David committed
530
      else
slimm609's avatar
slimm609 committed
531
  echo_message '\033[33mPartial RELRO\033[m   ' 'Partial RELRO,' ' relro="partial"' '"relro":"partial",'
Robin David's avatar
Robin David committed
532
533
      fi
    else
534
      echo_message '\033[31mNo RELRO     \033[m   ' 'No RELRO,' ' relro="no"' '"relro":"no",'
Robin David's avatar
Robin David committed
535
536
537
538
539
540
541
    fi
  else
    echo -n -e '\033[31mPermission denied (please run as root)\033[m\n'
    exit 1
  fi

  # check for stack canary support
slimm609's avatar
slimm609 committed
542
543
544
  ${debug} && echo -e "\n***function proccheck->canary"
  if ${readelf} -s "${1}/exe" 2>/dev/null | grep -q 'Symbol table'; then
    if ${readelf} -s "${1}/exe" 2>/dev/null | grep -Eq '__stack_chk_fail|__intel_security_cookie'; then
slimm609's avatar
spacing    
slimm609 committed
545
      echo_message '\033[32mCanary found         \033[m   ' 'Canary found,' ' canary="yes"' '"canary":"yes",'
Robin David's avatar
Robin David committed
546
    else
slimm609's avatar
spacing    
slimm609 committed
547
      echo_message '\033[31mNo canary found      \033[m   ' 'No Canary found,' ' canary="no"' '"canary":"no",'
Robin David's avatar
Robin David committed
548
549
    fi
  else
slimm609's avatar
slimm609 committed
550
    if [[ "${1}" == "1" ]] ; then
Derek Betker's avatar
Derek Betker committed
551
      echo_message '\033[33mPermission denied    \033[m   ' 'Permission denied,' ' canary="Permission denied"' '"canary":"Permission denied",'
Robin David's avatar
Robin David committed
552
    else
Derek Betker's avatar
Derek Betker committed
553
      echo_message '\033[33mNo symbol table found \033[m  ' 'No symbol table found,' ' canary="No symbol table found"' '"canary":"No symbol table found",'
Robin David's avatar
Robin David committed
554
555
556
    fi
  fi

slimm609's avatar
slimm609 committed
557
558
559
560
  if ${extended_checks}; then
    # check if compiled with Clang CFI
    $debug && echo -e "\n***function proccheck->clangcfi"
    #if $readelf -s "$1" 2>/dev/null | grep -Eq '\.cfi'; then
561
    read -r -a cfifunc <<< "$($readelf -s "$1/exe" 2>/dev/null | grep .cfi | awk '{ print $8 }')"
slimm609's avatar
slimm609 committed
562
    func=${cfifunc/.cfi/}
Brian Davis's avatar
Brian Davis committed
563
564
    # TODO: fix this check properly, need more clang CFI files to be able to test properly
    # shellcheck disable=SC2128
565
    if [ -n "$cfifunc" ] && $readelf -s "$1/exe" 2>/dev/null | grep -q "$func$"; then
slimm609's avatar
slimm609 committed
566
567
568
569
570
571
572
573
574
575
576
577
578
579
      echo_message '\033[32mClang CFI found   \033[m   ' 'with CFI,' ' clangcfi="yes"' '"clangcfi":"yes",'
    else
      echo_message '\033[31mNo Clang CFI found\033[m   ' 'without CFI,' ' clangcfi="no"' '"clangcfi":"no",'
    fi

    # check if compiled with Clang SafeStack
    $debug && echo -e "\n***function proccheck->safestack"
    if $readelf -s "$1/exe" 2>/dev/null | grep -Eq '__safestack_init'; then
      echo_message '\033[32mSafeStack found   \033[m   ' 'with SafeStack,' ' safestack="yes"' '"safestack":"yes",'
    else
      echo_message '\033[31mNo SafeStack found\033[m   ' 'without SafeStack,' ' safestack="no"' '"safestack":"no",'
    fi
  fi

slimm609's avatar
slimm609 committed
580
  # check for Seccomp mode
slimm609's avatar
slimm609 committed
581
582
583
  ${debug} && echo -e "\n***function proccheck->Seccomp"
  seccomp=$(grep 'Seccomp:' "${1}/status" 2> /dev/null | cut -b10)
  if [[ "${seccomp}" == "1" ]] ; then
slimm609's avatar
slimm609 committed
584
    echo_message '\033[32mSeccomp strict\033[m   ' 'Seccomp strict,' ' seccomp="strict"' '"seccomp":"strict",'
slimm609's avatar
slimm609 committed
585
  elif [[ "${seccomp}" == "2" ]] ; then
slimm609's avatar
slimm609 committed
586
587
588
589
590
    echo_message '\033[32mSeccomp-bpf   \033[m   ' 'Seccomp-bpf,' ' seccomp="bpf"' '"seccomp":"bpf",'
  else
    echo_message '\033[31mNo Seccomp    \033[m   ' 'No Seccomp,' ' seccomp="no"' '"seccomp":"no",'
  fi

Robin David's avatar
Robin David committed
591
  # first check for PaX support
slimm609's avatar
slimm609 committed
592
593
594
595
596
597
598
  ${debug} && echo -e "\n***function proccheck->PAX"
  if grep -q 'PaX:' "${1}/status" 2> /dev/null ; then
    pageexec=$(grep 'PaX:' "${1}/status" 2> /dev/null | cut -b6)
    segmexec=$(grep 'PaX:' "${1}/status" 2> /dev/null | cut -b10)
    mprotect=$(grep 'PaX:' "${1}/status" 2> /dev/null | cut -b8)
    randmmap=$(grep 'PaX:' "${1}/status" 2> /dev/null | cut -b9)
    if [[ "${pageexec}" = "P" || "${segmexec}" = "S" ]] && [[ "${mprotect}" = "M" && "${randmmap}" = "R" ]] ; then
599
      echo_message '\033[32mPaX enabled\033[m   ' 'Pax enabled,' ' pax="yes"' '"pax":"yes",'
slimm609's avatar
slimm609 committed
600
    elif [[ "${pageexec}" = "p" && "${segmexec}" = "s" && "${randmmap}" = "R" ]] ; then
601
      echo_message '\033[33mPaX ASLR only\033[m ' 'Pax ASLR only,' ' pax="aslr_only"' '"pax":"aslr_only",'
slimm609's avatar
slimm609 committed
602
    elif [[ "${pageexec}" = "P" || "${segmexec}" = "S" ]] && [[ "${mprotect}" = "m" && "${randmmap}" = "R" ]] ; then
603
      echo_message '\033[33mPaX mprot off \033[m' 'Pax mprot off,' ' pax="mprot_off"' '"pax":"mprot_off",'
slimm609's avatar
slimm609 committed
604
    elif [[ "${pageexec}" = "P" || "${segmexec}" = "S" ]] && [[ "${mprotect}" = "M" && "${randmmap}" = "r" ]] ; then
605
      echo_message '\033[33mPaX ASLR off\033[m  ' 'Pax ASLR off,' ' pax="aslr_off"' '"pax":"aslr_off",'
slimm609's avatar
slimm609 committed
606
    elif [[ "${pageexec}" = "P" || "${segmexec}" = "S" ]] && [[ "${mprotect}" = "m" && "${randmmap}" = "r" ]] ; then
607
      echo_message '\033[33mPaX NX only\033[m   ' 'Pax NX only,' ' pax="nx_only"' '"pax":"nx_only",'
Robin David's avatar
Robin David committed
608
    else
609
      echo_message '\033[31mPaX disabled\033[m  ' 'Pax disabled,' ' pax="no"' '"pax":"no",'
Robin David's avatar
Robin David committed
610
611
    fi
  # fallback check for NX support
slimm609's avatar
slimm609 committed
612
  ${debug} && echo -e "\n***function proccheck->NX"
613
  elif ${readelf} -l "${1}/exe" 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then
614
    echo_message '\033[31mNX disabled\033[m   ' 'NX disabled,' ' nx="no"' '"nx":"no",'
Robin David's avatar
Robin David committed
615
  else
616
    echo_message '\033[32mNX enabled \033[m   ' 'NX enabled,' ' pax="yes"' '"nx":"yes",'
617
  fi
Robin David's avatar
Robin David committed
618
619

  # check for PIE support
slimm609's avatar
slimm609 committed
620
621
  ${debug} && echo -e "\n***function proccheck->PIE"
  if ${readelf} -h "${1}/exe" 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then
root's avatar
root committed
622
    echo_message '\033[31mNo PIE               \033[m   ' 'No PIE,' ' pie="no"' '"pie":"no",'
slimm609's avatar
slimm609 committed
623
624
  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
root's avatar
root committed
625
      echo_message '\033[32mPIE enabled          \033[m   ' 'PIE enabled,' ' pie="yes"' '"pie":"yes",'
626
    else
root's avatar
root committed
627
      echo_message '\033[33mDynamic Shared Object\033[m   ' 'Dynamic Shared Object,' ' pie="dso"' '"pie":"dso",'
Robin David's avatar
Robin David committed
628
629
    fi
  else
root's avatar
root committed
630
    echo_message '\033[33mNot an ELF file      \033[m   ' 'Not an ELF file,' ' pie="not_elf"' '"pie":"not_elf",'
Robin David's avatar
Robin David committed
631
  fi
root's avatar
root committed
632

Brian Davis's avatar
Brian Davis committed
633
634
635
636
637
638
639
640
641
  if ${extended_checks}; then
    # check for selfrando support
    ${debug} && echo -e "\n***function proccheck->selfrando"
    if ${readelf} -S "${1}/exe" 2>/dev/null | grep -c txtrp | grep -q '1'; then
      echo_message '\033[32mSelfrando enabled    \033[m   '
    else
      echo_message '\033[31mNo Selfrando         \033[m   '
    fi
  fi 
642

slimm609's avatar
slimm609 committed
643
  #check for forifty source support
644
645
646
647
648
649
  FS_functions="$(${readelf} -s "${1}/exe" 2>/dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//')"
  if grep -q '_chk$' <<<"$FS_functions"; then
    echo_message '\033[32mYes\033[m' 'Yes' " fortify_source='yes'>" '"fortify_source":"yes" }'
  else
    echo_message "\033[31mNo\033[m" "No" " fortify_source='no'>" '"fortify_source":"no" }'
  fi
Robin David's avatar
Robin David committed
650
651
652
653
}

# check mapped libraries
libcheck() {
slimm609's avatar
slimm609 committed
654
  ${debug} && echo "***function libcheck"
Brian Davis's avatar
Brian Davis committed
655
  IFS=" " read -r -a libs <<< "$(awk '{ print $6 }' "/proc/${1}/maps" | grep '/' | sort -u | xargs file | grep ELF | awk '{ print $1 }' | sed 's/:/ /')"
Derek Betker's avatar
Derek Betker committed
656
  echo_message "\n* Loaded libraries (file information, # of mapped files: ${#libs[@]}):\n\n" "" "" "\"libs\": {"
slimm609's avatar
slimm609 committed
657

658
  for ((element=0; element<${#libs[@]}; element++))
Robin David's avatar
Robin David committed
659
  do
660
661
    echo_message "  ${libs[$element]}:\n" "${libs[$element]}," "" ""
    echo_message "    " "" "    " ""
slimm609's avatar
slimm609 committed
662
    filecheck "${libs[$element]}"
slimm609's avatar
slimm609 committed
663
    if [[ ${element} == $((${#libs[@]} - 1)) ]]; then
Derek Betker's avatar
Derek Betker committed
664
665
666
667
      echo_message "\n\n" "\n" " filename='${libs[$element]}' />\n" ""
    else
      echo_message "\n\n" "\n" " filename='${libs[$element]}' />\n" "},"
    fi
Robin David's avatar
Robin David committed
668
669
670
671
672
  done
}

# check for system-wide ASLR support
aslrcheck() {
slimm609's avatar
slimm609 committed
673
  ${debug} && echo "***function aslrcheck"
Robin David's avatar
Robin David committed
674
  # PaX ASLR support
slimm609's avatar
slimm609 committed
675
  ${debug} && echo -e "\n***function aslrcheck->PAX ASLR"
slimm609's avatar
slimm609 committed
676
  if ! (grep -q 'Name:' /proc/1/status 2> /dev/null) ; then
Brian Davis's avatar
Brian Davis committed
677
    echo_message '\033[33m insufficient privileges for PaX ASLR checks\033[m\n' '' '' ''
678
    echo_message '  Fallback to standard Linux ASLR check' '' '' ''
Robin David's avatar
Robin David committed
679
  fi
slimm609's avatar
slimm609 committed
680

slimm609's avatar
slimm609 committed
681
682
  if grep -q 'PaX:' /proc/1/status 2> /dev/null; then
    if grep -q 'PaX:' /proc/1/status 2> /dev/null | grep -q 'R'; then
683
      echo_message '\033[32mPaX ASLR enabled\033[m\n\n' '' '' ''
Robin David's avatar
Robin David committed
684
    else
685
      echo_message '\033[31mPaX ASLR disabled\033[m\n\n' '' '' ''
Robin David's avatar
Robin David committed
686
687
    fi
  else
slimm609's avatar
slimm609 committed
688
  ${debug} && echo -e "\n***function aslrcheck->randomize_va_space"
Robin David's avatar
Robin David committed
689
690
    # standard Linux 'kernel.randomize_va_space' ASLR support
    # (see the kernel file 'Documentation/sysctl/kernel.txt' for a detailed description)
691
    echo_message " (kernel.randomize_va_space): " '' '' ''
Brian Davis's avatar
Brian Davis committed
692
    if sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 1'; then
693
      echo_message '\033[33mPartial (Setting: 1)\033[m\n\n' '' '' ''
694
695
696
697
      echo_message "  Description - Make the addresses of mmap base, stack and VDSO page randomized.\n" '' '' ''
      echo_message "  This, among other things, implies that shared libraries will be loaded to \n" '' '' ''
      echo_message "  random addresses. Also for PIE-linked binaries, the location of code start\n" '' '' ''
      echo_message "  is randomized. Heap addresses are *not* randomized.\n\n" '' '' ''
Brian Davis's avatar
Brian Davis committed
698
    elif sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 2'; then
699
      echo_message '\033[32mFull (Setting: 2)\033[m\n\n' '' '' ''
700
701
702
      echo_message "  Description - Make the addresses of mmap base, heap, stack and VDSO page randomized.\n" '' '' ''
      echo_message "  This, among other things, implies that shared libraries will be loaded to random \n" '' '' ''
      echo_message "  addresses. Also for PIE-linked binaries, the location of code start is randomized.\n\n" '' '' ''
Brian Davis's avatar
Brian Davis committed
703
    elif sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 0'; then
704
      echo_message '\033[31mNone (Setting: 0)\033[m\n' '' '' ''
Robin David's avatar
Robin David committed
705
    else
706
      echo_message '\033[31mNot supported\033[m\n' '' '' ''
Robin David's avatar
Robin David committed
707
    fi
708
    echo_message "  See the kernel file 'Documentation/sysctl/kernel.txt' for more details.\n\n" '' '' ''
709
  fi
Robin David's avatar
Robin David committed
710
711
712
713
}

# check cpu nx flag
nxcheck() {
slimm609's avatar
slimm609 committed
714
  ${debug} && echo -e "\n***function nxcheck"
715
  if grep -qFw nx /proc/cpuinfo; then
716
    echo_message '\033[32mYes\033[m\n\n' '' '' ''
Robin David's avatar
Robin David committed
717
  else
718
    echo_message '\033[31mNo\033[m\n\n' '' '' ''
Robin David's avatar
Robin David committed
719
720
721
  fi
}

Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
722
723
#Check core dumps restricted?
coredumpcheck() {
slimm609's avatar
slimm609 committed
724
        ${debug} && echo -e "\n***function coredumpcheck"
Christian Göttsche's avatar
Christian Göttsche committed
725
726
        coreValue=$(grep -Exic "hard[[:blank:]]+core[[:blank:]]+0" /etc/security/limits.conf)
        coreValueDefault=$(grep -Exic "\*[[:blank:]]+hard[[:blank:]]+core[[:blank:]]+0" /etc/security/limits.conf)
slimm609's avatar
slimm609 committed
727
        dumpableValue=$(sysctl -b -e fs.suid_dumpable)
Brian Davis's avatar
Brian Davis committed
728
        if { [[ "${coreValue}" == 1 ]] || [[ "${coreValueDefault}" == 1 ]]; } && { [[ "${dumpableValue}" == 0 ]] || [[ "${dumpableValue}" == 2 ]]; }; then
Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
729
730
731
732
733
734
                echo_message '\033[32mRestricted\033[m\n\n' '' '' ''
        else
                echo_message '\033[31mNot Restricted\033[m\n\n' '' '' ''
        fi
}

Robin David's avatar
Robin David committed
735
736
# check for kernel protection mechanisms
kernelcheck() {
slimm609's avatar
slimm609 committed
737
  ${debug} && echo "***function kernelcheck"
738
739
740
741
  echo_message "  Description - List the status of kernel protection mechanisms. Rather than\n" '' '' ''
  echo_message "  inspect kernel mechanisms that may aid in the prevention of exploitation of\n" '' '' ''
  echo_message "  userspace processes, this option lists the status of kernel configuration\n" '' '' ''
  echo_message "  options that harden the kernel itself against attack.\n\n" '' '' ''
slimm609's avatar
signed    
slimm609 committed
742
  echo_message "  Kernel config:\n" '' '' '{ "kernel": '
slimm609's avatar
slimm609 committed
743

slimm609's avatar
slimm609 committed
744
745
  if [[ ! "${1}" == "" ]] ; then
    kconfig="cat ${1}"
746
    echo_message "  Warning: The config ${1} on disk may not represent running kernel config!\n\n" "${1}" "<kernel config=\"${1}\"" "{ \"KernelConfig\":\"${1}\""
747
    # update the architecture based on the config rather than the system
slimm609's avatar
slimm609 committed
748
    if ${kconfig} | grep -qi 'CONFIG_ARM=y\|CONFIG_ARM=y'; then
749
750
      arch="arm"
    fi
slimm609's avatar
slimm609 committed
751
    if ${kconfig} | grep -qi 'CONFIG_ARM64=y'; then
Scott Ellis's avatar
Scott Ellis committed
752
753
      arch="aarch64"
    fi
slimm609's avatar
slimm609 committed
754
    if ${kconfig} | grep -qi 'CONFIG_X86_64=y'; then
755
756
      arch="64"
    fi
slimm609's avatar
slimm609 committed
757
    if ${kconfig} | grep -qi 'CONFIG_X86_32=y'; then
758
759
      arch="32"
    fi
slimm609's avatar
slimm609 committed
760
  elif [[ -f /proc/config.gz ]] ; then
Robin David's avatar
Robin David committed
761
    kconfig="zcat /proc/config.gz"
762
    echo_message "\033[32m/proc/config.gz\033[m\n\n" '/proc/config.gz' '<kernel config="/proc/config.gz"' '{ "KernelConfig":"/proc/config.gz"'
slimm609's avatar
slimm609 committed
763
  elif [[ -f /boot/config-"$(uname -r)" ]] ; then
slimm609's avatar
slimm609 committed
764
    kern=$(uname -r)
765
766
767
    kconfig="cat /boot/config-${kern}"
    echo_message "\033[33m    /boot/config-${kern}\033[m\n\n" "/boot/config-${kern}," "<kernel config='/boot/config-${kern}'" "{ \"KernelConfig\":\"/boot/config-${kern}\""
    echo_message "  Warning: The config on disk may not represent running kernel config!\n           Running kernel: ${kern}\n\n" "" "" ""
slimm609's avatar
slimm609 committed
768
  elif [[ -f "${KBUILD_OUTPUT:-/usr/src/linux}"/.config ]] ; then
Robin David's avatar
Robin David committed
769
    kconfig="cat ${KBUILD_OUTPUT:-/usr/src/linux}/.config"
770
    echo_message "\033[33m${KBUILD_OUTPUT:-/usr/src/linux}/.config\033[m\n\n" "${KBUILD_OUTPUT:-/usr/src/linux}/.config," "<kernel config='${KBUILD_OUTPUT:-/usr/src/linux}/.config'" "{ \"KernelConfig\":\"${KBUILD_OUTPUT:-/usr/src/linux}/.config\""
771
    echo_message "  Warning: The config on disk may not represent running kernel config!\n\n" "" "" ""
Robin David's avatar
Robin David committed
772
  else
Brian Davis's avatar
Brian Davis committed
773
    echo_message "\033[31mNOT FOUND\033[m\n\n" "NOT FOUND,,,,,,," "<kernel config='not_found' />" '{ "KernelConfig":"not_found" } }'
Robin David's avatar
Robin David committed
774
775
    exit 0
  fi
slimm609's avatar
slimm609 committed
776
777
  ${debug} && ${kconfig} | grep "CONFIG_GRKERNSEC"
  ${debug} && ${kconfig} | grep "CONFIG_PAX"
Robin David's avatar
Robin David committed
778

Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
779
  echo_message "  Vanilla Kernel ASLR:                    " "" "" ""
slimm609's avatar
signed    
slimm609 committed
780
  randomize_va=$(sysctl -b -e kernel.randomize_va_space)
slimm609's avatar
slimm609 committed
781
  if [[ "x${randomize_va}" == "x2" ]]; then
782
    echo_message "\033[32mFull\033[m\n" "Full," " randomize_va_space='full'" ', "randomize_va_space":"full"'
slimm609's avatar
slimm609 committed
783
  elif [[ "x${randomize_va}" == "x1" ]]; then
784
    echo_message "\033[33mPartial\033[m\n" "Partial," " randomize_va_space='partial'" ', "randomize_va_space":"partial"'
root's avatar
root committed
785
  else
786
787
788
789
    echo_message "\033[31mNone\033[m\n" "None," " randomize_va_space='none'" ', "randomize_va_space":"none"'
  fi

  echo_message "  NX protection:                          " "" "" ""
790
791
792
793
794
795
  if (command_exists journalctl); then
    nx_protection=$(journalctl -kb -o cat | grep -Fw NX | head -n 1)
  elif (command_exists dmesg) && (root_privs); then
    nx_protection=$(dmesg -t 2>/dev/null | grep -Fw NX)
  fi
  if [ -n "$nx_protection" ]; then
796
797
798
799
800
801
802
    if [[ "x${nx_protection}" == "xNX (Execute Disable) protection: active" ]]; then
      echo_message "\033[32mEnabled\033[m\n" "Enabled," " nx_protection='yes'" ', "nx_protection":"yes"'
    else
      echo_message "\033[31mDisabled\033[m\n" "Disabled," " nx_protection='no'" ', "nx_protection":"no"'
    fi
  else
    echo_message "\033[33mSkipped\033[m\n" "Skipped," " nx_protection='skipped'" ', "nx_protection":"skipped"'
root's avatar
root committed
803
804
  fi

Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
805
  echo_message "  Protected symlinks:                     " "" "" ""
slimm609's avatar
signed    
slimm609 committed
806
  symlink=$(sysctl -b -e fs.protected_symlinks)
slimm609's avatar
slimm609 committed
807
  if [[ "x${symlink}" == "x1" ]]; then
808
    echo_message "\033[32mEnabled\033[m\n" "Enabled," " protect_symlinks='yes'" ', "protect_symlinks":"yes"'
slimm609's avatar
signed    
slimm609 committed
809
  else
810
    echo_message "\033[31mDisabled\033[m\n" "Disabled," " protect_symlinks='no'" ', "protect_symlinks":"no"'
slimm609's avatar
signed    
slimm609 committed
811
812
  fi

Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
813
  echo_message "  Protected hardlinks:                    " "" "" ""
slimm609's avatar
signed    
slimm609 committed
814
  hardlink=$(sysctl -b -e fs.protected_hardlinks)
slimm609's avatar
slimm609 committed
815
  if [[ "x${hardlink}" == "x1" ]]; then
816
    echo_message "\033[32mEnabled\033[m\n" "Enabled," " protect_hardlinks='yes'" ', "protect_hardlinks":"yes"'
slimm609's avatar
signed    
slimm609 committed
817
  else
818
    echo_message "\033[31mDisabled\033[m\n" "Disabled," " protect_hardlinks='no'" ', "protect_hardlinks":"no"'
slimm609's avatar
signed    
slimm609 committed
819
820
  fi

821
  echo_message "  Protected fifos:                        " "" "" ""
822
823
824
825
  fifos=$(sysctl -b -e fs.protected_fifos)
  if [[ "x${fifos}" == "x" ]]; then
    echo_message "\033[33mUnsupported\033[m\n" "Unsupported," " protect_fifos='unsupported'" ', "protect_fifos":"unsupported"'
  elif [[ "x${fifos}" == "x2" ]]; then
826
    echo_message "\033[32mEnabled\033[m\n" "Enabled," " protect_fifos='yes'" ', "protect_fifos":"yes"'
slimm609's avatar
signed    
slimm609 committed
827
  else
828
    echo_message "\033[31mDisabled\033[m\n" "Disabled," " protect_fifos='no'" ', "protect_fifos":"no"'
slimm609's avatar
signed    
slimm609 committed
829
830
  fi

831
  echo_message "  Protected regular:                      " "" "" ""
832
833
834
835
  regular=$(sysctl -b -e fs.protected_regular)
  if [[ "x${regular}" == "x" ]]; then
    echo_message "\033[33mUnsupported\033[m\n" "Unsupported," " protect_regular='unsupported'" ', "protect_regular":"unsupported"'
  elif [[ "x${regular}" == "x2" ]]; then
836
837
838
839
    echo_message "\033[32mEnabled\033[m\n" "Enabled," " protect_regular='yes'" ', "protect_regular":"yes"'
  else
    echo_message "\033[31mDisabled\033[m\n" "Disabled," " protect_regular='no'" ', "protect_regular":"no"'
  fi
840

841
842
843
844
  echo_message "  Ipv4 reverse path filtering:            " "" "" ""
  ipv4_rpath=$(sysctl -b -e net.ipv4.conf.all.rp_filter)
  if [[ "x${ipv4_rpath}" == "x1" ]]; then
    echo_message "\033[32mEnabled\033[m\n" "Enabled," " ipv4_rpath='yes'" ', "ipv4_rpath":"yes"'
slimm609's avatar
signed    
slimm609 committed
845
  else
846
    echo_message "\033[31mDisabled\033[m\n" "Disabled," " ipv4_rpath='no'" ', "ipv4_rpath":"no"'
slimm609's avatar
signed    
slimm609 committed
847
848
849
850
  fi

  echo_message "  Kernel heap randomization:              " "" "" ""
  # NOTE: y means it turns off kernel heap randomization for backwards compatability (libc5)
slimm609's avatar
slimm609 committed
851
  if ${kconfig} | grep -qi 'CONFIG_COMPAT_BRK=y'; then
852
    echo_message "\033[31mDisabled\033[m\n" "Disabled," " kernel_heap_randomization='no'" ', "kernel_heap_randomization":"no"'
slimm609's avatar
signed    
slimm609 committed
853
  else
854
    echo_message "\033[32mEnabled\033[m\n" "Enabled," " kernel_heap_randomization='yes'" ', "kernel_heap_randomization":"yes"'
slimm609's avatar
signed    
slimm609 committed
855
856
  fi

slimm609's avatar
slimm609 committed
857
  if ${kconfig} | grep -qi 'CONFIG_CC_STACKPROTECTOR' || ${kconfig} | grep -qa 'CONFIG_STACKPROTECTOR'; then
slimm609's avatar
slimm609 committed
858
    echo_message "  GCC stack protector support:            " "" "" ""
slimm609's avatar
slimm609 committed
859
    if ${kconfig} | grep -qi 'CONFIG_CC_STACKPROTECTOR=y' || ${kconfig} | grep -qi 'CONFIG_STACKPROTECTOR=y' ; then
860
      echo_message "\033[32mEnabled\033[m\n" "Enabled," " gcc_stack_protector='yes'" ', "gcc_stack_protector":"yes"'
Scott Ellis's avatar
Scott Ellis committed
861

slimm609's avatar
slimm609 committed
862
      if ${kconfig} | grep -qi 'CONFIG_CC_STACKPROTECTOR_STRONG' || ${kconfig} | grep -qi 'CONFIG_STACKPROTECTOR_STRONG'; then
slimm609's avatar
slimm609 committed
863
        echo_message "  GCC stack protector strong:             " "" "" ""
slimm609's avatar
slimm609 committed