checksec 81.6 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:
#
slimm609's avatar
slimm609 committed
6
# Copyright (c) 2014-2019, 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
67
have_readelf=1
verbose=false
format="cli"
slimm609's avatar
slimm609 committed
68
SCRIPT_NAME="checksec"
slimm609's avatar
slimm609 committed
69
SCRIPT_URL="https://github.com/slimm609/checksec.sh/raw/master/${SCRIPT_NAME}"
slimm609's avatar
slimm609 committed
70
SIG_URL="https://github.com/slimm609/checksec.sh/raw/master/$(basename ${SCRIPT_NAME} .sh).sig"
slimm609's avatar
slimm609 committed
71
72
73
SCRIPT_VERSION=2019072301
SCRIPT_MAJOR=2
SCRIPT_MINOR=0
74
SCRIPT_REVISION=0
slimm609's avatar
slimm609 committed
75
pkg_release=false
slimm609's avatar
slimm609 committed
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
commandsmissing=false
OPT=0
# 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;
}

for command in cat awk sysctl uname mktemp openssl grep stat file find sort fgrep head ps readlink basename id which xargs; do
    if ! (command_exists ${command}); then
       echo -e "\e[31mWARNING: '${command}' not found! It's required for most checks.\e[0m"
       commandsmissing=true
    fi
done

if [[ ${command}smissing == true ]]; then
    echo -e "\n\e[31mWARNING: Not all necessary commands found. Some tests might not work!\e[0m\n"
    sleep 2
fi

if (command_exists readelf); then
     readelf=readelf
elif (command_exists eu-readelf); then
     readelf=eu-readelf
elif (command_exists greadelf); then
     readelf=greadelf
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
117

slimm609's avatar
slimm609 committed
118
if [[ $(id -u) != 0 ]]; then
slimm609's avatar
slimm609 committed
119
    export PATH=${PATH}:/sbin/:/usr/sbin/
120
121
fi

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

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

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

152
153
# Version compare
vercomp () {
slimm609's avatar
slimm609 committed
154
    if [[ "${1}" == "${2}" ]]
155
156
157
158
    then
        return 0
    fi
    local IFS=.
slimm609's avatar
slimm609 committed
159
    local i ver1="${1}" ver2="${2}"
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
    # 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
184
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
223
# Update/Upgrade
upgrade () {
  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
}
224

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

# help
help() {
Brian Davis's avatar
Brian Davis committed
234
  echo "Usage: checksec [--output {cli|csv|xml|json}] [OPTION]"
Robin David's avatar
Robin David committed
235
236
237
238
  echo
  echo
  echo "Options:"
  echo
slimm609's avatar
slimm609 committed
239
240
241
242
243
244
245
246
247
  echo " ## Checksec Options"
  echo "  --file=<file>"
  echo "  --dir=<directory>"
  echo "  --proc=<process name>"
  echo "  --proc-all"
  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
257
258
  echo " ## Modifiers"
  echo "  --debug"
  echo "  --verbose"
  echo "  --format=[cli|csv|xml|json]"
  echo
Robin David's avatar
Robin David committed
259
  echo "For more information, see:"
root's avatar
root committed
260
  echo "  http://github.com/slimm609/checksec.sh"
Robin David's avatar
Robin David committed
261
262
263
  echo
}

slimm609's avatar
slimm609 committed
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# 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}"
}

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

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

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

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

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

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

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

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

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

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

  # check for PIE support
slimm609's avatar
slimm609 committed
395
396
  ${debug} && echo -e "\n***function filecheck->pie"
  if ${readelf} -h "${1}" 2>/dev/null | grep -q 'Type:[[:space:]]*EXEC'; then
397
    echo_message '\033[31mNo PIE       \033[m   ' 'No PIE,' ' pie="no"' '"pie":"no",'
slimm609's avatar
slimm609 committed
398
399
  elif ${readelf} -h "${1}" 2>/dev/null | grep -q 'Type:[[:space:]]*DYN'; then
    if ${readelf} -d "${1}" 2>/dev/null | grep -q 'DEBUG'; then
400
      echo_message '\033[32mPIE enabled  \033[m   ' 'PIE enabled,' ' pie="yes"' '"pie":"yes",'
401
    else
402
      echo_message '\033[33mDSO          \033[m   ' 'DSO,' ' pie="dso"' '"pie":"dso",'
Robin David's avatar
Robin David committed
403
404
    fi
  else
405
    echo_message '\033[33mNot an ELF file\033[m   ' 'Not an ELF file,' ' pie="not_elf"' '"pie":"not_elf",'
406
  fi
Robin David's avatar
Robin David committed
407
408

  # check for rpath / run path
slimm609's avatar
slimm609 committed
409
  ${debug} && echo -e "\n***function filecheck->rpath"
410
411
  # 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]"
slimm609's avatar
slimm609 committed
412
  IFS=: read -a rpath_array <<< $(${readelf} -d "${1}" 2>/dev/null | awk -F'[][]' '/RPATH/ {print $2}')
413
  if [[ "${#rpath_array[@]}" -gt 0 ]]; then
