#!/bin/sh ################################################################################# # # Lynis # ------------------ # # Copyright 2007-2013, Michael Boelen # Copyright 2007-2021, 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 "${SECTION_BOOT_AND_SERVICES}" # ################################################################################# # BOOT_LOADER="unknown" BOOT_LOADER_FOUND=0 BOOT_LOADER_SEARCHED=0 GRUB_VERSION=0 if [ -z "${SERVICE_MANAGER}" ]; then SERVICE_MANAGER="unknown" fi # ################################################################################# # # 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 [ -n "${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" fi fi fi # ################################################################################# # # Test : BOOT-5104 # Description : Determine service manager # Notes : # initscripts - Used by Arch before # runit - Used by Artix, Devuan, Dragora and Void # 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 OUTPUT=$(${AWKBINARY} '/(^\/|init|runit)/ { print $1 }' /proc/1/cmdline | ${TRBINARY} '\0' ' ' | ${SEDBINARY} 's/ $//') LogText "Result: cmdline found = ${OUTPUT}" FILENAME=$(echo "${OUTPUT}" | ${AWKBINARY} '{print $1}') LogText "Result: file on disk = ${FILENAME}" ISFILE=$(echo ${FILENAME} | ${GREPBINARY} "^/") if [ -n "${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 [ -n "${FILENAME}" ]; then SHORTNAME=$(echo ${FILENAME} | ${AWKBINARY} -F/ '{ print $NF }') LogText "Found: ${SHORTNAME}" if [ "${SERVICE_MANAGER}" = "unknown" ]; then case ${SHORTNAME} in busybox) SERVICE_MANAGER="busybox" ;; "init" | "initsplash") if [ -d ${ROOTDIR}etc/rc.d ]; then SERVICE_MANAGER="bsdrc.d" else SERVICE_MANAGER="SysV Init" fi ;; systemd) SERVICE_MANAGER="systemd" ;; upstart) SERVICE_MANAGER="upstart" ;; runit) SERVICE_MANAGER="runit" ;; openrc-init) SERVICE_MANAGER="openrc" ;; *) CONTAINS_SYSTEMD=$(echo ${SHORTNAME} | ${GREPBINARY} "systemd") if [ -n "${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 fi 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" | "OpenBSD") if [ -x /sbin/init -a -d ${ROOTDIR}etc/rc.d -a -f ${ROOTDIR}etc/rc ]; then SERVICE_MANAGER="bsdrc" fi ;; "macOS") if [ -x ${ROOTDIR}sbin/launchd ]; then SERVICE_MANAGER="launchd" fi ;; "Solaris") if [ -n "${ROOTDIR}usr/bin/svcs" ]; then SERVICE_MANAGER="SMF (svcs)" elif [ -d "${ROOTDIR}etc/init.d" ]; then SERVICE_MANAGER="SysV Init" 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 BOOT_LOADER_SEARCHED=1 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 BOOT_LOADER_SEARCHED=1 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-5109 # Description : Check for rEFInd Register --test-no BOOT-5109 --os "Linux" --weight L --network NO --root-only YES --category security --description "Check rEFInd as bootloader" if [ ${SKIPTEST} -eq 0 ]; then BOOT_LOADER_SEARCHED=1 FileExists ${ROOTDIR}boot/refind_linux.conf if [ ${FILE_FOUND} -eq 1 ]; then LogText "Result: found rEFInd" BOOT_LOADER="rEFInd" 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 [ -n "${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-5117 # Description : Check for systemd-boot boot loader if [ ! "${BOOTCTLBINARY}" = "" -a ${HAS_SYSTEMD} -eq 1 -a ${UEFI_BOOTED} -eq 1 ]; then PREQS_MET="YES"; else PREQS_MET="NO"; fi Register --test-no BOOT-5117 --preqs-met ${PREQS_MET} --os "Linux" --weight L --network NO --category security --description "Check for systemd-boot bootloader presence" if [ ${SKIPTEST} -eq 0 ]; then BOOT_LOADER_SEARCHED=1 CURRENT_BOOT_LOADER=$(${BOOTCTLBINARY} status --no-pager 2>/dev/null | ${AWKBINARY} '/Current Boot Loader/{ getline; print $2 }') if [ "${CURRENT_BOOT_LOADER}" = "systemd-boot" ]; then Display --indent 2 --text "- Checking systemd-boot presence" --result "${STATUS_FOUND}" --color GREEN LogText "Result: found systemd-boot" BOOT_LOADER="systemd-boot" BOOT_LOADER_FOUND=1 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 -n "${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 [ -n "${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 if [ -d "${ROOTDIR}etc/grub.d" ]; then CONF_FILES=$(${FINDBINARY} -L "${ROOTDIR}etc/grub.d" -type f -name "[0-9][0-9]*" -print0 | ${TRBINARY} '\0' ' ' | ${TRBINARY} -d '[:cntrl:]') CONF_FILES="${GRUBCONFFILE} ${ROOTDIR}boot/grub/custom.cfg ${CONF_FILES}" else CONF_FILES="${GRUBCONFFILE} ${ROOTDIR}boot/grub/custom.cfg" fi for FILE in ${CONF_FILES}; do if [ -f "${FILE}" ]; then LogText "Found file ${FILE}, proceeding with tests." if FileIsReadable "${FILE}"; then FIND=$(${GREPBINARY} 'password --md5' ${FILE} | ${GREPBINARY} -v '^#') FIND2=$(${GREPBINARY} 'password --encrypted' ${FILE} | ${GREPBINARY} -v '^#') FIND3=$(${GREPBINARY} 'set superusers' ${FILE} | ${GREPBINARY} -v '^#') FIND4=$(${GREPBINARY} 'password_pbkdf2' ${FILE} | ${GREPBINARY} -v '^#') FIND5=$(${GREPBINARY} 'grub.pbkdf2' ${FILE} | ${GREPBINARY} -v '^#') # GRUB1: Password should be set (MD5 or SHA1) if [ -n "${FIND}" -o -n "${FIND2}" ]; then FOUND=1 # GRUB2: Superusers AND password should be defined elif [ -n "${FIND3}" ]; then if [ -n "${FIND4}" -o -n "${FIND5}" ]; then FOUND=1; fi else LogText "Result: did not find hashed password line in this file" fi else LogText "Result: Can not read '${FILE}' (no permission?)" fi else LogText "Result: File '${FILE}' does not exist" fi done 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_NONE}" --color RED LogText "Result: Didn't find hashed password line in GRUB configuration" ReportSuggestion "${TEST_NO}" "Set a password on GRUB boot loader to prevent altering boot configuration (e.g. boot in single user mode without password)" AddHP 0 2 fi unset CONF_FILES FILE FIND FIND2 FIND3 FIND4 FIND5 FOUND 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=$(${GREPBINARY} -E '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=': 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=': 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-5140 # Description : Check for ELILO boot loader Register --test-no BOOT-5140 --os "Linux" --weight L --network NO --root-only YES --category security --description "Check for ELILO boot loader presence" if [ ${SKIPTEST} -eq 0 ]; then BOOT_LOADER_SEARCHED=1 CONF_FILES="${ROOTDIR}etc/elilo.conf ${ROOTDIR}boot/efi/EFI/${LINUX_VERSION}/elilo.conf" for FILE in ${CONF_FILES}; do FileExists ${FILE} if [ ${FILE_FOUND} -eq 1 ]; then Display --indent 2 --text "- Checking boot loader ELILO" --result "${STATUS_FOUND}" --color GREEN LogText "Result: found ELILO boot loader" BOOT_LOADER="ELILO" BOOT_LOADER_FOUND=1 fi done 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 ${ROOTDIR}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 HasData "${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=$(${GREPBINARY} -E -v -i '^#|none' ${ROOTDIR}etc/rc.conf | ${GREPBINARY} -E -i '_enable.*(yes|on|1)' | ${SORTBINARY} | ${AWKBINARY} -F= '{ print $1 }' | ${SEDBINARY} 's/_enable//') fi COUNT=0 for ITEM in ${FIND}; do LogText "Found service (service/rc.conf): ${ITEM}" Report "boottask[]=${ITEM}" COUNT=$((COUNT + 1)) done Display --indent 2 --text "- Checking services at startup (service/rc.conf)" --result "${STATUS_DONE}" --color GREEN Display --indent 6 --text "Result: found ${COUNT} services/options set" LogText "Found ${COUNT} services/options to run at startup" fi # ################################################################################# # # Test : BOOT-5170 # Description : Check for Solaris boot daemons Register --test-no BOOT-5170 --os Solaris --weight L --network NO --category security --description "Check for Solaris boot daemons" if [ ${SKIPTEST} -eq 0 ]; then if [ -n "${SVCSBINARY}" ]; then LogText "Result: Using svcs binary to check for daemons" LogText "SysV style services may be incorrectly counted as running." Report "running_service_tool=svcs" # For the documentation of the states (field $1) see # "Managing System Services in Oracle Solaris 11.4" pp. 24, available # at https://docs.oracle.com/cd/E37838_01/pdf/E60998.pdf FIND=$("${SVCSBINARY}" -Ha | ${AWKBINARY} '{ if ($1 == "online" || $1 == "legacy_run") print $3 }') COUNT=0 for ITEM in ${FIND}; do LogText "Found running daemon: ${ITEM}" Report "running_service[]=${ITEM}" COUNT=$((COUNT + 1 )) done Display --indent 2 --text "- Check running daemons (svcs)" --result "${STATUS_DONE}" --color GREEN Display --indent 8 --text "Result: found ${COUNT} running daemons" LogText "Result: Found ${COUNT} running daemons" LogText "Searching for enabled daemons (svcs)" Report "boot_service_tool=svcs" FIND=$("${SVCSBINARY}" -Ha | ${AWKBINARY} '{ if ($1 != "disabled" && $1 != "uninitialized") print $3 }') COUNT=0 for ITEM in ${FIND}; do LogText "Found enabled daemon at boot: ${ITEM}" Report "boot_service[]=${ITEM}" COUNT=$((COUNT + 1 )) done LogText "Note: Run svcs -a see all services" Display --indent 2 --text "- Check enabled daemons at boot (svcs)" --result "${STATUS_DONE}" --color GREEN Display --indent 8 --text "Result: found ${COUNT} enabled daemons at boot" LogText "Result: Found ${COUNT} enabled daemons at boot" fi fi # ################################################################################# # # Test : BOOT-5171 # Description : Check for services with errors on solaris # ################################################################################# # # 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 HasData "${SYSTEMCTLBINARY}"; then LogText "Result: systemctl binary found, trying that to discover information" # Running services LogText "Searching for running services (systemctl services only)" FIND=$(${SYSTEMCTLBINARY} --no-legend --full --type=service --state=running | ${AWKBINARY} -F.service '{ print $1 }') COUNT=0 Report "running_service_tool=systemctl" for ITEM in ${FIND}; do LogText "Found running service: ${ITEM}" Report "running_service[]=${ITEM}" COUNT=$((COUNT + 1)) done LogText "Hint: 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 ${COUNT} running services" LogText "Result: Found ${COUNT} running services" # Services at boot LogText "Searching for enabled services (systemctl services only)" FIND=$(${SYSTEMCTLBINARY} list-unit-files --no-legend --type=service --state=enabled | ${SORTBINARY} -u | ${AWKBINARY} -F.service '{ print $1 }') COUNT=0 Report "boot_service_tool=systemctl" for ITEM in ${FIND}; do LogText "Found enabled service at boot: ${ITEM}" Report "boot_service[]=${ITEM}" COUNT=$((COUNT + 1)) done LogText "Hint: 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 ${COUNT} enabled services" LogText "Result: Found ${COUNT} enabled services" else LogText "Result: systemctl binary not found, checking chkconfig binary" if [ -n "${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 | ${GREPBINARY} -E '3:on|5:on' | ${AWKBINARY} '{ print $1 }') COUNT=0 Report "boot_service_tool=chkconfig" for ITEM in ${FIND}; do LogText "Found service (at boot, runlevel 3 or 5): ${ITEM}" Report "boot_service[]=${ITEM}" COUNT=$((COUNT + 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 ${COUNT} services" LogText "Result: Found ${COUNT} 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" ] || [ "${LINUX_VERSION}" = "Ubuntu" ] || [ "${LINUX_VERSION_LIKE}" = "Debian" ] || [ "${LINUX_VERSION_LIKE}" = "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 [ -n "${FIND}" ]; then COUNT=0 for SERVICE in ${FIND}; do LogText "Found service (at boot, runlevel 2): ${SERVICE}" COUNT=$((COUNT + 1)) done Display --indent 2 --text "- Check services at startup (rc2.d)" --result "${STATUS_DONE}" --color WHITE Display --indent 4 --text "Result: found ${COUNT} services" LogText "Result: found ${COUNT} 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 Solaris" --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 ${ROOTDIR}etc/init.d scripts for writable bit" for DIR in ${CHECKDIRS}; do LogText "Test: checking if directory ${DIR} exists" if [ -d ${DIR} ]; then LogText "Result: directory ${DIR} found" LogText "Test: checking for available files in directory" FIND=$(${FINDBINARY} -L ${DIR} -type f -print | ${SORTBINARY}) if [ -n "${FIND}" ]; then LogText "Result: found files in directory, checking permissions now" for FILE in ${FIND}; do LogText "Test: checking permissions of file ${FILE}" if IsWorldWritable ${FILE}; then FOUND=1 LogText "Result: warning, file ${FILE} is world writable" else LogText "Result: good, file ${FILE} not world writable" fi done else LogText "Result: found no files in directory." fi else LogText "Result: directory ${DIR} not found. Skipping.." fi done # /etc/rc[0-6].d for NO in 0 1 2 3 4 5 6; do LogText "Test: Checking ${ROOTDIR}etc/rc${NO}.d scripts for writable bit" if [ -d ${ROOTDIR}etc/rc${NO}.d ]; then FIND=$(${FINDBINARY} -L ${ROOTDIR}etc/rc${NO}.d -type f -print | ${SORTBINARY}) 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=$(${CUTBINARY} -d ' ' -f1 /proc/uptime | ${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 [ -n "${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 [ -n "${TIME_BOOT}" -a -n "${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 [ -n "${SYSCTLBINARY}" ]; then TIME_BOOT=$(${SYSCTLBINARY} -n kern.boottime) TIME_NOW=$(date "+%s") LogText "Boot time: ${TIME_BOOT}" LogText "Current time: ${TIME_NOW}" if [ -n "${TIME_BOOT}" -a -n "${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 [ -n "${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 [ -n "${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 --os Linux --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=$(${GREPBINARY} -E "^ExecStart=.*sulogin" ${ROOTDIR}usr/lib/systemd/system/rescue.service) if [ -n "${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 # ################################################################################# # # Test : BOOT-5262 # Description : Check for OpenBSD boot daemons Register --test-no BOOT-5262 --os OpenBSD --weight L --network NO --category security --description "Check for OpenBSD boot daemons" if [ ${SKIPTEST} -eq 0 ]; then if HasData "${RCCTLBINARY}"; then LogText "Result: rcctl binary found, trying that to discover information" # OpenBSD (Ask rcctl(8) for running daemons) LogText "Searching for running daemons (rcctl)" FIND=$(${RCCTLBINARY} ls started) COUNT=0 Report "running_service_tool=rcctl" for ITEM in ${FIND}; do LogText "Found running daemon: ${ITEM}" Report "running_service[]=${ITEM}" COUNT=$((COUNT + 1 )) done LogText "Note: Run rcctl ls all | grep -E '^(pf|check_quotas|library_aslr)$' to see all daemons" Display --indent 2 --text "- Check running daemons (rcctl)" --result "${STATUS_DONE}" --color GREEN Display --indent 8 --text "Result: found ${COUNT} running daemons" LogText "Result: Found ${COUNT} running daemons" # OpenBSD (Ask rcctl(8) for enabled daemons) LogText "Searching for enabled daemons (rcctl)" FIND=$(${RCCTLBINARY} ls on | ${GREPBINARY} -E -v '^(pf|check_quotas|library_aslr)$') COUNT=0 Report "boot_service_tool=rcctl" for ITEM in ${FIND}; do LogText "Found enabled daemon at boot: ${ITEM}" Report "boot_service[]=${ITEM}" COUNT=$((COUNT + 1 )) done LogText "Note: Run rcctl ls all | grep -E '^(pf|check_quotas|library_aslr)$' to see all daemons" Display --indent 2 --text "- Check enabled daemons at boot (rcctl)" --result "${STATUS_DONE}" --color GREEN Display --indent 8 --text "Result: found ${COUNT} enabled daemons at boot" LogText "Result: Found ${COUNT} enabled daemons at boot" fi fi # ################################################################################# # # Test : BOOT-5263 # Description : Check OpenBSD world writable startup scripts Register --test-no BOOT-5263 --os OpenBSD --weight L --network NO --category security --description "Check permissions for boot files/scripts" if [ ${SKIPTEST} -eq 0 ]; then FOUND=0 CHECKDIR="${ROOTDIR}etc/rc.d" LogText "Result: checking ${ROOTDIR}etc/rc.d scripts for writable bit" LogText "Test: checking if directory ${DIR} exists" if [ -d ${CHECKDIR} ]; then LogText "Result: directory ${DIR} found" LogText "Test: checking for available files in directory" # OpenBSD uses symlinks to create another instance of daemons FIND=$(${FINDBINARY} -L ${CHECKDIR} -type f -print | ${SORTBINARY}) if [ -n "${FIND}" ]; then LogText "Result: found files in directory, checking permissions now" for FILE in ${FIND}; do LogText "Test: checking permissions of file ${FILE}" ShowSymlinkPath "${FILE}" if [ ${FOUNDPATH} -eq 1 ]; then CHECKFILE="${SYMLINK}" LogText "Result: found the path behind this symlink (${CHECKFILE} --> ${FILE})" else CHECKFILE="${FILE}" fi if IsWorldWritable ${CHECKFILE}; then FOUND=1 LogText "Result: warning, file ${CHECKFILE} is world writable" else LogText "Result: good, file ${CHECKFILE} not world writable" fi done else LogText "Result: found no files in directory." fi else LogText "Result: directory ${CHECKDIR} not found. Skipping.." fi # Other files CHECKFILES="${ROOTDIR}etc/rc ${ROOT}etc/rc.conf ${ROOT}etc/rc.conf.local ${ROOTDIR}etc/rc.local" 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-5264 # Description : Run systemd-analyze security if [ -z "${SYSTEMDANALYZEBINARY}" ]; then SKIPREASON="systemd-analyze not available"; PREQS_MET="NO"; else SYSTEMD_VERSION=$("${SYSTEMDANALYZEBINARY}" --version | ${AWKBINARY} '/^systemd / {print $2}') if [ "${SYSTEMD_VERSION}" -ge 240 ]; then PREQS_MET="YES"; else SKIPREASON="systemd-analyze too old (v${SYSTEMD_VERSION}), need at least v240"; PREQS_MET="NO"; fi fi Register --test-no BOOT-5264 --preqs-met ${PREQS_MET} --skip-reason "${SKIPREASON}" --os Linux --weight L --network NO --category security --description "Run systemd-analyze security" if [ ${SKIPTEST} -eq 0 ]; then LogText "Test: Run systemd-analyze security" Display --indent 2 --text "- Running 'systemd-analyze security'" ${SYSTEMDANALYZEBINARY} security | while read UNIT EXPOSURE PREDICATE HAPPY; do if [ "${UNIT}" = "UNIT" ]; then continue fi STATUS="UNKNOWN" COLOR="BLACK" case ${PREDICATE} in PERFECT | SAFE | OK) STATUS="${STATUS_PROTECTED}" COLOR=GREEN ;; MEDIUM) STATUS="${STATUS_MEDIUM}" COLOR=WHITE ;; EXPOSED) STATUS="${STATUS_EXPOSED}" COLOR=YELLOW ;; UNSAFE | DANGEROUS) STATUS="${STATUS_UNSAFE}" COLOR=RED ;; esac Display --indent 8 --text "- ${UNIT}:" --result "${STATUS}" --color "${COLOR}" LogText "Result: ${UNIT}: ${EXPOSURE} ${STATUS}" done ReportSuggestion "${TEST_NO}" "Consider hardening system services" "Run '${SYSTEMDANALYZEBINARY} security SERVICE' for each service" 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