mirror of https://github.com/CISOfy/lynis.git
823 lines
40 KiB
Bash
823 lines
40 KiB
Bash
#!/bin/sh
|
|
|
|
#################################################################################
|
|
#
|
|
# Lynis
|
|
# ------------------
|
|
#
|
|
# Copyright 2007-2013, Michael Boelen
|
|
# Copyright 2007-2017, CISOfy
|
|
#
|
|
# Website : https://cisofy.com
|
|
# Blog : http://linux-audit.com
|
|
# GitHub : https://github.com/CISOfy/lynis
|
|
#
|
|
# Lynis comes with ABSOLUTELY NO WARRANTY. This is free software, and you are
|
|
# welcome to redistribute it under the terms of the GNU General Public License.
|
|
# See LICENSE file for usage of this software.
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Category: Boot and services
|
|
#
|
|
#################################################################################
|
|
#
|
|
InsertSection "Boot and services"
|
|
#
|
|
#################################################################################
|
|
#
|
|
BOOT_LOADER="unknown"
|
|
BOOT_LOADER_FOUND=0
|
|
BOOT_LOADER_SEARCHED=0
|
|
GRUB_VERSION=0
|
|
SERVICE_MANAGER="unknown"
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5102
|
|
# Description : Check for AIX boot device
|
|
# Notes : The AIX bootstrap is called as software ROS. Bootstrap contains IPL (Initial Program loader)
|
|
# TODO - binary detection of bootinfo and replace with variable
|
|
Register --test-no BOOT-5102 --os AIX --weight L --network NO --root-only YES --category security --description "Check for AIX boot device"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
BOOT_LOADER_SEARCHED=1
|
|
LogText "Test: Query bootinfo for AIX boot device"
|
|
if [ -x /usr/sbin/bootinfo ]; then
|
|
FIND=$(/usr/sbin/bootinfo -b)
|
|
if [ ! -z "${FIND}" ]; then
|
|
LogText "Result: found boot device ${FIND}"
|
|
Display --indent 2 --text "- Checking boot device (bootinfo)" --result "${STATUS_FOUND}" --color GREEN
|
|
BOOT_LOADER="ROS"
|
|
BOOT_LOADER_FOUND=1
|
|
else
|
|
LogText "Result: no data received from bootinfo, most likely boot device not found"
|
|
#Display --indent 4 --text "- Checking boot device (bootinfo)" --result "${STATUS_NOT_FOUND}" --color YELLOW
|
|
#ReportSuggestion ${TEST_NO} "Only use root (not sudo account) to query properly boot device"
|
|
fi
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5104
|
|
# Description : Determine service manager
|
|
# Notes :
|
|
# initscripts - Used by Arch before
|
|
# systemd - Common option with more Linux distros implementing it
|
|
# upstart - Used by Debian/Ubuntu
|
|
Register --test-no BOOT-5104 --weight L --network NO --category security --description "Determine service manager"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
BOOT_LOADER_SEARCHED=1
|
|
case ${OS} in
|
|
"Linux")
|
|
if [ -f /proc/1/cmdline ]; then
|
|
FILENAME=$(${AWKBINARY} '/(^\/|init)/ { print $1 }' /proc/1/cmdline)
|
|
LogText "Result: cmdline found = ${FILENAME}"
|
|
ISFILE=$(echo ${FILENAME} | ${GREPBINARY} "^/")
|
|
if [ ! "${ISFILE}" = "" ]; then
|
|
if [ -L ${ISFILE} ]; then
|
|
ShowSymlinkPath ${ISFILE}
|
|
FILENAME="${SYMLINK}"
|
|
elif [ -f ${ISFILE} ]; then
|
|
FILENAME="${ISFILE}"
|
|
else
|
|
LogText "Result: cmdline of PID 1 is not a file"
|
|
fi
|
|
fi
|
|
if [ ! "${FILENAME}" = "" ]; then
|
|
SHORTNAME=$(echo ${FILENAME} | ${AWKBINARY} -F/ '{ print $NF }')
|
|
LogText "Found: ${SHORTNAME}"
|
|
case ${SHORTNAME} in
|
|
"init" | "initsplash")
|
|
SERVICE_MANAGER="SysV Init"
|
|
;;
|
|
systemd)
|
|
SERVICE_MANAGER="systemd"
|
|
;;
|
|
upstart)
|
|
SERVICE_MANAGER="upstart"
|
|
;;
|
|
*)
|
|
CONTAINS_SYSTEMD=$(echo ${SHORTNAME} | ${GREPBINARY} "systemd")
|
|
if [ ! -z "${CONTAINS_SYSTEMD}" ]; then
|
|
SERVICE_MANAGER="systemd"
|
|
else
|
|
LogText "Found ${SHORTNAME}. Unclear what service manager this is"
|
|
ReportException "${TEST_NO}:001" "Unknown service manager"
|
|
fi
|
|
;;
|
|
esac
|
|
else
|
|
LogText "Result: /proc/1/cmdline seems to be empty"
|
|
ReportException "${TEST_NO}:002" "No data found in /proc/1/cmdline"
|
|
fi
|
|
fi
|
|
# Continue testing if we didn't find it yet
|
|
if [ "${SERVICE_MANAGER}" = "unknown" ]; then
|
|
if [ -f /usr/bin/init-openrc ]; then SERVICE_MANAGER="openrc"; fi
|
|
fi
|
|
;;
|
|
"DragonFly" | "NetBSD" | "FreeBSD")
|
|
if [ -x /sbin/init -a -d ${ROOTDIR}etc/rc.d -a -f ${ROOTDIR}etc/rc ]; then
|
|
SERVICE_MANAGER="bsdrc"
|
|
fi
|
|
;;
|
|
*)
|
|
LogText "Result: unknown service manager"
|
|
;;
|
|
esac
|
|
LogText "Result: service manager found = ${SERVICE_MANAGER}"
|
|
if [ "${SERVICE_MANAGER}" = "" -o "${SERVICE_MANAGER}" = "unknown" ]; then
|
|
Display --indent 2 --text "- Service Manager" --result "${STATUS_UNKNOWN}" --color YELLOW
|
|
else
|
|
Display --indent 2 --text "- Service Manager" --result "${SERVICE_MANAGER}" --color GREEN
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5106
|
|
# Description : Check if boot.efi is found on macOS/macOS
|
|
Register --test-no BOOT-5106 --os "macOS" --weight L --network NO --root-only YES --category security --description "Check EFI boot file on Mac OS X/macOS"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FileExists ${ROOTDIR}System/Library/CoreServices/boot.efi
|
|
if [ ${FILE_FOUND} -eq 1 ]; then
|
|
LogText "Result: found macOS/Mac OS X boot.efi file"
|
|
BOOT_LOADER="macOS-boot-EFI"
|
|
BOOT_LOADER_FOUND=1
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5108
|
|
# Description : Check for Syslinux
|
|
Register --test-no BOOT-5108 --os "Linux" --weight L --network NO --root-only YES --category security --description "Check Syslinux as bootloader"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FileExists ${ROOTDIR}boot/syslinux/syslinux.cfg
|
|
if [ ${FILE_FOUND} -eq 1 ]; then
|
|
LogText "Result: found Syslinux"
|
|
BOOT_LOADER="Syslinux"
|
|
BOOT_LOADER_FOUND=1
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5116
|
|
# Description : Check if system is booted in UEFI mode
|
|
Register --test-no BOOT-5116 --weight L --network NO --root-only YES --category security --description "Check if system is booted in UEFI mode"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
UEFI_TESTS_PERFORMED=0
|
|
case ${OS} in
|
|
Linux)
|
|
UEFI_TESTS_PERFORMED=1
|
|
# Check if UEFI is available in this boot
|
|
LogText "Test: checking if UEFI is used"
|
|
if [ -d ${ROOTDIR}sys/firmware/efi ]; then
|
|
LogText "Result: system booted in UEFI mode"
|
|
UEFI_BOOTED=1
|
|
else
|
|
LogText "Result: UEFI not used, can't find /sys/firmware/efi directory"
|
|
fi
|
|
|
|
# Test if Secure Boot is enabled
|
|
LogText "Test: determine if Secure Boot is used"
|
|
if [ -d ${ROOTDIR}sys/firmware/efi/efivars ]; then
|
|
FIND=$(${LSBINARY} ${ROOTDIR}sys/firmware/efi/efivars/SecureBoot-* 2> /dev/null)
|
|
if [ ! -z "${FIND}" ]; then
|
|
for FILE in ${FIND}; do
|
|
LogText "Test: checking file ${FILE}"
|
|
# TODO: add detection for od
|
|
J=$(od -An -t u1 ${FILE} | ${AWKBINARY} '{ print $5 }')
|
|
if [ "${J}" = "1" ]; then
|
|
LogText "Result: found SecureBoot file with enabled status"
|
|
UEFI_BOOTED_SECURE=1
|
|
else
|
|
LogText "Result: system not booted with Secure Boot (status 0 in file ${FILE})"
|
|
fi
|
|
done
|
|
fi
|
|
else
|
|
LogText "Result: system not booted with Secure Boot (no SecureBoot file found)"
|
|
fi
|
|
;;
|
|
#macOS)
|
|
# TODO: macOS ioreg -l -p IODeviceTree | ${GREPBINARY} firmware-abi
|
|
#;;
|
|
*)
|
|
LogText "Result: no test implemented yet to test for UEFI on this platform"
|
|
;;
|
|
esac
|
|
if [ ${UEFI_BOOTED} -eq 1 ]; then
|
|
Display --indent 2 --text "- Checking UEFI boot" --result "${STATUS_ENABLED}" --color GREEN
|
|
if [ ${UEFI_BOOTED_SECURE} -eq 1 ]; then
|
|
Display --indent 2 --text "- Checking Secure Boot" --result "${STATUS_ENABLED}" --color GREEN
|
|
else
|
|
Display --indent 2 --text "- Checking Secure Boot" --result "${STATUS_DISABLED}" --color YELLOW
|
|
fi
|
|
else
|
|
if [ ${UEFI_TESTS_PERFORMED} -eq 1 ]; then
|
|
Display --indent 2 --text "- Checking UEFI boot" --result "${STATUS_DISABLED}" --color WHITE
|
|
fi
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5121
|
|
# Description : Check for GRUB boot loader
|
|
Register --test-no BOOT-5121 --weight L --network NO --category security --description "Check for GRUB boot loader presence"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
BOOT_LOADER_SEARCHED=1
|
|
FOUND=0
|
|
LogText "Test: Checking for presence GRUB conf file (/boot/grub/grub.conf or /boot/grub/menu.lst)"
|
|
if [ -f /boot/grub/grub.conf -o -f /boot/grub/menu.lst ]; then
|
|
FOUND=1
|
|
BOOT_LOADER="GRUB"
|
|
BOOT_LOADER_FOUND=1
|
|
GRUB_VERSION=1
|
|
Display --indent 2 --text "- Checking presence GRUB" --result "${STATUS_OK}" --color GREEN
|
|
if [ -f /boot/grub/grub.conf ]; then GRUBCONFFILE="/boot/grub/grub.conf"; else GRUBCONFFILE="/boot/grub/menu.lst"; fi
|
|
fi
|
|
|
|
# GRUB2 configuration file
|
|
if [ -f /boot/grub/grub.cfg -o -f /boot/grub2/grub.cfg ]; then
|
|
FOUND=1
|
|
BOOT_LOADER="GRUB2"
|
|
BOOT_LOADER_FOUND=1
|
|
GRUB_VERSION=2
|
|
Display --indent 2 --text "- Checking presence GRUB2" --result "${STATUS_FOUND}" --color GREEN
|
|
if [ -f /boot/grub/grub.cfg ]; then
|
|
GRUBCONFFILE="/boot/grub/grub.cfg"
|
|
elif [ -f /boot/grub2/grub.cfg ]; then
|
|
GRUBCONFFILE="/boot/grub2/grub.cfg"
|
|
fi
|
|
LogText "Result: found GRUB2 configuration file (${GRUBCONFFILE})"
|
|
fi
|
|
|
|
# Some OSes like Gentoo do not have /boot mounted by default
|
|
# TODO: root directory and rewrite ls statement
|
|
if [ -d /boot ]; then
|
|
if [ "`ls /boot/* 2> /dev/null`" = "" -a ! -z "${GRUB2INSTALLBINARY}" ]; then
|
|
BOOT_LOADER_FOUND=1
|
|
LogText "Result: found empty /boot, however with GRUB2 binary installed. Best guess is that GRUB2 is actually installed, but /boot not mounted"
|
|
Display --indent 2 --text "- Checking presence GRUB2" --result "POSSIBLE MATCH" --color YELLOW
|
|
ReportManual "${TEST_NO}:01"
|
|
fi
|
|
fi
|
|
|
|
if [ ${FOUND} -eq 0 ]; then
|
|
LogText "Result: no GRUB configuration file found."
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5122
|
|
# Description : Check for GRUB boot loader configuration
|
|
if [ ! "${GRUBCONFFILE}" = "" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
|
|
Register --test-no BOOT-5122 --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for GRUB boot password"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FOUND=0
|
|
LogText "Found file ${GRUBCONFFILE}, proceeding with tests."
|
|
FileIsReadable ${GRUBCONFFILE}
|
|
if [ ${CANREAD} -eq 1 ]; then
|
|
FIND=$(${GREPBINARY} 'password --md5' ${GRUBCONFFILE} | ${GREPBINARY} -v '^#')
|
|
FIND2=$(${GREPBINARY} 'password --encrypted' ${GRUBCONFFILE} | ${GREPBINARY} -v '^#')
|
|
FIND3=$(${GREPBINARY} 'set superusers' ${GRUBCONFFILE} | ${GREPBINARY} -v '^#')
|
|
FIND4=$(${GREPBINARY} 'password_pbkdf2' ${GRUBCONFFILE} | ${GREPBINARY} -v '^#')
|
|
FIND5=$(${GREPBINARY} 'grub.pbkdf2' ${GRUBCONFFILE} | ${GREPBINARY} -v '^#')
|
|
# GRUB1: Password should be set (MD5 or SHA1)
|
|
if [ ! -z "${FIND}" -o ! -z "${FIND2}" ]; then
|
|
FOUND=1
|
|
# GRUB2: Superusers AND password should be defined
|
|
elif [ ! -z "${FIND3}" ]; then
|
|
if [ ! -z "${FIND4}" -o ! -z "${FIND5}" ]; then FOUND=1; fi
|
|
fi
|
|
if [ ${FOUND} -eq 1 ]; then
|
|
Display --indent 4 --text "- Checking for password protection" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Result: GRUB has password protection."
|
|
AddHP 4 4
|
|
else
|
|
Display --indent 4 --text "- Checking for password protection" --result "${STATUS_WARNING}" --color RED
|
|
LogText "Result: Didn't find hashed password line in GRUB boot file!"
|
|
ReportSuggestion ${TEST_NO} "Set a password on GRUB bootloader to prevent altering boot configuration (e.g. boot in single user mode without password)"
|
|
AddHP 0 2
|
|
fi
|
|
else
|
|
LogText "Result: Can not read ${GRUBCONFFILE} (no permission)"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5124
|
|
# Description : Check for FreeBSD boot loader
|
|
Register --test-no BOOT-5124 --os FreeBSD --weight L --network NO --category security --description "Check for FreeBSD boot loader presence"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
BOOT_LOADER_SEARCHED=1
|
|
if [ -f ${ROOTDIR}boot/boot1 -a -f ${ROOTDIR}boot/boot2 -a -f ${ROOTDIR}boot/loader ]; then
|
|
LogText "Result: found boot1, boot2 and loader files in ${ROOTDIR}boot"
|
|
Display --indent 2 --text "- Checking presence FreeBSD loader" --result "${STATUS_FOUND}" --color GREEN
|
|
BOOT_LOADER="FreeBSD"
|
|
BOOT_LOADER_FOUND=1
|
|
else
|
|
LogText "Result: Not all expected files found in ${ROOTDIR}boot"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5261
|
|
# Description : Check for DragonFly boot loader
|
|
Register --test-no BOOT-5261 --os DragonFly --weight L --network NO --category security --description "Check for DragonFly boot loader presence"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
BOOT_LOADER_SEARCHED=1
|
|
if [ -f ${ROOTDIR}boot/boot1 -a -f ${ROOTDIR}boot/boot2 -a -f ${ROOTDIR}boot/loader ]; then
|
|
LogText "Result: found boot1, boot2 and loader files in ${ROOTDIR}boot"
|
|
Display --indent 2 --text "- Checking presence DragonFly loader" --result "${STATUS_FOUND}" --color GREEN
|
|
BOOT_LOADER="DragonFly"
|
|
BOOT_LOADER_FOUND=1
|
|
else
|
|
LogText "Result: Not all expected files found in ${ROOTDIR}boot"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5126
|
|
# Description : Check for NetBSD boot loader
|
|
Register --test-no BOOT-5126 --os NetBSD --weight L --network NO --category security --description "Check for NetBSD boot loader presence"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
BOOT_LOADER_SEARCHED=1
|
|
if [ -f ${ROOTDIR}boot.${HARDWARE} -o -f ${ROOTDIR}boot -o -f ${ROOTDIR}ofwboot ]; then
|
|
LogText "Result: found NetBSD secondary bootstrap"
|
|
Display --indent 2 --text "- Checking presence NetBSD loader" --result "${STATUS_FOUND}" --color GREEN
|
|
BOOT_LOADER="NetBSD"
|
|
BOOT_LOADER_FOUND=1
|
|
else
|
|
LogText "Result: NetBSD secondary bootstrap not found"
|
|
ReportException "${TEST_NO}:1" "No boot loader found on NetBSD"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5139
|
|
# Description : Check for LILO boot loader
|
|
# Notes : password= or password =
|
|
Register --test-no BOOT-5139 --weight L --network NO --category security --description "Check for LILO boot loader presence"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
BOOT_LOADER_SEARCHED=1
|
|
LILOCONFFILE="${ROOTDIR}etc/lilo.conf"
|
|
LogText "Test: checking for presence LILO configuration file"
|
|
if [ -f ${LILOCONFFILE} ]; then
|
|
FileIsReadable ${LILOCONFFILE}
|
|
if [ ${CANREAD} -eq 1 ]; then
|
|
BOOT_LOADER="LILO"
|
|
BOOT_LOADER_FOUND=1
|
|
Display --indent 2 --text "- Checking presence LILO" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Checking password option LILO"
|
|
FIND=$(${EGREPBINARY} 'password[[:space:]]?=' ${LILOCONFFILE} | ${GREPBINARY} -v "^#")
|
|
if [ -z "${FIND}" ]; then
|
|
if [ "${MACHINE_ROLE}" = "server" -o "${MACHINE_ROLE}" = "workstation" ]; then
|
|
Display --indent 4 --text "- Password option presence " --result "${STATUS_WARNING}" --color RED
|
|
LogText "Result: no password set for LILO. Bootloader is unprotected to dropping to single user mode or unauthorized access to devices/data."
|
|
ReportSuggestion ${TEST_NO} "Add a password to LILO, by adding a line to the lilo.conf file, above the first line saying 'image=<name>': password=<password>"
|
|
ReportWarning ${TEST_NO} "No password set on LILO bootloader"
|
|
AddHP 0 2
|
|
elif [ "${MACHINE_ROLE}" = "personal"]; then
|
|
Display --indent 4 --text "- Password option presence " --result "${STATUS_WARNING}" --color yellow
|
|
LogText "Result: no password set for LILO. Bootloader is unprotected to dropping to single user mode or unauthorized access to devices/data."
|
|
ReportSuggestion ${TEST_NO} "No password set on LILO bootloader. Add a password to LILO, by adding a line to the lilo.conf file, above the first line saying 'image=<name>': password=<password>"
|
|
AddHP 1 2
|
|
else
|
|
LogText "Result: no password set for LILO, with unknown machine role"
|
|
fi
|
|
else
|
|
Display --indent 4 --text "- Password option presence " --result "${STATUS_OK}" --color GREEN
|
|
LogText "Result: LILO password option set"
|
|
AddHP 4 4
|
|
fi
|
|
else
|
|
LogText "Result: can not read ${LILOCONFFILE} (no permission)"
|
|
fi
|
|
else
|
|
LogText "Result: LILO configuration file not found"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5142
|
|
# Description : Check for SILO boot loader
|
|
Register --test-no BOOT-5142 --weight L --network NO --category security --description "Check SPARC Improved boot loader (SILO)"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
BOOT_LOADER_SEARCHED=1
|
|
if [ -f /etc/silo.conf ]; then
|
|
LogText "Result: Found SILO configuration file (/etc/silo.conf)"
|
|
Display --indent 2 --text "- Checking boot loader SILO" --result "${STATUS_FOUND}" --color GREEN
|
|
BOOT_LOADER="SILO"
|
|
BOOT_LOADER_FOUND=1
|
|
else
|
|
LogText "Result: no SILO configuration file found."
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5155
|
|
# Description : Check for YABOOT boot loader
|
|
Register --test-no BOOT-5155 --weight L --network NO --category security --description "Check for YABOOT boot loader configuration file"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
BOOT_LOADER_SEARCHED=1
|
|
LogText "Test: Check for /etc/yaboot.conf"
|
|
if [ -f /etc/yaboot.conf ]; then
|
|
LogText "Result: Found YABOOT configuration file (/etc/yaboot.conf)"
|
|
Display --indent 4 --text "- Checking boot loader YABOOT" --result "${STATUS_FOUND}" --color GREEN
|
|
BOOT_LOADER="YABOOT"
|
|
BOOT_LOADER_FOUND=1
|
|
else
|
|
LogText "Result: no YABOOT configuration file found."
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5159
|
|
# Description : Check for OpenBSD boot loader
|
|
# More info : Only OpenBSD
|
|
Register --test-no BOOT-5159 --os OpenBSD --weight L --network NO --category security --description "Check for OpenBSD boot loader presence"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
BOOT_LOADER_SEARCHED=1
|
|
FOUND=0
|
|
# Boot files
|
|
# /usr/mdec/biosboot: first stage bootstrap
|
|
# /boot : second stage bootstrap
|
|
if [ -f ${ROOTDIR}usr/mdec/biosboot -a -f ${ROOTDIR}boot ]; then
|
|
FOUND=1
|
|
fi
|
|
# Configuration file
|
|
if [ -f ${ROOTDIR}etc/boot.conf ]; then
|
|
FOUND=1
|
|
Display --indent 2 --text "- Checking ${ROOTDIR}etc/boot.conf" --result "${STATUS_FOUND}" --color GREEN
|
|
FIND=$(${GREPBINARY} '^boot' ${ROOTDIR}etc/boot.conf)
|
|
if [ -z "${FIND}" ]; then
|
|
Display --indent 4 --text "- Checking boot option" --result "${STATUS_WARNING}" --color RED
|
|
#ReportSuggestion ${TEST_NO} "Add 'boot' to the ${ROOTDIR}etc/boot.conf file to disable the default 5 seconds waiting time, to disallow booting into single user mode."
|
|
ReportWarning ${TEST_NO} "System can be booted into single user mode without password"
|
|
else
|
|
Display --indent 4 --text "- Checking boot option" --result "${STATUS_OK}" --color GREEN
|
|
LogText "Ok, boot option is enabled."
|
|
fi
|
|
else
|
|
Display --indent 2 --text "- Checking ${ROOTDIR}etc/boot.conf" --result "${STATUS_NOT_FOUND}" --color YELLOW
|
|
LogText "Result: no ${ROOTDIR}etc/boot.conf found. When using the default boot loader, physical"
|
|
LogText "access to the server can be used to possibly enter single user mode."
|
|
ReportSuggestion ${TEST_NO} "Add 'boot' to the ${ROOTDIR}etc/boot.conf file to disable the default 5 seconds waiting time."
|
|
fi
|
|
if [ ${FOUND} -eq 1 ]; then
|
|
LogText "Result: found OpenBSD boot loader"
|
|
BOOT_LOADER="OpenBSD"
|
|
BOOT_LOADER_FOUND=1
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
if [ ${BOOT_LOADER_FOUND} -eq 0 -a ${BOOT_LOADER_SEARCHED} -eq 1 ]; then
|
|
# Your boot loader is not detected. Want to help supporting it, see the README
|
|
# ReportException "BOOTLOADER" "No boot loader found"
|
|
Display --indent 4 --text "- Boot loader" --result "NONE FOUND" --color YELLOW
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5165
|
|
# Description : Check for FreeBSD boot services
|
|
Register --test-no BOOT-5165 --os FreeBSD --weight L --network NO --category security --description "Check for FreeBSD boot services"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
if [ ! "${SERVICEBINARY}" = "" ]; then
|
|
# FreeBSD (Ask services(8) for enabled services)
|
|
LogText "Searching for services at startup (service)"
|
|
FIND=$(${SERVICEBINARY} -e | ${SEDBINARY} 's|^.*\/||' | ${SORTBINARY})
|
|
else
|
|
# FreeBSD (Read /etc/rc.conf file for enabled services)
|
|
LogText "Searching for services at startup (rc.conf)"
|
|
FIND=$(${EGREPBINARY} -v -i '^#|none' /etc/rc.conf | ${EGREPBINARY} -i '_enable.*(yes|on|1)' | ${SORTBINARY} | ${AWKBINARY} -F= '{ print $1 }' | ${SEDBINARY} 's/_enable//')
|
|
fi
|
|
N=0
|
|
for I in ${FIND}; do
|
|
LogText "Found service (service/rc.conf): ${I}"
|
|
Report "boottask[]=${I}"
|
|
N=$((N + 1))
|
|
done
|
|
Display --indent 2 --text "- Checking services at startup (service/rc.conf)" --result "${STATUS_DONE}" --color GREEN
|
|
Display --indent 6 --text "Result: found $N services/options set"
|
|
LogText "Found $N services/options to run at startup"
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5177
|
|
# Description : Check for Linux boot services (systemd and chkconfig)
|
|
# Notes : We skip using chkconfig if systemd is being used.
|
|
Register --test-no BOOT-5177 --os Linux --weight L --network NO --category security --description "Check for Linux boot and running services"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
CHECKED=0
|
|
LogText "Test: checking presence systemctl binary"
|
|
# Determine if we have systemctl on board
|
|
if [ ! -z "${SYSTEMCTLBINARY}" ]; then
|
|
LogText "Result: systemctl binary found, trying that to discover information"
|
|
# Running services
|
|
LogText "Searching for running services (systemctl services only)"
|
|
FIND=$(${SYSTEMCTLBINARY} --full --type=service | ${AWKBINARY} '{ if ($4=="running") { print $1 } }' | ${AWKBINARY} -F. '{ print $1 }')
|
|
N=0
|
|
Report "running_service_tool=systemctl"
|
|
for I in ${FIND}; do
|
|
LogText "Found running service: ${I}"
|
|
Report "running_service[]=${I}"
|
|
N=$((N + 1))
|
|
done
|
|
LogText "Note: Run systemctl --full --type=service to see all services"
|
|
Display --indent 2 --text "- Check running services (systemctl)" --result "${STATUS_DONE}" --color GREEN
|
|
Display --indent 8 --text "Result: found $N running services"
|
|
LogText "Result: Found $N enabled services"
|
|
|
|
# Services at boot
|
|
LogText "Searching for enabled services (systemctl services only)"
|
|
FIND=$(${SYSTEMCTLBINARY} list-unit-files --type=service | ${SORTBINARY} -u | ${AWKBINARY} '{ if ($2=="enabled") { print $1 } }' | ${AWKBINARY} -F. '{ print $1 }')
|
|
N=0
|
|
Report "boot_service_tool=systemctl"
|
|
for I in ${FIND}; do
|
|
LogText "Found enabled service at boot: ${I}"
|
|
Report "boot_service[]=${I}"
|
|
N=$((N + 1))
|
|
done
|
|
LogText "Note: Run systemctl list-unit-files --type=service to see all services"
|
|
Display --indent 2 --text "- Check enabled services at boot (systemctl)" --result "${STATUS_DONE}" --color GREEN
|
|
Display --indent 8 --text "Result: found $N enabled services"
|
|
LogText "Result: Found $N running services"
|
|
|
|
else
|
|
|
|
LogText "Result: systemctl binary not found, checking chkconfig binary"
|
|
if [ ! -z "${CHKCONFIGBINARY}" ]; then
|
|
LogText "Result: chkconfig binary found, trying that to discover information"
|
|
LogText "Searching for services at startup (chkconfig, runlevel 3 and 5)"
|
|
FIND=$(${CHKCONFIGBINARY} --list | ${EGREPBINARY} '3:on|5:on' | ${AWKBINARY} '{ print $1 }')
|
|
N=0
|
|
Report "boot_service_tool=chkconfig"
|
|
for I in ${FIND}; do
|
|
LogText "Found service (at boot, runlevel 3 or 5): ${I}"
|
|
Report "boot_service[]=${I}"
|
|
N=$((N + 1))
|
|
done
|
|
LogText "Hint: Run chkconfig --list to see all services and disable unneeded services"
|
|
Display --indent 2 --text "- Check services at startup (chkconfig)" --result "${STATUS_DONE}" --color GREEN
|
|
Display --indent 8 --text "Result: found $N services"
|
|
LogText "Result: Found $N services at startup"
|
|
else
|
|
LogText "Result: both systemctl and chkconfig not found. Skipping this test"
|
|
fi
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5180
|
|
# Description : Check for Linux boot services (Debian style)
|
|
# Notes : Debian 8+ shows runlevel 5
|
|
if [ "${LINUX_VERSION}" = "Debian" -o "${LINUX_VERSION}" = "Ubuntu" ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi
|
|
Register --test-no BOOT-5180 --os Linux --preqs-met ${PREQS_MET} --weight L --network NO --category security --description "Check for Linux boot services (Debian style)"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
# Runlevel check
|
|
sRUNLEVEL=$(${RUNLEVELBINARY} | ${GREPBINARY} "N [0-9]" | ${AWKBINARY} '{ print $2} ')
|
|
LogText "Result: found runlevel ${sRUNLEVEL}"
|
|
if [ "${sRUNLEVEL}" = "2" ]; then
|
|
LogText "Result: performing find in /etc/rc2.d as runlevel 2 is found"
|
|
FIND=$(${FINDBINARY} ${ROOTDIR}etc/rc2.d -type l -print | ${CUTBINARY} -d '/' -f4 | ${SEDBINARY} "s/S[0-9][0-9]//g" | sort)
|
|
if [ ! "${FIND}" = "" ]; then
|
|
N=0
|
|
for SERVICE in ${FIND}; do
|
|
LogText "Found service (at boot, runlevel 2): ${SERVICE}"
|
|
N=$((N + 1))
|
|
done
|
|
Display --indent 2 --text "- Check services at startup (rc2.d)" --result "${STATUS_DONE}" --color WHITE
|
|
Display --indent 4 --text "Result: found $N services"
|
|
LogText "Result: found $N services"
|
|
fi
|
|
elif [ -z "${sRUNLEVEL}" ]; then
|
|
ReportSuggestion ${TEST_NO} "Determine runlevel and services at startup"
|
|
else
|
|
LogText "Result: skipping further actions"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5184
|
|
# Description : Check world writable startup scripts
|
|
Register --test-no BOOT-5184 --os Linux --weight L --network NO --category security --description "Check permissions for boot files/scripts"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FOUND=0
|
|
CHECKDIRS="${ROOTDIR}etc/init.d ${ROOTDIR}etc/rc.d ${ROOTDIR}etc/rcS.d"
|
|
|
|
LogText "Result: checking /etc/init.d scripts for writable bit"
|
|
for I in ${CHECKDIRS}; do
|
|
LogText "Test: checking if directory ${I} exists"
|
|
if [ -d ${I} ]; then
|
|
LogText "Result: directory ${I} found"
|
|
LogText "Test: checking for available files in directory"
|
|
FIND=$(${FINDBINARY} ${I} -type f -print)
|
|
if [ ! -z "${FIND}" ]; then
|
|
LogText "Result: found files in directory, checking permissions now"
|
|
for J in ${FIND}; do
|
|
LogText "Test: checking permissions of file ${J}"
|
|
if IsWorldWritable ${J}; then
|
|
FOUND=1
|
|
LogText "Result: warning, file ${J} is world writable"
|
|
else
|
|
LogText "Result: good, file ${J} not world writable"
|
|
fi
|
|
done
|
|
else
|
|
LogText "Result: found no files in directory."
|
|
fi
|
|
else
|
|
LogText "Result: directory ${I} not found. Skipping.."
|
|
fi
|
|
done
|
|
|
|
# /etc/rc[0-6].d
|
|
for NO in 0 1 2 3 4 5 6; do
|
|
LogText "Test: Checking /etc/rc${NO}.d scripts for writable bit"
|
|
if [ -d ${ROOTDIR}etc/rc${NO}.d ]; then
|
|
FIND=$(${FINDBINARY} ${ROOTDIR}etc/rc${NO}.d -type f -print)
|
|
for I in ${FIND}; do
|
|
if IsWorldWritable ${I}; then
|
|
FOUND=1
|
|
LogText "Result: warning, file ${I} is world writable"
|
|
else
|
|
LogText "Result: good, file ${I} not world writable"
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
|
|
# Other files
|
|
CHECKFILES="${ROOTDIR}etc/rc ${ROOTDIR}etc/rc.local ${ROOTDIR}etc/rc.d/rc.sysinit"
|
|
for I in ${CHECKFILES}; do
|
|
if [ -f ${I} ]; then
|
|
ShowSymlinkPath "${I}"
|
|
if [ ${FOUNDPATH} -eq 1 ]; then
|
|
CHECKFILE="${SYMLINK}"
|
|
LogText "Result: found the path behind this symlink (${CHECKFILE} --> ${I})"
|
|
else
|
|
CHECKFILE="${I}"
|
|
fi
|
|
LogText "Test: Checking ${CHECKFILE} file for writable bit"
|
|
if IsWorldWritable ${CHECKFILE}; then
|
|
FOUND=1
|
|
ReportWarning ${TEST_NO} "Found writable startup script ${CHECKFILE}"
|
|
LogText "Result: warning, file ${CHECKFILE} is world writable"
|
|
else
|
|
LogText "Result: good, file ${CHECKFILE} not world writable"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# Check results
|
|
if [ ${FOUND} -eq 1 ]; then
|
|
Display --indent 2 --text "- Check startup files (permissions)" --result "${STATUS_WARNING}" --color RED
|
|
ReportWarning ${TEST_NO} "Found world writable startup scripts" "-" "-"
|
|
LogText "Result: found one or more scripts which are possibly writable by other users"
|
|
AddHP 0 3
|
|
else
|
|
Display --indent 2 --text "- Check startup files (permissions)" --result "${STATUS_OK}" --color GREEN
|
|
AddHP 3 3
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5202
|
|
# Description : Check uptime of system
|
|
Register --test-no BOOT-5202 --weight L --network NO --category security --description "Check uptime of system"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
FOUND=0
|
|
FIND=""
|
|
UPTIME_IN_SECS=""
|
|
case "${OS}" in
|
|
Linux)
|
|
# Idle time, not real uptime
|
|
if [ -f /proc/uptime ]; then
|
|
UPTIME_IN_SECS=$(cat /proc/uptime | ${CUTBINARY} -d ' ' -f1 | ${CUTBINARY} -d '.' -f1)
|
|
else
|
|
Display --indent 2 --text "- Checking uptime" --result "${STATUS_SKIPPED}" --color YELLOW
|
|
ReportException "${TEST_NO}:1" "No uptime test available for this operating system (/proc/uptime missing)"
|
|
fi
|
|
;;
|
|
|
|
DragonFly | FreeBSD | macOS)
|
|
if [ ! -z "${SYSCTLBINARY}" ]; then
|
|
TIME_BOOT=$(${SYSCTLBINARY} kern.boottime | ${AWKBINARY} '{ print $5 }' | ${SEDBINARY} -e 's/,//' | ${GREPBINARY} "[0-9]")
|
|
TIME_NOW=$(date "+%s")
|
|
LogText "Boot time: ${TIME_BOOT}"
|
|
LogText "Current time: ${TIME_NOW}"
|
|
if [ ! -z "${TIME_BOOT}" -a ! -z "${TIME_NOW}" ]; then
|
|
UPTIME_IN_SECS=$((TIME_NOW - TIME_BOOT))
|
|
else
|
|
ReportException "${TEST_NO}:5" "Most likely kern.boottime empty, unable to determine uptime"
|
|
fi
|
|
else
|
|
Display --indent 2 --text "- Checking uptime" --result "${STATUS_SKIPPED}" --color YELLOW
|
|
ReportException "${TEST_NO}:4" "No uptime test available for this operating system (sysctl missing)"
|
|
fi
|
|
;;
|
|
|
|
NetBSD | OpenBSD)
|
|
if [ ! -z "${SYSCTLBINARY}" ]; then
|
|
TIME_BOOT=$(${SYSCTLBINARY} -n kern.boottime)
|
|
TIME_NOW=$(date "+%s")
|
|
LogText "Boot time: ${TIME_BOOT}"
|
|
LogText "Current time: ${TIME_NOW}"
|
|
if [ ! -z "${TIME_BOOT}" -a ! -z "${TIME_NOW}" ]; then
|
|
UPTIME_IN_SECS=$((TIME_NOW - TIME_BOOT))
|
|
else
|
|
ReportException "${TEST_NO}:5" "Most likely kern.boottime empty, unable to determine uptime"
|
|
fi
|
|
else
|
|
Display --indent 2 --text "- Checking uptime" --result "${STATUS_SKIPPED}" --color YELLOW
|
|
ReportException "${TEST_NO}:4" "No uptime test available for this operating system (sysctl missing)"
|
|
fi
|
|
;;
|
|
|
|
Solaris)
|
|
if [ ! -z "${KSTATBINARY}" ]; then
|
|
UPTIME_IN_SECS=$(${KSTATBINARY} -p unix:0:system_misc:snaptime | ${GREPBINARY} "^unix" | ${AWKBINARY} '{print $2}' | ${CUTBINARY} -d "." -f1)
|
|
else
|
|
Display --indent 2 --text "- Checking uptime" --result "${STATUS_SKIPPED}" --color YELLOW
|
|
ReportException "${TEST_NO}:2" "No uptime test available for this operating system (kstat missing)"
|
|
fi
|
|
;;
|
|
|
|
*)
|
|
Display --indent 2 --text "- Checking uptime" --result "${STATUS_SKIPPED}" --color YELLOW
|
|
|
|
# Want to help improving Lynis? Share your operating system and a way to determine the uptime (in seconds)
|
|
ReportException "${TEST_NO}:3" "No uptime test available yet for this operating system"
|
|
;;
|
|
esac
|
|
if [ ! -z "${UPTIME_IN_SECS}" ]; then
|
|
UPTIME_IN_DAYS=$((UPTIME_IN_SECS / 60 / 60 / 24))
|
|
LogText "Uptime (in seconds): ${UPTIME_IN_SECS}"
|
|
LogText "Uptime (in days): ${UPTIME_IN_DAYS}"
|
|
Report "uptime_in_seconds=${UPTIME_IN_SECS}"
|
|
Report "uptime_in_days=${UPTIME_IN_DAYS}"
|
|
else
|
|
LogText "Result: no uptime information available"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
# Test : BOOT-5260
|
|
# Description : Check single user mode for systemd
|
|
Register --test-no BOOT-5260 --weight L --network NO --category security --description "Check single user mode for systemd"
|
|
if [ ${SKIPTEST} -eq 0 ]; then
|
|
LogText "Test: Searching /usr/lib/systemd/system/rescue.service"
|
|
if [ -f ${ROOTDIR}usr/lib/systemd/system/rescue.service ]; then
|
|
LogText "Result: file /usr/lib/systemd/system/rescue.service"
|
|
LogText "Test: checking presence sulogin for single user mode"
|
|
FIND=$(${EGREPBINARY} "^ExecStart=-(/bin/sh -c \")?(/usr)?/(s)?bin/sulogin" ${ROOTDIR}usr/lib/systemd/system/rescue.service)
|
|
if [ ! -z "${FIND}" ]; then
|
|
FOUND=1
|
|
LogText "Result: found sulogin, so single user is protected"
|
|
AddHP 3 3
|
|
else
|
|
LogText "Result: did not find sulogin in rescue.service"
|
|
AddHP 1 3
|
|
Display --indent 2 --text "- Checking sulogin in rescue.service" --result "${STATUS_NOT_FOUND}" --color YELLOW
|
|
ReportSuggestion "${TEST_NO}" "Protect rescue.service by using sulogin"
|
|
fi
|
|
else
|
|
LogText "Result: file ${ROOTDIR}usr/lib/systemd/system/rescue.service does not exist"
|
|
fi
|
|
fi
|
|
#
|
|
#################################################################################
|
|
#
|
|
|
|
Report "boot_loader=${BOOT_LOADER}"
|
|
Report "boot_uefi_booted=${UEFI_BOOTED}"
|
|
Report "boot_uefi_booted_secure=${UEFI_BOOTED_SECURE}"
|
|
Report "service_manager=${SERVICE_MANAGER}"
|
|
|
|
WaitForKeyPress
|
|
|
|
#
|
|
#================================================================================
|
|
# Lynis - Security Auditing and System Hardening for Linux and UNIX - https://cisofy.com
|