414
    if xargs stat -c %A <<< ${rpath_array[*]} 2>/dev/null | grep -q 'rw'; then
415
      echo_message '\033[31mRW-RPATH \033[m  ' 'RPATH,' ' rpath="yes"' '"rpath":"yes",'
416
    else
417
      echo_message '\033[31mRPATH   \033[m  ' 'RPATH,' ' rpath="yes"' '"rpath":"yes",'
418
    fi
Robin David's avatar
Robin David committed
419
  else
420
    echo_message '\033[32mNo RPATH \033[m  ' 'No RPATH,' ' rpath="no"' '"rpath":"no",'
Robin David's avatar
Robin David committed
421
422
  fi

slimm609's avatar
slimm609 committed
423
  ${debug} && echo -e "\n***function filecheck->runpath"
424
  # search for a line that matches RUNPATH and extract the colon-separated path list within brackets
slimm609's avatar
slimm609 committed
425
  IFS=: read -a runpath_array <<< $(${readelf} -d "${1}" 2>/dev/null | awk -F'[][]' '/RUNPATH/ {print $2}')
426
  if [[ "${#runpath_array[@]}" -gt 0 ]]; then
427
    if xargs stat -c %A <<< ${runpath_array[*]} 2>/dev/null | grep -q 'rw'; then
428
      echo_message '\033[31mRW-RUNPATH \033[m  ' 'RUNPATH,' ' runpath="yes"' '"runpath":"yes",'
429
    else
430
      echo_message '\033[31mRUNPATH   \033[m  ' 'RUNPATH,' ' runpath="yes"' '"runpath":"yes",'
431
    fi
Robin David's avatar
Robin David committed
432
  else
433
   echo_message '\033[32mNo RUNPATH \033[m  ' 'No RUNPATH,' ' runpath="no"' '"runpath":"no",'
Robin David's avatar
Robin David committed
434
  fi
435

436
437
  # check for stripped symbols in the binary
  SYM_cnt=' '
slimm609's avatar
slimm609 committed
438
439
440
  SYM_cnt=( $(${readelf} --symbols "${1}" 2>/dev/null | grep '\.symtab' | cut -d' ' -f5 | cut -d: -f1))
  if ${readelf} --symbols "${1}" 2>/dev/null | grep -q '\.symtab'; then
    echo_message "\033[31m${SYM_cnt[0]} Symbols   \033[m  " 'Symbols,' ' symbols="yes"' '"symbols":"yes",'
441
  else
slimm609's avatar
slimm609 committed
442
    echo_message '\033[32mNo Symbols    \033[m  ' 'No Symbols,' ' symbols="no"' '"symbols":"no",'
443
444
  fi

445
  # check for FORTIFY SOURCE
slimm609's avatar
slimm609 committed
446
  ${debug} && echo "***function filecheck->fortify"
slimm609's avatar
slimm609 committed
447
  if [[ -e /lib/libc.so.6 ]] ; then
slimm609's avatar
slimm609 committed
448
    FS_libc=/lib/libc.so.6
449
450
  elif [[ -e /lib/libc.so.7 ]] ; then
    FS_libc=/lib/libc.so.7
slimm609's avatar
slimm609 committed
451
  elif [[ -e /lib/libc.so ]] ; then
rofl0r's avatar
rofl0r committed
452
    FS_libc=/lib/libc.so
slimm609's avatar
slimm609 committed
453
  elif [[ -e /lib64/libc.so.6 ]] ; then
slimm609's avatar
slimm609 committed
454
    FS_libc=/lib64/libc.so.6
slimm609's avatar
slimm609 committed
455
  elif [[ -e /lib/i386-linux-gnu/libc.so.6 ]] ; then
slimm609's avatar
slimm609 committed
456
    FS_libc=/lib/i386-linux-gnu/libc.so.6
slimm609's avatar
slimm609 committed
457
  elif [[ -e /lib/x86_64-linux-gnu/libc.so.6 ]] ; then
slimm609's avatar
slimm609 committed
458
    FS_libc=/lib/x86_64-linux-gnu/libc.so.6
Avamander's avatar
Avamander committed
459
460
461
462
  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
463
464
  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
465
466
467
468
  else
    printf "\033[31mError: libc not found.\033[m\n\n"
    exit 1
  fi
469

slimm609's avatar
slimm609 committed
470
  FS_chk_func_libc="$(${readelf} -s $FS_libc 2>/dev/null | sed -ne 's/.*__\(.*_chk\)@@.*/\1/p')"
471
  FS_func_libc="$(echo "${FS_chk_func_libc}" | sed 's/_chk$//')"
slimm609's avatar
slimm609 committed
472
  FS_functions="$(${readelf} --dyn-syms "${1}" 2>/dev/null | awk '{ print $8 }' | sed -e 's/_*//' -e 's/@.*//' -e '/^$/d')"
473
474
475
  FS_cnt_checked=$(fgrep -xf <(sort <<< "${FS_chk_func_libc}") <(sort <<< "${FS_functions}") | wc -l)
  FS_cnt_unchecked=$(fgrep -xf <(sort <<< "${FS_func_libc}") <(sort <<< "${FS_functions}") | wc -l)
  FS_cnt_total=$((FS_cnt_unchecked+FS_cnt_checked))
