From 0b6ea0d97e2d182b64a72d854fee0d05b132f188 Mon Sep 17 00:00:00 2001 From: jeremydenoun Date: Thu, 4 Feb 2021 16:21:49 +0100 Subject: [PATCH] IMP: add multiple Improvements * add new kernel module detection (enable & listing) with detection of monolithic kernel * change way to detect if file system type is disabled * add global IS_CONTAINER variable * disable test for 3.4.x to be consistent with others * add cli options to override configuration loglevel --- MANUAL.md | 4 + README.md | 3 + bin/hardening.sh | 14 ++- bin/hardening/1.1.1.1_disable_freevxfs.sh | 28 +++-- bin/hardening/1.1.1.2_disable_jffs2.sh | 28 +++-- bin/hardening/1.1.1.3_disable_hfs.sh | 30 ++++-- bin/hardening/1.1.1.4_disable_hfsplus.sh | 30 ++++-- bin/hardening/1.1.1.5_disable_squashfs.sh | 32 +++--- bin/hardening/1.1.1.6_disable_udf.sh | 30 ++++-- bin/hardening/1.1.1.7_restrict_fat.sh | 1 + bin/hardening/1.1.23_disable_usb_storage.sh | 28 +++-- bin/hardening/3.4.1_disable_dccp.sh | 26 +++-- bin/hardening/3.4.2_disable_sctp.sh | 26 +++-- bin/hardening/3.4.3_disable_rds.sh | 26 +++-- bin/hardening/3.4.4_disable_tipc.sh | 26 +++-- debian/cis-hardening.8 | 5 + lib/common.sh | 27 ++++- lib/utils.sh | 107 +++++++++++++------- tests/hardening/3.4.1_disable_dccp.sh | 14 ++- tests/hardening/3.4.2_disable_sctp.sh | 14 ++- tests/hardening/3.4.3_disable_rds.sh | 14 ++- tests/hardening/3.4.4_disable_tipc.sh | 14 ++- 22 files changed, 362 insertions(+), 165 deletions(-) diff --git a/MANUAL.md b/MANUAL.md index 14855f4..15748c7 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -115,6 +115,10 @@ will create a timestamped backup in this directory. the -n option instructs sudo not to prompt for a password. Finally note that `--sudo` mode only works for audit mode. +`--set-log-level=level` +: This option sets LOGLEVEL, you can choose : info, warning, error, ok, debug. + Default value is : info + `--batch` : While performing system audit, this option sets LOGLEVEL to 'ok' and captures all output to print only one line once the check is done, formatted like : diff --git a/README.md b/README.md index 5fa89a7..c3ca2b9 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,9 @@ to allow a certain kind of services on the machine, such as http, mail, etc. Can be specified multiple times to allow multiple services. Use --allow-service-list to get a list of supported services. +``--set-log-level ``: This option sets LOGLEVEL, you can choose : info, warning, error, ok, debug. +Default value is : info + ``--create-config-files-only``: create the config files in etc/conf.d. Must be run as root, before running the audit with user secaudit, to have the rights setup well on the conf files. diff --git a/bin/hardening.sh b/bin/hardening.sh index 7d64884..283e257 100755 --- a/bin/hardening.sh +++ b/bin/hardening.sh @@ -26,6 +26,7 @@ ALLOW_SERVICE_LIST=0 SET_HARDENING_LEVEL=0 SUDO_MODE='' BATCH_MODE='' +ASK_LOGLEVEL='' usage() { cat < + This option sets LOGLEVEL, you can choose : info, warning, error, ok, debug. + Default value is : info + --batch While performing system audit, this option sets LOGLEVEL to 'ok' and captures all output to print only one line once the check is done, formatted like : @@ -143,6 +148,10 @@ while [[ $# -gt 0 ]]; do SET_HARDENING_LEVEL="$2" shift ;; + --set-log-level) + ASK_LOGLEVEL=$2 + shift + ;; --only) TEST_LIST[${#TEST_LIST[@]}]="$2" shift @@ -152,7 +161,7 @@ while [[ $# -gt 0 ]]; do ;; --batch) BATCH_MODE='--batch' - LOGLEVEL=ok + ASK_LOGLEVEL=ok ;; -h | --help) usage @@ -183,13 +192,12 @@ fi [ -r "$CIS_ROOT_DIR"/lib/constants.sh ] && . "$CIS_ROOT_DIR"/lib/constants.sh # shellcheck source=../etc/hardening.cfg [ -r "$CIS_ROOT_DIR"/etc/hardening.cfg ] && . "$CIS_ROOT_DIR"/etc/hardening.cfg +if [ "$ASK_LOGLEVEL" ]; then LOGLEVEL=$ASK_LOGLEVEL; fi # shellcheck source=../lib/common.sh [ -r "$CIS_ROOT_DIR"/lib/common.sh ] && . "$CIS_ROOT_DIR"/lib/common.sh # shellcheck source=../lib/utils.sh [ -r "$CIS_ROOT_DIR"/lib/utils.sh ] && . "$CIS_ROOT_DIR"/lib/utils.sh -if [ "$BATCH_MODE" ]; then MACHINE_LOG_LEVEL=3; fi - # If --allow-service-list is specified, don't run anything, just list the supported services if [ "$ALLOW_SERVICE_LIST" = 1 ]; then declare -a HARDENING_EXCEPTIONS_LIST diff --git a/bin/hardening/1.1.1.1_disable_freevxfs.sh b/bin/hardening/1.1.1.1_disable_freevxfs.sh index 0a0497d..36c8712 100755 --- a/bin/hardening/1.1.1.1_disable_freevxfs.sh +++ b/bin/hardening/1.1.1.1_disable_freevxfs.sh @@ -17,28 +17,36 @@ HARDENING_LEVEL=2 # shellcheck disable=2034 DESCRIPTION="Disable mounting of freevxfs filesystems." -# Note: we check /proc/config.gz to be compliant with both monolithic and modular kernels - KERNEL_OPTION="CONFIG_VXFS_FS" MODULE_NAME="freevxfs" # This function will be called if the script status is on enabled / audit mode audit() { - is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - crit "$KERNEL_OPTION is enabled!" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing or disable this check!" else - ok "$KERNEL_OPTION is disabled" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + crit "$MODULE_NAME is enabled!" + else + ok "$MODULE_NAME is disabled" + fi fi } # This function will be called if the script status is on enabled mode apply() { - is_kernel_option_enabled "$KERNEL_OPTION" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - warn "I cannot fix $KERNEL_OPTION enabled, recompile your kernel please" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing!" else - ok "$KERNEL_OPTION is disabled, nothing to do" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + warn "I cannot fix $MODULE_NAME, recompile your kernel or blacklist module $MODULE_NAME (/etc/modprobe.d/blacklist.conf : +install $MODULE_NAME /bin/true)" + else + ok "$MODULE_NAME is disabled" + fi fi } diff --git a/bin/hardening/1.1.1.2_disable_jffs2.sh b/bin/hardening/1.1.1.2_disable_jffs2.sh index 8aaea98..713fba7 100755 --- a/bin/hardening/1.1.1.2_disable_jffs2.sh +++ b/bin/hardening/1.1.1.2_disable_jffs2.sh @@ -17,28 +17,36 @@ HARDENING_LEVEL=2 # shellcheck disable=2034 DESCRIPTION="Disable mounting of jffs2 filesystems." -# Note: we check /proc/config.gz to be compliant with both monolithic and modular kernels - KERNEL_OPTION="CONFIG_JFFS2_FS" MODULE_NAME="jffs2" # This function will be called if the script status is on enabled / audit mode audit() { - is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - crit "$KERNEL_OPTION is enabled!" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing or disable this check!" else - ok "$KERNEL_OPTION is disabled" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + crit "$MODULE_NAME is enabled!" + else + ok "$MODULE_NAME is disabled" + fi fi } # This function will be called if the script status is on enabled mode apply() { - is_kernel_option_enabled "$KERNEL_OPTION" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - warn "I cannot fix $KERNEL_OPTION enabled, recompile your kernel please" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing!" else - ok "$KERNEL_OPTION is disabled, nothing to do" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + warn "I cannot fix $MODULE_NAME, recompile your kernel or blacklist module $MODULE_NAME (/etc/modprobe.d/blacklist.conf : +install $MODULE_NAME /bin/true)" + else + ok "$MODULE_NAME is disabled" + fi fi } diff --git a/bin/hardening/1.1.1.3_disable_hfs.sh b/bin/hardening/1.1.1.3_disable_hfs.sh index 181e7b0..30f7b80 100755 --- a/bin/hardening/1.1.1.3_disable_hfs.sh +++ b/bin/hardening/1.1.1.3_disable_hfs.sh @@ -17,28 +17,36 @@ HARDENING_LEVEL=2 # shellcheck disable=2034 DESCRIPTION="Disable mounting of hfs filesystems." -# Note: we check /proc/config.gz to be compliant with both monolithic and modular kernels - KERNEL_OPTION="CONFIG_HFS_FS" -MODULE_FILE="hfs" +MODULE_NAME="hfs" # This function will be called if the script status is on enabled / audit mode audit() { - is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_FILE" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - crit "$KERNEL_OPTION is enabled!" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing or disable this check!" else - ok "$KERNEL_OPTION is disabled" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + crit "$MODULE_NAME is enabled!" + else + ok "$MODULE_NAME is disabled" + fi fi } # This function will be called if the script status is on enabled mode apply() { - is_kernel_option_enabled "$KERNEL_OPTION" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - warn "I cannot fix $KERNEL_OPTION enabled, recompile your kernel please" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing!" else - ok "$KERNEL_OPTION is disabled, nothing to do" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + warn "I cannot fix $MODULE_NAME, recompile your kernel or blacklist module $MODULE_NAME (/etc/modprobe.d/blacklist.conf : +install $MODULE_NAME /bin/true)" + else + ok "$MODULE_NAME is disabled" + fi fi } diff --git a/bin/hardening/1.1.1.4_disable_hfsplus.sh b/bin/hardening/1.1.1.4_disable_hfsplus.sh index 3af05a7..3184e5b 100755 --- a/bin/hardening/1.1.1.4_disable_hfsplus.sh +++ b/bin/hardening/1.1.1.4_disable_hfsplus.sh @@ -17,28 +17,36 @@ HARDENING_LEVEL=2 # shellcheck disable=2034 DESCRIPTION="Disable mounting of hfsplus filesystems." -# Note: we check /proc/config.gz to be compliant with both monolithic and modular kernels - KERNEL_OPTION="CONFIG_HFSPLUS_FS" -MODULE_FILE="hfsplus" +MODULE_NAME="hfsplus" # This function will be called if the script status is on enabled / audit mode audit() { - is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_FILE" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - crit "$KERNEL_OPTION is enabled!" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing or disable this check!" else - ok "$KERNEL_OPTION is disabled" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + crit "$MODULE_NAME is enabled!" + else + ok "$MODULE_NAME is disabled" + fi fi } # This function will be called if the script status is on enabled mode apply() { - is_kernel_option_enabled "$KERNEL_OPTION" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - warn "I cannot fix $KERNEL_OPTION enabled, recompile your kernel please" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing!" else - ok "$KERNEL_OPTION is disabled, nothing to do" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + warn "I cannot fix $MODULE_NAME, recompile your kernel or blacklist module $MODULE_NAME (/etc/modprobe.d/blacklist.conf : +install $MODULE_NAME /bin/true)" + else + ok "$MODULE_NAME is disabled" + fi fi } diff --git a/bin/hardening/1.1.1.5_disable_squashfs.sh b/bin/hardening/1.1.1.5_disable_squashfs.sh index 7d67c03..8c6766e 100755 --- a/bin/hardening/1.1.1.5_disable_squashfs.sh +++ b/bin/hardening/1.1.1.5_disable_squashfs.sh @@ -17,31 +17,37 @@ HARDENING_LEVEL=2 # shellcheck disable=2034 DESCRIPTION="Disable mounting of squashfs filesytems." -# Note: we check /proc/config.gz to be compliant with both monolithic and modular kernels - KERNEL_OPTION="CONFIG_SQUASHFS" -MODULE_FILE="squashfs" +MODULE_NAME="squashfs" # This function will be called if the script status is on enabled / audit mode audit() { - is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_FILE" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - crit "$KERNEL_OPTION is enabled!" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing or disable this check!" else - ok "$KERNEL_OPTION is disabled" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + crit "$MODULE_NAME is enabled!" + else + ok "$MODULE_NAME is disabled" + fi fi - : } # This function will be called if the script status is on enabled mode apply() { - is_kernel_option_enabled "$KERNEL_OPTION" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - warn "I cannot fix $KERNEL_OPTION enabled, recompile your kernel please" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing!" else - ok "$KERNEL_OPTION is disabled, nothing to do" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + warn "I cannot fix $MODULE_NAME, recompile your kernel or blacklist module $MODULE_NAME (/etc/modprobe.d/blacklist.conf : +install $MODULE_NAME /bin/true)" + else + ok "$MODULE_NAME is disabled" + fi fi - : } # This function will check config parameters required diff --git a/bin/hardening/1.1.1.6_disable_udf.sh b/bin/hardening/1.1.1.6_disable_udf.sh index ae54166..e62d134 100755 --- a/bin/hardening/1.1.1.6_disable_udf.sh +++ b/bin/hardening/1.1.1.6_disable_udf.sh @@ -17,28 +17,36 @@ HARDENING_LEVEL=2 # shellcheck disable=2034 DESCRIPTION="Disable mounting of udf filesystems." -# Note: we check /proc/config.gz to be compliant with both monolithic and modular kernels - KERNEL_OPTION="CONFIG_UDF_FS" -MODULE_FILE="udf" +MODULE_NAME="udf" # This function will be called if the script status is on enabled / audit mode audit() { - is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_FILE" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - crit "$KERNEL_OPTION is enabled!" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing or disable this check!" else - ok "$KERNEL_OPTION is disabled" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + crit "$MODULE_NAME is enabled!" + else + ok "$MODULE_NAME is disabled" + fi fi } # This function will be called if the script status is on enabled mode apply() { - is_kernel_option_enabled "$KERNEL_OPTION" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - warn "I cannot fix $KERNEL_OPTION enabled, recompile your kernel please" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing!" else - ok "$KERNEL_OPTION is disabled, nothing to do" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + warn "I cannot fix $MODULE_NAME, recompile your kernel or blacklist module $MODULE_NAME (/etc/modprobe.d/blacklist.conf : +install $MODULE_NAME /bin/true)" + else + ok "$MODULE_NAME is disabled" + fi fi } diff --git a/bin/hardening/1.1.1.7_restrict_fat.sh b/bin/hardening/1.1.1.7_restrict_fat.sh index 633fabb..be8954b 100755 --- a/bin/hardening/1.1.1.7_restrict_fat.sh +++ b/bin/hardening/1.1.1.7_restrict_fat.sh @@ -24,6 +24,7 @@ MODULE_FILE="vfat" # This function will be called if the script status is on enabled / audit mode audit() { + # TODO check if uefi enabled if yes check if only boot partition use FAT is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_FILE" if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated crit "$KERNEL_OPTION is enabled!" diff --git a/bin/hardening/1.1.23_disable_usb_storage.sh b/bin/hardening/1.1.23_disable_usb_storage.sh index af7a3f9..59faa80 100755 --- a/bin/hardening/1.1.23_disable_usb_storage.sh +++ b/bin/hardening/1.1.23_disable_usb_storage.sh @@ -20,25 +20,35 @@ DESCRIPTION="Disable USB storage." # Note: we check /proc/config.gz to be compliant with both monolithic and modular kernels KERNEL_OPTION="CONFIG_USB_STORAGE" -MODULE_FILE="usb-storage" +MODULE_NAME="usb-storage" # This function will be called if the script status is on enabled / audit mode audit() { - is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_FILE" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - crit "$KERNEL_OPTION is enabled!" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing or disable this check!" else - ok "$KERNEL_OPTION is disabled" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + crit "$MODULE_NAME is enabled!" + else + ok "$MODULE_NAME is disabled" + fi fi } # This function will be called if the script status is on enabled mode apply() { - is_kernel_option_enabled "$KERNEL_OPTION" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - warn "I cannot fix $KERNEL_OPTION enabled, recompile your kernel please" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing!" else - ok "$KERNEL_OPTION is disabled, nothing to do" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + warn "I cannot fix $MODULE_NAME, recompile your kernel or blacklist module $MODULE_NAME (/etc/modprobe.d/blacklist.conf : +install $MODULE_NAME /bin/true)" + else + ok "$MODULE_NAME is disabled" + fi fi } diff --git a/bin/hardening/3.4.1_disable_dccp.sh b/bin/hardening/3.4.1_disable_dccp.sh index edf1535..ba1ceed 100755 --- a/bin/hardening/3.4.1_disable_dccp.sh +++ b/bin/hardening/3.4.1_disable_dccp.sh @@ -24,21 +24,31 @@ MODULE_NAME="dccp" # This function will be called if the script status is on enabled / audit mode audit() { - is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - crit "$KERNEL_OPTION is enabled!" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing or disable this check!" else - ok "$KERNEL_OPTION is disabled" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + crit "$MODULE_NAME is enabled!" + else + ok "$MODULE_NAME is disabled" + fi fi } # This function will be called if the script status is on enabled mode apply() { - is_kernel_option_enabled "$KERNEL_OPTION" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - warn "I cannot fix $KERNEL_OPTION enabled, recompile your kernel please" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing!" else - ok "$KERNEL_OPTION is disabled, nothing to do" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + warn "I cannot fix $MODULE_NAME, recompile your kernel or blacklist module $MODULE_NAME (/etc/modprobe.d/blacklist.conf : +install $MODULE_NAME /bin/true)" + else + ok "$MODULE_NAME is disabled" + fi fi } diff --git a/bin/hardening/3.4.2_disable_sctp.sh b/bin/hardening/3.4.2_disable_sctp.sh index 48b6fc0..6269304 100755 --- a/bin/hardening/3.4.2_disable_sctp.sh +++ b/bin/hardening/3.4.2_disable_sctp.sh @@ -24,21 +24,31 @@ MODULE_NAME="sctp" # This function will be called if the script status is on enabled / audit mode audit() { - is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - crit "$KERNEL_OPTION is enabled!" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing or disable this check!" else - ok "$KERNEL_OPTION is disabled" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + crit "$MODULE_NAME is enabled!" + else + ok "$MODULE_NAME is disabled" + fi fi } # This function will be called if the script status is on enabled mode apply() { - is_kernel_option_enabled "$KERNEL_OPTION" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - warn "I cannot fix $KERNEL_OPTION enabled, recompile your kernel please" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing!" else - ok "$KERNEL_OPTION is disabled, nothing to do" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + warn "I cannot fix $MODULE_NAME, recompile your kernel or blacklist module $MODULE_NAME (/etc/modprobe.d/blacklist.conf : +install $MODULE_NAME /bin/true)" + else + ok "$MODULE_NAME is disabled" + fi fi } diff --git a/bin/hardening/3.4.3_disable_rds.sh b/bin/hardening/3.4.3_disable_rds.sh index 3e1574e..e10f9cc 100755 --- a/bin/hardening/3.4.3_disable_rds.sh +++ b/bin/hardening/3.4.3_disable_rds.sh @@ -24,21 +24,31 @@ MODULE_NAME="rds" # This function will be called if the script status is on enabled / audit mode audit() { - is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - crit "$KERNEL_OPTION is enabled!" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing or disable this check!" else - ok "$KERNEL_OPTION is disabled" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + crit "$MODULE_NAME is enabled!" + else + ok "$MODULE_NAME is disabled" + fi fi } # This function will be called if the script status is on enabled mode apply() { - is_kernel_option_enabled "$KERNEL_OPTION" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - warn "I cannot fix $KERNEL_OPTION enabled, recompile your kernel please" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing!" else - ok "$KERNEL_OPTION is disabled, nothing to do" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + warn "I cannot fix $MODULE_NAME, recompile your kernel or blacklist module $MODULE_NAME (/etc/modprobe.d/blacklist.conf : +install $MODULE_NAME /bin/true)" + else + ok "$MODULE_NAME is disabled" + fi fi } diff --git a/bin/hardening/3.4.4_disable_tipc.sh b/bin/hardening/3.4.4_disable_tipc.sh index 5e7a402..f38c687 100755 --- a/bin/hardening/3.4.4_disable_tipc.sh +++ b/bin/hardening/3.4.4_disable_tipc.sh @@ -24,21 +24,31 @@ MODULE_NAME="tipc" # This function will be called if the script status is on enabled / audit mode audit() { - is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - crit "$KERNEL_OPTION is enabled!" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing or disable this check!" else - ok "$KERNEL_OPTION is disabled" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + crit "$MODULE_NAME is enabled!" + else + ok "$MODULE_NAME is disabled" + fi fi } # This function will be called if the script status is on enabled mode apply() { - is_kernel_option_enabled "$KERNEL_OPTION" - if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated - warn "I cannot fix $KERNEL_OPTION enabled, recompile your kernel please" + if [ "$IS_CONTAINER" -eq 1 ]; then + # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it + ok "Container detected, consider host enforcing!" else - ok "$KERNEL_OPTION is disabled, nothing to do" + is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" + if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated + warn "I cannot fix $MODULE_NAME, recompile your kernel or blacklist module $MODULE_NAME (/etc/modprobe.d/blacklist.conf : +install $MODULE_NAME /bin/true)" + else + ok "$MODULE_NAME is disabled" + fi fi } diff --git a/debian/cis-hardening.8 b/debian/cis-hardening.8 index 917d318..7a51e96 100644 --- a/debian/cis-hardening.8 +++ b/debian/cis-hardening.8 @@ -127,6 +127,11 @@ Note that you need to provide a sudoers file with NOPASSWD option in password. Finally note that \f[C]--sudo\f[R] mode only works for audit mode. .TP +.B \f[C]--set-log-level=level\f[R] +This option sets LOGLEVEL, you can choose : info, warning, error, ok, +debug. +Default value is : info +.TP .B \f[C]--batch\f[R] While performing system audit, this option sets LOGLEVEL to `ok' and captures all output to print only one line once the check is done, diff --git a/lib/common.sh b/lib/common.sh index 151975a..3a5c3d1 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -113,11 +113,36 @@ sudo_wrapper() { fi } +# +# detect if container based on cgroup detection +# +is_running_in_container() { + awk -F/ '$2 == "'"$1"'"' /proc/self/cgroup +} + +CONTAINER_TYPE="" +IS_CONTAINER=0 + +if [ "$(is_running_in_container "docker")" != "" ]; then + CONTAINER_TYPE="docker" + IS_CONTAINER=1 +fi +if [ "$(is_running_in_container "lxc")" != "" ]; then + CONTAINER_TYPE="lxc" + IS_CONTAINER=1 +fi +if [ "$(is_running_in_container "kubepods")" != "" ]; then + # shellcheck disable=SC2034 + CONTAINER_TYPE="kubepods" + # shellcheck disable=SC2034 + IS_CONTAINER=1 +fi + # # Math functions # -function div() { +div() { local _d=${3:-2} local _n=0000000000 _n=${_n:0:$_d} diff --git a/lib/utils.sh b/lib/utils.sh index 0d0c959..d30f948 100644 --- a/lib/utils.sh +++ b/lib/utils.sh @@ -295,51 +295,90 @@ is_service_enabled() { is_kernel_option_enabled() { local KERNEL_OPTION="$1" local MODULE_NAME="" + local MODPROBE_FILTER="" local RESULT="" + local IS_MONOLITHIC_KERNEL=1 + local DEF_MODULE="" if [ $# -ge 2 ]; then MODULE_NAME="$2" fi - if $SUDO_CMD [ -r "/proc/config.gz" ]; then - RESULT=$($SUDO_CMD zgrep "^$KERNEL_OPTION=" /proc/config.gz) || : - elif $SUDO_CMD [ -r "/boot/config-$(uname -r)" ]; then - RESULT=$($SUDO_CMD grep "^$KERNEL_OPTION=" "/boot/config-$(uname -r)") || : - else - debug "No information about kernel found, you're probably in a container" - FNRET=127 - return + if [ $# -ge 3 ]; then + MODPROBE_FILTER="$3" fi - ANSWER=$(cut -d = -f 2 <<<"$RESULT") - if [ "x$ANSWER" = "xy" ]; then - debug "Kernel option $KERNEL_OPTION enabled" - FNRET=0 - elif [ "x$ANSWER" = "xn" ]; then - debug "Kernel option $KERNEL_OPTION disabled" - FNRET=1 - else - debug "Kernel option $KERNEL_OPTION not found" - FNRET=2 # Not found + debug "Detect if lsmod is available and does not return an error code (otherwise consider as a monolithic kernel" + if $SUDO_CMD lsmod >/dev/null 2>&1; then + IS_MONOLITHIC_KERNEL=0 fi - if $SUDO_CMD [ "$FNRET" -ne 0 ] && [ -n "$MODULE_NAME" ] && [ -d "/lib/modules/$(uname -r)" ]; then - # also check in modules, because even if not =y, maybe - # the admin compiled it separately later (or out-of-tree) - # as a module (regardless of the fact that we have =m or not) - debug "Checking if we have $MODULE_NAME.ko" - local modulefile - modulefile=$($SUDO_CMD find "/lib/modules/$(uname -r)/" -type f -name "$MODULE_NAME.ko") - if $SUDO_CMD [ -n "$modulefile" ]; then - debug "We do have $modulefile!" - # ... but wait, maybe it's blacklisted? check files in /etc/modprobe.d/ for "blacklist xyz" - if grep -qRE "^\s*blacklist\s+$MODULE_NAME\s*$" /etc/modprobe.d/; then - debug "... but it's blacklisted!" - FNRET=1 # Not found (found but blacklisted) - # FIXME: even if blacklisted, it might be present in the initrd and - # be insmod from there... but painful to check :/ maybe lsmod would be enough ? + if [ $IS_MONOLITHIC_KERNEL -eq 1 ]; then + if $SUDO_CMD [ -r "/proc/config.gz" ]; then + RESULT=$($SUDO_CMD zgrep "^$KERNEL_OPTION=" /proc/config.gz) || : + elif $SUDO_CMD [ -r "/boot/config-$(uname -r)" ]; then + RESULT=$($SUDO_CMD grep "^$KERNEL_OPTION=" "/boot/config-$(uname -r)") || : + else + debug "No information about kernel found, you're probably in a container" + FNRET=127 + return + fi + + ANSWER=$(cut -d = -f 2 <<<"$RESULT") + if [ "x$ANSWER" = "xy" ]; then + debug "Kernel option $KERNEL_OPTION enabled" + FNRET=0 + elif [ "x$ANSWER" = "xn" ]; then + debug "Kernel option $KERNEL_OPTION disabled" + FNRET=1 + else + debug "Kernel option $KERNEL_OPTION not found" + FNRET=2 # Not found + fi + + if $SUDO_CMD [ "$FNRET" -ne 0 ] && [ -n "$MODULE_NAME" ] && [ -d "/lib/modules/$(uname -r)" ]; then + # also check in modules, because even if not =y, maybe + # the admin compiled it separately later (or out-of-tree) + # as a module (regardless of the fact that we have =m or not) + debug "Checking if we have $MODULE_NAME.ko" + local modulefile + modulefile=$($SUDO_CMD find "/lib/modules/$(uname -r)/" -type f -name "$MODULE_NAME.ko") + if $SUDO_CMD [ -n "$modulefile" ]; then + debug "We do have $modulefile!" + # ... but wait, maybe it's blacklisted? check files in /etc/modprobe.d/ for "blacklist xyz" + if grep -qRE "^\s*blacklist\s+$MODULE_NAME\s*$" /etc/modprobe.d/*.conf; then + debug "... but it's blacklisted!" + FNRET=1 # Not found (found but blacklisted) + fi + # ... but wait, maybe it's override ? check files in /etc/modprobe.d/ for "install xyz /bin/(true|false)" + if grep -aRE "^\s*install\s+$MODULE_NAME\s+/bin/(true|false)\s*$" /etc/modprobe.d/*.conf; then + debug "... but it's override!" + FNRET=1 # Not found (found but override) + fi + FNRET=0 # Found! fi - FNRET=0 # Found! + fi + else + if [ "$FILTER" != "" ]; then + DEF_MODULE="$($SUDO_CMD modprobe -n -v "$MODULE_NAME" 2>/dev/null | grep -E "$MODPROBE_FILTER" | xargs)" + else + DEF_MODULE="$($SUDO_CMD modprobe -n -v "$MODULE_NAME" 2>/dev/null | xargs)" + fi + + if [ "$DEF_MODULE" == "install /bin/true" ] || [ "$DEF_MODULE" == "install /bin/false" ]; then + debug "$MODULE_NAME is disabled (blacklist with override)" + FNRET=1 + elif [ "$DEF_MODULE" == "" ]; then + debug "$MODULE_NAME is disabled" + FNRET=1 + else + debug "$MODULE_NAME is enabled" + FNRET=0 + fi + + if [ "$($SUDO_CMD lsmod | grep -E "$MODULE_NAME" 2>/dev/null)" != "" ]; then + debug "$MODULE_NAME is enabled" + FNRET=0 fi fi } diff --git a/tests/hardening/3.4.1_disable_dccp.sh b/tests/hardening/3.4.1_disable_dccp.sh index a5243cb..5195a49 100644 --- a/tests/hardening/3.4.1_disable_dccp.sh +++ b/tests/hardening/3.4.1_disable_dccp.sh @@ -1,11 +1,15 @@ # shellcheck shell=bash # run-shellcheck test_audit() { - describe Running on blank host - register_test retvalshouldbe 0 - dismiss_count_for_test - # shellcheck disable=2154 - run blank /opt/debian-cis/bin/hardening/"${script}".sh --audit-all + if [ -f "/.dockerenv" ]; then + skip "SKIPPED on docker" + else + describe Running on blank host + register_test retvalshouldbe 0 + dismiss_count_for_test + # shellcheck disable=2154 + run blank /opt/debian-cis/bin/hardening/"${script}".sh --audit-all + fi ################################################################## # For this test, we only check that it runs properly on a blank # diff --git a/tests/hardening/3.4.2_disable_sctp.sh b/tests/hardening/3.4.2_disable_sctp.sh index a5243cb..5195a49 100644 --- a/tests/hardening/3.4.2_disable_sctp.sh +++ b/tests/hardening/3.4.2_disable_sctp.sh @@ -1,11 +1,15 @@ # shellcheck shell=bash # run-shellcheck test_audit() { - describe Running on blank host - register_test retvalshouldbe 0 - dismiss_count_for_test - # shellcheck disable=2154 - run blank /opt/debian-cis/bin/hardening/"${script}".sh --audit-all + if [ -f "/.dockerenv" ]; then + skip "SKIPPED on docker" + else + describe Running on blank host + register_test retvalshouldbe 0 + dismiss_count_for_test + # shellcheck disable=2154 + run blank /opt/debian-cis/bin/hardening/"${script}".sh --audit-all + fi ################################################################## # For this test, we only check that it runs properly on a blank # diff --git a/tests/hardening/3.4.3_disable_rds.sh b/tests/hardening/3.4.3_disable_rds.sh index a5243cb..5195a49 100644 --- a/tests/hardening/3.4.3_disable_rds.sh +++ b/tests/hardening/3.4.3_disable_rds.sh @@ -1,11 +1,15 @@ # shellcheck shell=bash # run-shellcheck test_audit() { - describe Running on blank host - register_test retvalshouldbe 0 - dismiss_count_for_test - # shellcheck disable=2154 - run blank /opt/debian-cis/bin/hardening/"${script}".sh --audit-all + if [ -f "/.dockerenv" ]; then + skip "SKIPPED on docker" + else + describe Running on blank host + register_test retvalshouldbe 0 + dismiss_count_for_test + # shellcheck disable=2154 + run blank /opt/debian-cis/bin/hardening/"${script}".sh --audit-all + fi ################################################################## # For this test, we only check that it runs properly on a blank # diff --git a/tests/hardening/3.4.4_disable_tipc.sh b/tests/hardening/3.4.4_disable_tipc.sh index a5243cb..5195a49 100644 --- a/tests/hardening/3.4.4_disable_tipc.sh +++ b/tests/hardening/3.4.4_disable_tipc.sh @@ -1,11 +1,15 @@ # shellcheck shell=bash # run-shellcheck test_audit() { - describe Running on blank host - register_test retvalshouldbe 0 - dismiss_count_for_test - # shellcheck disable=2154 - run blank /opt/debian-cis/bin/hardening/"${script}".sh --audit-all + if [ -f "/.dockerenv" ]; then + skip "SKIPPED on docker" + else + describe Running on blank host + register_test retvalshouldbe 0 + dismiss_count_for_test + # shellcheck disable=2154 + run blank /opt/debian-cis/bin/hardening/"${script}".sh --audit-all + fi ################################################################## # For this test, we only check that it runs properly on a blank #