476

477
478
479
  if [[ "${FS_functions}" =~ _chk ]]; then
    echo_message '\033[32mYes\033[m' 'Yes,' ' fortify_source="yes" ' '"fortify_source":"yes",'
  else
slimm609's avatar
slimm609 committed
480
    echo_message "\033[31mNo\033[m" "No," ' fortify_source="no" ' '"fortify_source":"no",'
481
  fi
slimm609's avatar
slimm609 committed
482
483
  echo_message "\t${FS_cnt_checked}\t" ${FS_cnt_checked},  "fortified=\"${FS_cnt_checked}\" " "\"fortified\":\"${FS_cnt_checked}\","
  echo_message "\t${FS_cnt_total}\t" ${FS_cnt_total} "fortify-able=\"${FS_cnt_total}\"" "\"fortify-able\":\"${FS_cnt_total}\""
Robin David's avatar
Robin David committed
484
485
486
487
}

# check process(es)
proccheck() {
slimm609's avatar
slimm609 committed
488
  ${debug} && echo -e "\n***function proccheck"
Robin David's avatar
Robin David committed
489
  # check for RELRO support
slimm609's avatar
slimm609 committed
490
491
492
493
  ${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
494
  echo_message '\033[32mFull RELRO   \033[m   ' 'Full RELRO,' ' relro="full"' '"relro":"full",'
Robin David's avatar
Robin David committed
495
      else
slimm609's avatar
slimm609 committed
496
  echo_message '\033[33mPartial RELRO\033[m   ' 'Partial RELRO,' ' relro="partial"' '"relro":"partial",'
Robin David's avatar
Robin David committed
497
498
      fi
    else
499
      echo_message '\033[31mNo RELRO     \033[m   ' 'No RELRO,' ' relro="no"' '"relro":"no",'
Robin David's avatar
Robin David committed
500
501
502
503
504
505
506
    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
507
508
509
  ${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
510
      echo_message '\033[32mCanary found         \033[m   ' 'Canary found,' ' canary="yes"' '"canary":"yes",'
Robin David's avatar
Robin David committed
511
    else
slimm609's avatar
spacing    
slimm609 committed
512
      echo_message '\033[31mNo canary found      \033[m   ' 'No Canary found,' ' canary="no"' '"canary":"no",'
Robin David's avatar
Robin David committed
513
514
    fi
  else
slimm609's avatar
slimm609 committed
515
    if [[ "${1}" == "1" ]] ; then
Derek Betker's avatar
Derek Betker committed
516
      echo_message '\033[33mPermission denied    \033[m   ' 'Permission denied,' ' canary="Permission denied"' '"canary":"Permission denied",'
Robin David's avatar
Robin David committed
517
    else
Derek Betker's avatar
Derek Betker committed
518
      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
519
520
521
    fi
  fi

slimm609's avatar
slimm609 committed
522
  # check for Seccomp mode
slimm609's avatar
slimm609 committed
523
524
525
  ${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
526
    echo_message '\033[32mSeccomp strict\033[m   ' 'Seccomp strict,' ' seccomp="strict"' '"seccomp":"strict",'
slimm609's avatar
slimm609 committed
527
  elif [[ "${seccomp}" == "2" ]] ; then
slimm609's avatar
slimm609 committed
528
529
530
531
532
    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
533
  # first check for PaX support
slimm609's avatar
slimm609 committed
534
535
536
537
538
539
540
  ${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
541
      echo_message '\033[32mPaX enabled\033[m   ' 'Pax enabled,' ' pax="yes"' '"pax":"yes",'
slimm609's avatar
slimm609 committed
542
    elif [[ "${pageexec}" = "p" && "${segmexec}" = "s" && "${randmmap}" = "R" ]] ; then
543
      echo_message '\033[33mPaX ASLR only\033[m ' 'Pax ASLR only,' ' pax="aslr_only"' '"pax":"aslr_only",'
slimm609's avatar
slimm609 committed
544
    elif [[ "${pageexec}" = "P" || "${segmexec}" = "S" ]] && [[ "${mprotect}" = "m" && "${randmmap}" = "R" ]] ; then
545
      echo_message '\033[33mPaX mprot off \033[m' 'Pax mprot off,' ' pax="mprot_off"' '"pax":"mprot_off",'
slimm609's avatar
slimm609 committed
546
    elif [[ "${pageexec}" = "P" || "${segmexec}" = "S" ]] && [[ "${mprotect}" = "M" && "${randmmap}" = "r" ]] ; then
547
      echo_message '\033[33mPaX ASLR off\033[m  ' 'Pax ASLR off,' ' pax="aslr_off"' '"pax":"aslr_off",'
slimm609's avatar
slimm609 committed
548
    elif [[ "${pageexec}" = "P" || "${segmexec}" = "S" ]] && [[ "${mprotect}" = "m" && "${randmmap}" = "r" ]] ; then
549
      echo_message '\033[33mPaX NX only\033[m   ' 'Pax NX only,' ' pax="nx_only"' '"pax":"nx_only",'
Robin David's avatar
Robin David committed
550
    else
551
      echo_message '\033[31mPaX disabled\033[m  ' 'Pax disabled,' ' pax="no"' '"pax":"no",'
Robin David's avatar
Robin David committed
552
553
    fi
  # fallback check for NX support
slimm609's avatar
slimm609 committed
554
555
  ${debug} && echo -e "\n***function proccheck->NX"
  elif ${readelf} -W -l "${1}/exe" 2>/dev/null | grep 'GNU_STACK' | grep -q 'RWE'; then
556
    echo_message '\033[31mNX disabled\033[m   ' 'NX disabled,' ' nx="no"' '"nx":"no",'
Robin David's avatar
Robin David committed
557
  else
558
    echo_message '\033[32mNX enabled \033[m   ' 'NX enabled,' ' pax="yes"' '"nx":"yes",'
559
  fi
Robin David's avatar
Robin David committed
560
561

  # check for PIE support
slimm609's avatar
slimm609 committed
562
563
  ${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
564
    echo_message '\033[31mNo PIE               \033[m   ' 'No PIE,' ' pie="no"' '"pie":"no",'
slimm609's avatar
slimm609 committed
565
566
  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
567
      echo_message '\033[32mPIE enabled          \033[m   ' 'PIE enabled,' ' pie="yes"' '"pie":"yes",'
568
    else
root's avatar
root committed
569
      echo_message '\033[33mDynamic Shared Object\033[m   ' 'Dynamic Shared Object,' ' pie="dso"' '"pie":"dso",'
Robin David's avatar
Robin David committed
570
571
    fi
  else
root's avatar
root committed
572
    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
573
  fi
root's avatar
root committed
574

slimm609's avatar
slimm609 committed
575
  #check for forifty source support
slimm609's avatar
slimm609 committed
576
  FS_functions=( $(${readelf} -s "${1}/exe" 2>/dev/null | awk '{ print $8 }' | sed 's/_*//' | sed -e 's/@.*//') )
577
  for ((FS_elem_functions=0; FS_elem_functions<${#FS_functions[@]}; FS_elem_functions++))
root's avatar
root committed
578
579
  do
    if [[ ${FS_functions[$FS_elem_functions]} =~ _chk ]] ; then
slimm609's avatar
stash    
slimm609 committed
580
      echo_message '\033[32mYes\033[m' 'Yes' " fortify_source='yes'>" '"fortify_source":"yes" }'
root's avatar
root committed
581
582
583
      return
    fi
  done
slimm609's avatar
stash    
slimm609 committed
584
  echo_message "\033[31mNo\033[m" "No" " fortify_source='no'>" '"fortify_source":"no" }'
Robin David's avatar
Robin David committed
585
586
587
588
}

# check mapped libraries
libcheck() {
slimm609's avatar
slimm609 committed
589
590
  ${debug} && echo "***function libcheck"
  libs=( $(awk '{ print $6 }' "/proc/${1}/maps" | grep '/' | sort -u | xargs file | grep ELF | awk '{ print ${1} }' | sed 's/:/ /') )
slimm609's avatar
slimm609 committed
591

Derek Betker's avatar
Derek Betker committed
592
  echo_message "\n* Loaded libraries (file information, # of mapped files: ${#libs[@]}):\n\n" "" "" "\"libs\": {"
slimm609's avatar
slimm609 committed
593

594
  for ((element=0; element<${#libs[@]}; element++))
Robin David's avatar
Robin David committed
595
  do
596
597
    echo_message "  ${libs[$element]}:\n" "${libs[$element]}," "" ""
    echo_message "    " "" "    " ""
slimm609's avatar
slimm609 committed
598
    filecheck "${libs[$element]}"
slimm609's avatar
slimm609 committed
599
    if [[ ${element} == $((${#libs[@]} - 1)) ]]; then
Derek Betker's avatar
Derek Betker committed
600
601
602
603
      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
604
605
606
607
608
  done
}

# check for system-wide ASLR support
aslrcheck() {
slimm609's avatar
slimm609 committed
609
  ${debug} && echo "***function aslrcheck"
Robin David's avatar
Robin David committed
610
  # PaX ASLR support
slimm609's avatar
slimm609 committed
611
  ${debug} && echo -e "\n***function aslrcheck->PAX ASLR"
slimm609's avatar
slimm609 committed
612
  if ! (grep -q 'Name:' /proc/1/status 2> /dev/null) ; then
Brian Davis's avatar
Brian Davis committed
613
    echo_message '\033[33m insufficient privileges for PaX ASLR checks\033[m\n' '' '' ''
614
    echo_message '  Fallback to standard Linux ASLR check' '' '' ''
Robin David's avatar
Robin David committed
615
  fi
slimm609's avatar
slimm609 committed
616

slimm609's avatar
slimm609 committed
617
618
  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
619
      echo_message '\033[32mPaX ASLR enabled\033[m\n\n' '' '' ''
Robin David's avatar
Robin David committed
620
    else
621
      echo_message '\033[31mPaX ASLR disabled\033[m\n\n' '' '' ''
Robin David's avatar
Robin David committed
622
623
    fi
  else
slimm609's avatar
slimm609 committed
624
  ${debug} && echo -e "\n***function aslrcheck->randomize_va_space"
Robin David's avatar
Robin David committed
625
626
    # standard Linux 'kernel.randomize_va_space' ASLR support
    # (see the kernel file 'Documentation/sysctl/kernel.txt' for a detailed description)
627
    echo_message " (kernel.randomize_va_space): " '' '' ''
Brian Davis's avatar
Brian Davis committed
628
    if sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 1'; then
629
      echo_message '\033[33mPartial (Setting: 1)\033[m\n\n' '' '' ''
630
631
632
633
      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
634
    elif sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 2'; then
635
      echo_message '\033[32mFull (Setting: 2)\033[m\n\n' '' '' ''
636
637
638
      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
639
    elif sysctl -a 2>/dev/null | grep -q 'kernel.randomize_va_space = 0'; then
640
      echo_message '\033[31mNone (Setting: 0)\033[m\n' '' '' ''
Robin David's avatar
Robin David committed
641
    else
642
      echo_message '\033[31mNot supported\033[m\n' '' '' ''
Robin David's avatar
Robin David committed
643
    fi
644
    echo_message "  See the kernel file 'Documentation/sysctl/kernel.txt' for more details.\n\n" '' '' ''
645
  fi
Robin David's avatar
Robin David committed
646
647
648
649
}

# check cpu nx flag
nxcheck() {
slimm609's avatar
slimm609 committed
650
  ${debug} && echo -e "\n***function nxcheck"
Robin David's avatar
Robin David committed
651
  if grep -q nx /proc/cpuinfo; then
652
    echo_message '\033[32mYes\033[m\n\n' '' '' ''
Robin David's avatar
Robin David committed
653
  else
654
    echo_message '\033[31mNo\033[m\n\n' '' '' ''
Robin David's avatar
Robin David committed
655
656
657
  fi
}

Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
658
659
#Check core dumps restricted?
coredumpcheck() {
slimm609's avatar
slimm609 committed
660
661
662
663
        ${debug} && echo -e "\n***function coredumpcheck"
        coreValue=$(grep -ic "hard core 0" /etc/security/limits.conf)
        dumpableValue=$(sysctl -b -e fs.suid_dumpable)
        if [[ "${coreValue}" == 1 ]] && [[ "${dumpableValue}" == 0 ]] || [[ "${dumpableValue}" == 2 ]]; then
Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
664
665
666
667
668
669
                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
670
671
# check for kernel protection mechanisms
kernelcheck() {
slimm609's avatar
slimm609 committed
672
  ${debug} && echo "***function kernelcheck"
673
674
675
676
  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
677
  echo_message "  Kernel config:\n" '' '' '{ "kernel": '
slimm609's avatar
slimm609 committed
678

slimm609's avatar
slimm609 committed
679
680
681
  if [[ ! "${1}" == "" ]] ; then
    kconfig="cat ${1}"
    echo_message "  Warning: The config ${1} on disk may not represent running kernel config!\n\n" "${1}" "<kernel config=\"${1}\"" "{ \"KernelConfig\":\"${1}\","
682
    # update the architecture based on the config rather than the system
slimm609's avatar
slimm609 committed
683
    if ${kconfig} | grep -qi 'CONFIG_ARM=y\|CONFIG_ARM=y'; then
684
685
      arch="arm"
    fi
slimm609's avatar
slimm609 committed
686
    if ${kconfig} | grep -qi 'CONFIG_ARM64=y'; then
Scott Ellis's avatar
Scott Ellis committed
687
688
      arch="aarch64"
    fi
slimm609's avatar
slimm609 committed
689
    if ${kconfig} | grep -qi 'CONFIG_X86_64=y'; then
690
691
      arch="64"
    fi
slimm609's avatar
slimm609 committed
692
    if ${kconfig} | grep -qi 'CONFIG_X86_32=y'; then
693
694
      arch="32"
    fi
slimm609's avatar
slimm609 committed
695
  elif [[ -f /proc/config.gz ]] ; then
Robin David's avatar
Robin David committed
696
    kconfig="zcat /proc/config.gz"
697
    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
698
  elif [[ -f /boot/config-"$(uname -r)" ]] ; then
slimm609's avatar
slimm609 committed
699
700
    kconfig="cat /boot/config-$(uname -r)"
    kern=$(uname -r)
slimm609's avatar
slimm609 committed
701
    echo_message "\033[33m/boot/config-${kern}\033[m\n\n" "/boot/config-${kern}," "<kernel config='/boot/config-${kern}'" "{ \"KernelConfig\":\"/boot/config-${kern}\","
702
    echo_message "  Warning: The config on disk may not represent running kernel config!\n\n" "" "" ""
slimm609's avatar
slimm609 committed
703
  elif [[ -f "${KBUILD_OUTPUT:-/usr/src/linux}"/.config ]] ; then
Robin David's avatar
Robin David committed
704
    kconfig="cat ${KBUILD_OUTPUT:-/usr/src/linux}/.config"
slimm609's avatar
signed    
slimm609 committed
705
    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\","
706
    echo_message "  Warning: The config on disk may not represent running kernel config!\n\n" "" "" ""
Robin David's avatar
Robin David committed
707
  else
708
    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
709
710
    exit 0
  fi
slimm609's avatar
slimm609 committed
711
712
  ${debug} && ${kconfig} | grep "CONFIG_GRKERNSEC"
  ${debug} && ${kconfig} | grep "CONFIG_PAX"
Robin David's avatar
Robin David committed
713

Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
714
  echo_message "  Vanilla Kernel ASLR:                    " "" "" ""
slimm609's avatar
signed    
slimm609 committed
715
  randomize_va=$(sysctl -b -e kernel.randomize_va_space)
slimm609's avatar
slimm609 committed
716
  if [[ "x${randomize_va}" == "x2" ]]; then
root's avatar
root committed
717
    echo_message "\033[32mFull\033[m\n" "Full," " randomize_va_space='full'" '"randomize_va_space":"full",'
slimm609's avatar
slimm609 committed
718
  elif [[ "x${randomize_va}" == "x1" ]]; then
root's avatar
root committed
719
720
721
722
723
    echo_message "\033[33mPartial\033[m\n" "Partial," " randomize_va_space='partial'" '"randomize_va_space":"partial",'
  else
    echo_message "\033[31mNone\033[m\n" "None," " randomize_va_space='none'" '"randomize_va_space":"none",'
  fi

Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
724
  echo_message "  Protected symlinks:                     " "" "" ""
slimm609's avatar
signed    
slimm609 committed
725
  symlink=$(sysctl -b -e fs.protected_symlinks)
slimm609's avatar
slimm609 committed
726
  if [[ "x${symlink}" == "x1" ]]; then
slimm609's avatar
signed    
slimm609 committed
727
728
729
730
731
    echo_message "\033[32mEnabled\033[m\n" "Enabled," " protect_symlinks='yes'" '"protect_symlinks":"yes",'
  else
    echo_message "\033[31mDisabled\033[m\n" "Disabled," " protect_symlinks='no'" '"protect_symlinks":"no",'
  fi

Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
732
  echo_message "  Protected hardlinks:                    " "" "" ""
slimm609's avatar
signed    
slimm609 committed
733
  hardlink=$(sysctl -b -e fs.protected_hardlinks)
slimm609's avatar
slimm609 committed
734
  if [[ "x${hardlink}" == "x1" ]]; then
slimm609's avatar
signed    
slimm609 committed
735
736
737
738
739
    echo_message "\033[32mEnabled\033[m\n" "Enabled," " protect_hardlinks='yes'" '"protect_hardlinks":"yes",'
  else
    echo_message "\033[31mDisabled\033[m\n" "Disabled," " protect_hardlinks='no'" '"protect_hardlinks":"no",'
  fi

Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
740
  echo_message "  Ipv4 reverse path filtering:            " "" "" ""
slimm609's avatar
signed    
slimm609 committed
741
  ipv4_rpath=$(sysctl -b -e net.ipv4.conf.all.rp_filter)
slimm609's avatar
slimm609 committed
742
  if [[ "x${ipv4_rpath}" == "x1" ]]; then
slimm609's avatar
signed    
slimm609 committed
743
744
745
746
747
    echo_message "\033[32mEnabled\033[m\n" "Enabled," " ipv4_rpath='yes'" '"ipv4_rpath":"yes",'
  else
    echo_message "\033[31mDisabled\033[m\n" "Disabled," " ipv4_rpath='no'" '"ipv4_rpath":"no",'
  fi

Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
748
  echo_message "  Ipv6 reverse path filtering:            " "" "" ""
slimm609's avatar
signed    
slimm609 committed
749
  ipv6_rpath=$(sysctl -b -e net.ipv6.conf.all.rp_filter)
slimm609's avatar
slimm609 committed
750
  if [[ "x${ipv6_rpath}" == "x1" ]]; then
slimm609's avatar
signed    
slimm609 committed
751
752
753
754
755
756
757
    echo_message "\033[32mEnabled\033[m\n" "Enabled," " ipv6_rpath='yes'" '"ipv6_rpath":"yes",'
  else
    echo_message "\033[31mDisabled\033[m\n" "Disabled," " ipv6_rpath='no'" '"ipv6_rpath":"no",'
  fi

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

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

slimm609's avatar
slimm609 committed
769
      if ${kconfig} | grep -qi 'CONFIG_CC_STACKPROTECTOR_STRONG' || ${kconfig} | grep -qi 'CONFIG_STACKPROTECTOR_STRONG'; then
slimm609's avatar
slimm609 committed
770
        echo_message "  GCC stack protector strong:             " "" "" ""
slimm609's avatar
slimm609 committed
771
        if ${kconfig} | grep -qi 'CONFIG_CC_STACKPROTECTOR_STRONG=y' || ${kconfig} | grep -qi 'CONFIG_STACKPROTECTOR_STRONG=y'; then
slimm609's avatar
slimm609 committed
772
773
774
775
          echo_message "\033[32mEnabled\033[m\n" "Enabled," " gcc_stack_protector_strong='yes'" '"gcc_stack_protector_strong":"yes",'
        else
          echo_message "\033[31mDisabled\033[m\n" "Disabled," " gcc_stack_protector_strong='no'" '"gcc_stack_protector_strong":"no",'
        fi
Scott Ellis's avatar
Scott Ellis committed
776
      fi
slimm609's avatar
slimm609 committed
777
778
779
    else
      echo_message "\033[31mDisabled\033[m\n" "Disabled," " gcc_stack_protector='no'" '"gcc_stack_protector":"no",'
    fi
Robin David's avatar
Robin David committed
780
781
  fi

slimm609's avatar
slimm609 committed
782
  if ${kconfig} | grep -qi 'CONFIG_GCC_PLUGIN_STRUCTLEAK'; then
slimm609's avatar
slimm609 committed
783
    echo_message "  GCC structleak plugin:                  " "" "" ""
slimm609's avatar
slimm609 committed
784
    if ${kconfig} | grep -qi 'CONFIG_GCC_PLUGIN_STRUCTLEAK=y'; then
slimm609's avatar
slimm609 committed
785
786
      echo_message "\033[32mEnabled\033[m\n" "Enabled," " gcc_structleak='yes'" '"gcc_structleak":"yes",'
      echo_message "  GCC structleak by ref plugin:           " "" "" ""
slimm609's avatar
slimm609 committed
787
      if ${kconfig} | grep -qi 'CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL=y'; then
slimm609's avatar
slimm609 committed
788
789
790
791
        echo_message "\033[32mEnabled\033[m\n" "Enabled," " gcc_structleak_byref='yes'" '"gcc_structleak_byref":"yes",'
      else
        echo_message "\033[32mEnabled\033[m\n" "Enabled," " gcc_structleak_byref='no'" '"gcc_structleak_byref":"no",'
      fi
792
    else
slimm609's avatar
slimm609 committed
793
      echo_message "\033[31mDisabled\033[m\n" "Disabled," " gcc_structleak='no'" '"gcc_structleak":"no",'
794
    fi
795
796
  fi

slimm609's avatar
slimm609 committed
797
  if ${kconfig} | grep -qi 'CONFIG_SLAB_FREELIST_RANDOM'; then
slimm609's avatar
slimm609 committed
798
    echo_message "  SLAB freelist randomization:            " "" "" ""
slimm609's avatar
slimm609 committed
799
    if ${kconfig} | grep -qi 'CONFIG_SLAB_FREELIST_RANDOM=y'; then
800
      echo_message "\033[32mEnabled\033[m\n" "Enabled," " slab_freelist_randomization='yes'" '"slab_freelist_randomization":"yes",'
slimm609's avatar
slimm609 committed
801
802
803
    else
      echo_message "\033[31mDisabled\033[m\n" "Disabled," " slab_freelist_randomization='no'" '"slab_freelist_randomization":"no",'
    fi
804
  fi
805

slimm609's avatar
slimm609 committed
806
  if ${kconfig} | grep -qi 'CPU_SW_DOMAIN_PAN=y'; then
slimm609's avatar
slimm609 committed
807
    echo_message "  Use CPU domains:                        " "" "" ""
slimm609's avatar
slimm609 committed
808
    if ${kconfig} | grep -qi 'CPU_SW_DOMAIN_PAN=y'; then
slimm609's avatar
slimm609 committed
809
810
811
812
813
814
815
      echo_message "\033[32mEnabled\033[m\n" "Enabled," " cpu_sw_domain'yes'" '"cpu_sw_domain":"yes",'
    else
      echo_message "\033[31mDisabled\033[m\n" "Disabled," " cpu_sw_domain='no'" '"cpu_sw_domain":"no",'
    fi
  fi


slimm609's avatar
slimm609 committed
816
  if ${kconfig} | grep -qi 'CONFIG_VMAP_STACK'; then
slimm609's avatar
slimm609 committed
817
    echo_message "  Virtually-mapped kernel stack:          " "" "" ""
slimm609's avatar
slimm609 committed
818
    if ${kconfig} | grep -qi 'CONFIG_VMAP_STACK=y'; then
slimm609's avatar
slimm609 committed
819
820
821
822
      echo_message "\033[32mEnabled\033[m\n" "Enabled," " virtually_mapped_stack='yes'" '"virtually_mapped_stack":"yes",'
    else
      echo_message "\033[31mDisabled\033[m\n" "Disabled," " virtually_mapped_stack='no'" '"virtually_mapped_stack":"no",'
    fi
823
824
  fi

slimm609's avatar
slimm609 committed
825

slimm609's avatar
slimm609 committed
826
827
  if ${kconfig} | grep -qi 'CONFIG_DEVMEM'; then
    if ${kconfig} | grep -qi 'CONFIG_DEVMEM=y'; then
828
      echo_message "  Restrict /dev/mem access:               " "" "" ""
slimm609's avatar
slimm609 committed
829
      if ${kconfig} | grep -qi 'CONFIG_STRICT_DEVMEM=y'; then
830
831
832
833
        echo_message "\033[32mEnabled\033[m\n" "Enabled," " restrict_dev_mem_access='yes'" '"restrict_dev_mem_access":"yes",'
      else
        echo_message "\033[31mDisabled\033[m\n" "Disabled," " restrict_dev_mem_access='no'" '"restrict_dev_mem_access":"no",'
      fi
slimm609's avatar
slimm609 committed
834

835
      echo_message "  Restrict I/O access to /dev/mem:        " "" "" ""
slimm609's avatar
slimm609 committed
836
      if ${kconfig} | grep -qi 'CONFIG_IO_STRICT_DEVMEM=y'; then
837
838
839
840
        echo_message "\033[32mEnabled\033[m\n" "Enabled," " restrict_io_dev_mem_access='yes'" '"restrict_io_dev_mem_access":"yes",'
      else
        echo_message "\033[31mDisabled\033[m\n" "Disabled," " restrict_io_dev_mem_access='no'" '"restrict_io_dev_mem_access":"no",'
      fi
slimm609's avatar
slimm609 committed
841
842
843
844
    fi
  fi


slimm609's avatar
slimm609 committed
845
846
  if ! ${kconfig} | grep -qi 'CONFIG_PAX'; then
    if ${kconfig} | grep -qi 'CONFIG_DEBUG_RODATA' || ${kconfig} | grep -qi '|CONFIG_STRICT_KERNEL_RWX'; then
slimm609's avatar
slimm609 committed
847
      echo_message "  Enforce read-only kernel data:          " "" "" ""
slimm609's avatar
slimm609 committed
848
      if ${kconfig} | grep -qi 'CONFIG_DEBUG_RODATA=y\|CONFIG_STRICT_KERNEL_RWX=y'; then
slimm609's avatar
slimm609 committed
849
850
        echo_message "\033[32mEnabled\033[m\n" "Enabled," " ro_kernel_data='yes'" '"ro_kernel_data":"yes",'
        echo_message "  Enforce read-only module data:          " "" "" ""
slimm609's avatar
slimm609 committed
851
        if ${kconfig} | grep -qi 'CONFIG_STRICT_MODULE_RWX=y\|CONFIG_DEBUG_SET_MODULE_RONX'; then
slimm609's avatar
slimm609 committed
852
853
854
855
          echo_message "\033[32mEnabled\033[m\n" "Enabled," " ro_module_data='yes'" '"ro_module_data":"yes",'
        else
          echo_message "\033[31mDisabled\033[m\n" "Disabled," " ro_module_data='no'" '"ro_module_data":"no",'
        fi
slimm609's avatar
slimm609 committed
856
      else
slimm609's avatar
slimm609 committed
857
        echo_message "\033[31mDisabled\033[m\n" "Disabled," " ro_kernel_data='no'" '"ro_kernel_data":"no",'
slimm609's avatar
slimm609 committed
858
      fi
859
    fi
Robin David's avatar
Robin David committed
860
  fi
slimm609's avatar
signed    
slimm609 committed
861

slimm609's avatar
slimm609 committed
862
  if ${kconfig} | grep -qi 'CONFIG_REFCOUNT_FULL'; then
863
    echo_message "  Full reference count validation:        " "" "" ""
slimm609's avatar
slimm609 committed
864
    if ${kconfig} | grep -qi 'CONFIG_REFCOUNT_FULL=y'; then
865
866
867
868
869
870
      echo_message "\033[32mEnabled\033[m\n" "Enabled," " full_refcount_validation='yes'" '"full_refcount_validation":"yes",'
    else
      echo_message "\033[31mDisabled\033[m\n" "Disabled," " full_refcount_validation='no'" '"full_refcount_validation":"no",'
    fi
  fi

871
  echo_message "  Exec Shield:                            " """" ""
slimm609's avatar
slimm609 committed
872
  if grep -qi 'kernel.exec-shield = 1' /etc/sysctl.conf 2>/dev/null ; then
873
874
875
876
    echo_message '\033[32mEnabled\033[m\n\n' '' '' ''
  else
    echo_message '\033[31mDisabled\033[m\n\n' '' '' ''
  fi
Kirit Sankar Gupta's avatar
Kirit Sankar Gupta committed
877

slimm609's avatar
slimm609 committed
878
  if ${kconfig} | grep -qi 'CONFIG_HARDENED_USERCOPY'; then
slimm609's avatar
slimm609 committed
879
    echo_message "  Hardened Usercopy:                      " "" "" ""
slimm609's avatar
slimm609 committed
880
    if ${kconfig} | grep -qi 'CONFIG_HARDENED_USERCOPY=y'; then
slimm609's avatar
slimm609 committed
881
882
      echo_message "\033[32mEnabled\033[m\n" "Enabled," " hardened_usercopy='yes'" '"hardened_usercopy":"yes",'
      echo_message "  Hardened Usercopy Pagespan:             " "" "" ""
slimm609's avatar
slimm609 committed
883
      if ${kconfig} | grep -qi 'CONFIG_HARDENED_USERCOPY_PAGESPAN=y'; then
slimm609's avatar