Compare commits

...

5 Commits

Author SHA1 Message Date
336085c6fb chore: update script related to systemctl / service
- configure_systemd-timesync.sh:        use "is_service_enabled" instead of calling systemctl
- disable_automounting.sh:              use "manage_service" instead of "update-rc.d"
- enable_auditd.sh:                     use "manage_service" instead of "update-rc.d"
- enable_cron.sh:                       use "manage_service" instead of "update-rc.d"
- enable_syslog-ng.sh:                  use "manage_service" instead of "update-rc.d"
2025-07-15 09:26:56 +02:00
5e04b3449c update lib/utils.sh
- add 'is_pkg_a_dependency', to ensure a package is not needed by some others before removing it
-> will be used in debian 12 CIS by at least the 2.1.5 recommendation

- update 'is_service_enabled' to use 'systemd' instead of 'rc.d', as we are now only supporting debian LTS using systemd
- add 'is_using_sbin_init' to ensure we can use systemctl, in case of running on non detected container
- add 'manage_service' to enable / disable service using systemctl
2025-07-15 09:26:56 +02:00
861ad71734 chore: rename some scripts
- password configuration related scripts : ensure they start as "password_" like others checks
2025-07-11 15:33:53 +02:00
68f629ed36 adding new scripts for debian12
- "users_homedir_is_configured.sh" is a concatenation of different existing scripts:
        - [users_homedir_exist.sh](https://github.com/ovh/debian-cis/blob/master/bin/hardening/users_homedir_exist.sh)
        - [users_homedir_ownership.sh](https://github.com/ovh/debian-cis/blob/master/bin/hardening/users_homedir_ownership.sh)
        - [check_user_dir_perm.sh](https://github.com/ovh/debian-cis/blob/master/bin/hardening/check_user_dir_perm.sh)
And so is its test
It will be mapped as 7.2.9 for debian 12

- The following scripts are a split from [5.3.1_enable_pwquality.sh](https://github.com/ovh/debian-cis/blob/master/bin/hardening/enable_pwquality.sh):
        - enable_libpam_pwquality.sh    -> will be mapped as 5.3.2.3
        - install_libpam_pwquality.sh   -> will be mapped as 5.3.1.3
        - password_complexity.sh        -> will be mapped as 5.3.3.2.3
        - password_min_length.sh        -> will be mapped as 5.3.3.2.2

The others are scripts are new.
They will be mapped as follow for debian 12 CIS :

- apt_gpg_is_configured.sh                      -> 1.2.1.1
- dev_shm_separate_partition.sh                 -> 1.2.2.1
- install_iptables.sh                           -> 4.3.1.1
- install_nftables.sh                           -> 4.2.1
- password_consecutive_characters.sh            -> 5.3.3.2.4
- password_max_sequential_characters.sh         -> 5.3.3.2.5
2025-07-11 15:33:46 +02:00
51bc5825d6 refactor: is_kernel_option_enabled (#267)
Current "is_kernel_option_enabled" function is doing many things, like checking for a kernel option AND checking a kernel module state AND checking if it is disabled
We split it in different functions:
        - is_kernel_monolithic
        - is_kernel_option_enabled -> check for a kernel configuration in the running kernel
        - is_kernel_module_loaded -> check if a module is currently loaded
        - is_kernel_module_available -> check if a module is configured in all available kernel configs
        - is_kernel_module_disabled   -> check if a kernel module is disabled in the modprobe configuration

Also:

- update its behaviour to debian 12 CIS recommendation, to check if a module is "available in ANY installed kernel"
- fix "disable_usb_storage" to look for correct module name once loaded : issue #249
- the associated checks now check separately if the module is loaded, and if it is configured
- for checks about kernel module presence, the "apply" function now manages to disable the module in the modprobe configuration (if kernel not monolithic) (but still wont unload it)

Co-authored-by: Damien Cavagnini <damien.cavagnini@corp.ovh.com>
2025-07-11 11:20:59 +02:00
47 changed files with 1842 additions and 199 deletions

View File

@ -0,0 +1,105 @@
#!/bin/bash
# run-shellcheck
#
# CIS Debian Hardening
#
#
# Ensure GPG keys are configured (Manual)
#
set -e # One error, it's over
set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=3
# shellcheck disable=2034
DESCRIPTION="Ensure GPG keys are configured"
APT_KEY_PATH="/etc/apt/trusted.gpg.d"
APT_KEY_FILE="/etc/apt/trusted.gpg"
# from "man apt-secure"
SOURCES_UNSECURE_OPTION='allow-insecure=yes'
APT_UNSECURE_OPTION='Acquire::AllowInsecureRepositories=true'
# This function will be called if the script status is on enabled / audit mode
audit() {
key_files=0
info "Verifying that apt keys are present"
# apt-key list requires that gnupg2 is installed
# we are not going to install it for the sake of a test, so we only check the presence of key files
is_file_empty "$APT_KEY_FILE"
if [ "$FNRET" -eq 1 ]; then
info "$APT_KEY_FILE present and not empty"
key_files=$((key_files + 1))
fi
does_file_exist "$APT_KEY_PATH"
if [ "$FNRET" -ne 0 ]; then
info "$APT_KEY_PATH is missing"
else
asc_files=$(find "$APT_KEY_PATH" -name '*.asc' | wc -l)
key_files=$((key_files + asc_files))
gpg_files=$(find "$APT_KEY_PATH" -name '*.gpg' | wc -l)
key_files=$((key_files + gpg_files))
if [ "$asc_files" -eq 0 ] && [ "$gpg_files" -eq 0 ]; then
info "No key found in $APT_KEY_PATH"
fi
fi
if [ "$key_files" -eq 0 ]; then
crit "No GPG file found"
else
# we do not test the GPG keys validity, but we ensure we don't bypass them
info "Ensure an unsecure option is not set in some sources list"
unsecure_sources=$(find /etc/apt/ -name '*.list' -exec grep -l "$SOURCES_UNSECURE_OPTION" {} \;)
if [ -n "$unsecure_sources" ]; then
crit "Some source files use $SOURCES_UNSECURE_OPTION : $unsecure_sources"
fi
info "Ensure an unsecure option is not set in some apt configuration"
unsecure_option=$(grep -R "$APT_UNSECURE_OPTION" /etc/apt | wc -l)
if [ "$unsecure_option" -gt 0 ]; then
crit "$APT_UNSECURE_OPTION is set in apt configuration"
fi
fi
}
# This function will be called if the script status is on enabled mode
apply() {
audit
if [ "$FNRET" -gt 0 ]; then
crit "Your configuraiton does not match the recommendation. Please fix it manually"
else
info "Nothing to apply"
fi
}
# This function will check config parameters required
check_config() {
# No parameter for this script
:
}
# Source Root Dir Parameter
if [ -r /etc/default/cis-hardening ]; then
# shellcheck source=../../debian/default
. /etc/default/cis-hardening
fi
if [ -z "$CIS_LIB_DIR" ]; then
echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment."
echo "Cannot source CIS_LIB_DIR variable, aborting."
exit 128
fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r "${CIS_LIB_DIR}"/main.sh ]; then
# shellcheck source=../../lib/main.sh
. "${CIS_LIB_DIR}"/main.sh
else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening"
exit 128
fi

View File

@ -21,8 +21,8 @@ SERVICE_NAME="systemd-timesyncd"
# This function will be called if the script status is on enabled / audit mode # This function will be called if the script status is on enabled / audit mode
audit() { audit() {
status=$(systemctl is-enabled "$SERVICE_NAME") is_service_enabled "$SERVICE_NAME"
if [ "$status" = "enabled" ]; then if [ "$FNRET" -eq 0 ]; then
ok "$SERVICE_NAME is enabled" ok "$SERVICE_NAME is enabled"
else else
crit "$SERVICE_NAME is disabled" crit "$SERVICE_NAME is disabled"

View File

@ -0,0 +1,80 @@
#!/bin/bash
# run-shellcheck
#
# CIS Debian Hardening
#
#
# Ensure /dev/shm is a separate partition (Automated)
#
set -e # One error, it's over
set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=3
# shellcheck disable=2034
DESCRIPTION="Ensure /dev/shm is a separate partition"
# Quick factoring as many script use the same logic
PARTITION="/dev/shm"
# This function will be called if the script status is on enabled / audit mode
audit() {
info "Verifying that $PARTITION is a partition"
FNRET=0
is_a_partition "$PARTITION"
if [ "$FNRET" -gt 0 ]; then
crit "$PARTITION is not a partition"
FNRET=2
else
ok "$PARTITION is a partition"
is_mounted "$PARTITION"
if [ "$FNRET" -gt 0 ]; then
warn "$PARTITION is not mounted"
FNRET=1
else
ok "$PARTITION is mounted"
fi
fi
}
# This function will be called if the script status is on enabled mode
apply() {
audit
if [ "$FNRET" = 0 ]; then
ok "$PARTITION is correctly set"
elif [ "$FNRET" = 2 ]; then
crit "$PARTITION is not a partition, correct this by yourself, I cannot help you here"
else
info "mounting $PARTITION"
mount "$PARTITION"
fi
}
# This function will check config parameters required
check_config() {
# No parameter for this script
:
}
# Source Root Dir Parameter
if [ -r /etc/default/cis-hardening ]; then
# shellcheck source=../../debian/default
. /etc/default/cis-hardening
fi
if [ -z "$CIS_LIB_DIR" ]; then
echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment."
echo "Cannot source CIS_LIB_DIR variable, aborting."
exit 128
fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r "${CIS_LIB_DIR}"/main.sh ]; then
# shellcheck source=../../lib/main.sh
. "${CIS_LIB_DIR}"/main.sh
else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening"
exit 128
fi

View File

@ -36,7 +36,7 @@ apply() {
is_service_enabled "$SERVICE_NAME" is_service_enabled "$SERVICE_NAME"
if [ "$FNRET" = 0 ]; then if [ "$FNRET" = 0 ]; then
info "Disabling $SERVICE_NAME" info "Disabling $SERVICE_NAME"
update-rc.d "$SERVICE_NAME" remove >/dev/null 2>&1 manage_service disable "$SERVICE_NAME"
else else
ok "$SERVICE_NAME is disabled" ok "$SERVICE_NAME is disabled"
fi fi

View File

@ -26,11 +26,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" is_kernel_module_loaded "$KERNEL_OPTION" "$MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -41,11 +55,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -28,11 +28,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" is_kernel_module_loaded "$KERNEL_OPTION" "$MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -43,11 +57,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -26,11 +26,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" is_kernel_module_loaded "$KERNEL_OPTION" "$MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -41,11 +55,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -26,11 +26,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -41,11 +55,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -26,11 +26,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -41,11 +55,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -26,11 +26,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -41,11 +55,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -28,11 +28,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" is_kernel_module_loaded "$KERNEL_OPTION" "$MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -43,11 +57,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -28,11 +28,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -43,11 +57,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -26,11 +26,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -41,11 +55,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -28,11 +28,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -43,11 +57,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -26,11 +26,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -41,11 +55,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" "($MODULE_NAME|install)" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -20,7 +20,10 @@ DESCRIPTION="Disable USB storage."
# Note: we check /proc/config.gz to be compliant with both monolithic and modular kernels # Note: we check /proc/config.gz to be compliant with both monolithic and modular kernels
KERNEL_OPTION="CONFIG_USB_STORAGE" KERNEL_OPTION="CONFIG_USB_STORAGE"
# name as used for "modprobe"
MODULE_NAME="usb-storage" MODULE_NAME="usb-storage"
# name as returned by "modinfo -F name <module_file.ko>"
LOADED_MODULE_NAME="usb_storage"
# This function will be called if the script status is on enabled / audit mode # This function will be called if the script status is on enabled / audit mode
audit() { audit() {
@ -28,11 +31,25 @@ audit() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # 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!" ok "Container detected, consider host enforcing or disable this check!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 0 ]; then # 0 means true in bash, so it IS activated
crit "$MODULE_NAME is enabled!" crit "$LOADED_MODULE_NAME is loaded!"
else else
ok "$MODULE_NAME is disabled" ok "$LOADED_MODULE_NAME is not loaded"
fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 0 ]; then
ok "$MODULE_NAME is disabled in the modprobe configuration"
else
is_kernel_module_available "$KERNEL_OPTION"
if [ "$FNRET" -eq 0 ]; then
crit "$MODULE_NAME is available in some kernel config, but not disabled"
else
ok "$MODULE_NAME is not available in any kernel config"
fi
fi
fi fi
fi fi
} }
@ -43,11 +60,18 @@ apply() {
# In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it # In an unprivileged container, the kernel modules are host dependent, so you should consider enforcing it
ok "Container detected, consider host enforcing!" ok "Container detected, consider host enforcing!"
else else
is_kernel_option_enabled "$KERNEL_OPTION" "$MODULE_NAME" is_kernel_module_loaded "$KERNEL_OPTION" "$LOADED_MODULE_NAME"
if [ "$FNRET" = 0 ]; then # 0 means true in bash, so it IS activated if [ "$FNRET" -eq 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)" crit "$LOADED_MODULE_NAME is loaded!"
else warn "I wont unload the module, unload it manually or recompile the kernel if needed"
ok "$MODULE_NAME is disabled" fi
if [ "$IS_MONOLITHIC_KERNEL" -eq 1 ]; then
is_kernel_module_disabled "$MODULE_NAME"
if [ "$FNRET" -eq 1 ]; then
echo "install $MODULE_NAME /bin/true" >>/etc/modprobe.d/"$MODULE_NAME".conf
info "$MODULE_NAME has been disabled in the modprobe configuration"
fi
fi fi
fi fi
} }

View File

@ -50,8 +50,7 @@ apply() {
ok "$SERVICE_NAME is enabled" ok "$SERVICE_NAME is enabled"
else else
warn "$SERVICE_NAME is not enabled, enabling it" warn "$SERVICE_NAME is not enabled, enabling it"
update-rc.d "$SERVICE_NAME" remove >/dev/null 2>&1 manage_service enable "$SERVICE_NAME"
update-rc.d "$SERVICE_NAME" defaults >/dev/null 2>&1
fi fi
} }

View File

@ -47,8 +47,7 @@ apply() {
is_service_enabled "$SERVICE_NAME" is_service_enabled "$SERVICE_NAME"
if [ "$FNRET" != 0 ]; then if [ "$FNRET" != 0 ]; then
info "Enabling $SERVICE_NAME" info "Enabling $SERVICE_NAME"
update-rc.d "$SERVICE_NAME" remove >/dev/null 2>&1 manage_service enable "$SERVICE_NAME"
update-rc.d "$SERVICE_NAME" defaults >/dev/null 2>&1
else else
ok "$SERVICE_NAME is enabled" ok "$SERVICE_NAME is enabled"
fi fi

View File

@ -0,0 +1,67 @@
#!/bin/bash
# run-shellcheck
#
# CIS Debian Hardening
#
#
# Ensure pam_pwquality module is enabled (Automated)
#
set -e # One error, it's over
set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=2
# shellcheck disable=2034
DESCRIPTION="Ensure pam_pwquality module is enabled."
PATTERN_COMMON='pam_pwquality.so'
FILE_COMMON='/etc/pam.d/common-password'
# This function will be called if the script status is on enabled / audit mode
audit() {
does_pattern_exist_in_file "$FILE_COMMON" "$PATTERN_COMMON"
if [ "$FNRET" = 0 ]; then
ok "$PATTERN_COMMON is present in $FILE_COMMON"
else
crit "$PATTERN_COMMON is not present in $FILE_COMMON"
fi
}
# This function will be called if the script status is on enabled mode
apply() {
does_pattern_exist_in_file $FILE_COMMON $PATTERN_COMMON
if [ "$FNRET" = 0 ]; then
ok "$PATTERN_COMMON is present in $FILE_COMMON"
else
warn "$PATTERN_COMMON is not present in $FILE_COMMON"
add_line_file_before_pattern "$FILE_COMMON" "password requisite pam_pwquality.so retry=3" "# pam-auth-update(8) for details."
fi
}
# This function will check config parameters required
check_config() {
:
}
# Source Root Dir Parameter
if [ -r /etc/default/cis-hardening ]; then
# shellcheck source=../../debian/default
. /etc/default/cis-hardening
fi
if [ -z "$CIS_LIB_DIR" ]; then
echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment."
echo "Cannot source CIS_LIB_DIR variable, aborting."
exit 128
fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r "${CIS_LIB_DIR}"/main.sh ]; then
# shellcheck source=../../lib/main.sh
. "${CIS_LIB_DIR}"/main.sh
else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening"
exit 128
fi

View File

@ -46,8 +46,7 @@ apply() {
is_service_enabled "$SERVICE_NAME" is_service_enabled "$SERVICE_NAME"
if [ "$FNRET" != 0 ]; then if [ "$FNRET" != 0 ]; then
info "Enabling $SERVICE_NAME" info "Enabling $SERVICE_NAME"
update-rc.d "$SERVICE_NAME" remove >/dev/null 2>&1 manage_service enable "$SERVICE_NAME" >/dev/null 2>&1
update-rc.d "$SERVICE_NAME" defaults >/dev/null 2>&1
else else
ok "$SERVICE_NAME is enabled" ok "$SERVICE_NAME is enabled"
fi fi

View File

@ -0,0 +1,78 @@
#!/bin/bash
# run-shellcheck
#
# CIS Debian Hardening
#
#
# Ensure iptables packages are installed (Automated)
#
set -e # One error, it's over
set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=2
# shellcheck disable=2034
DESCRIPTION="Ensure iptables firewall is installed, does not check for its configuration."
# Note: CIS recommends your iptables rules to be persistent.
# Do as you want, but this script does not handle this
PACKAGES='iptables iptables-persistent'
# This function will be called if the script status is on enabled / audit mode
audit() {
FOUND=false
for PACKAGE in $PACKAGES; do
is_pkg_installed "$PACKAGE"
if [ "$FNRET" = 0 ]; then
ok "$PACKAGE provides firewalling feature"
FOUND=true
fi
done
if [ "$FOUND" = false ]; then
crit "None of the following firewall packages are installed: $PACKAGES"
fi
}
# This function will be called if the script status is on enabled mode
apply() {
for PACKAGE in $PACKAGES; do
is_pkg_installed "$PACKAGE"
if [ "$FNRET" = 0 ]; then
ok "$PACKAGE provides firewalling feature"
FOUND=true
fi
done
if [ "$FOUND" = false ]; then
crit "None of the following firewall packages are installed: $PACKAGES, installing them"
apt_install "$PACKAGES"
fi
}
# This function will check config parameters required
check_config() {
:
}
# Source Root Dir Parameter
if [ -r /etc/default/cis-hardening ]; then
# shellcheck source=../../debian/default
. /etc/default/cis-hardening
fi
if [ -z "$CIS_LIB_DIR" ]; then
echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment."
echo "Cannot source CIS_LIB_DIR variable, aborting."
exit 128
fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r "${CIS_LIB_DIR}"/main.sh ]; then
# shellcheck source=../../lib/main.sh
. "${CIS_LIB_DIR}"/main.sh
else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening"
exit 128
fi

View File

@ -0,0 +1,66 @@
#!/bin/bash
# run-shellcheck
#
# CIS Debian Hardening
#
#
# Ensure libpam-pwquality is installed (Automated)
#
set -e # One error, it's over
set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=2
# shellcheck disable=2034
DESCRIPTION="Ensure libpam-pwquality is installed "
PACKAGE='libpam-pwquality'
# This function will be called if the script status is on enabled / audit mode
audit() {
is_pkg_installed "$PACKAGE"
if [ "$FNRET" != 0 ]; then
crit "$PACKAGE is not installed!"
else
ok "$PACKAGE is installed"
fi
}
# This function will be called if the script status is on enabled mode
apply() {
is_pkg_installed "$PACKAGE"
if [ "$FNRET" = 0 ]; then
ok "$PACKAGE is installed"
else
crit "$PACKAGE is absent, installing it"
apt_install "$PACKAGE"
fi
}
# This function will check config parameters required
check_config() {
:
}
# Source Root Dir Parameter
if [ -r /etc/default/cis-hardening ]; then
# shellcheck source=../../debian/default
. /etc/default/cis-hardening
fi
if [ -z "$CIS_LIB_DIR" ]; then
echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment."
echo "Cannot source CIS_LIB_DIR variable, aborting."
exit 128
fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r "${CIS_LIB_DIR}"/main.sh ]; then
# shellcheck source=../../lib/main.sh
. "${CIS_LIB_DIR}"/main.sh
else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening"
exit 128
fi

View File

@ -0,0 +1,78 @@
#!/bin/bash
# run-shellcheck
#
# CIS Debian Hardening
#
#
# Ensure nftables is installed (Automated)
#
set -e # One error, it's over
set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=2
# shellcheck disable=2034
DESCRIPTION="Ensure nftables firewall is installed, does not check for its configuration."
# Note: CIS recommends your iptables rules to be persistent.
# Do as you want, but this script does not handle this
PACKAGES='nftables'
# This function will be called if the script status is on enabled / audit mode
audit() {
FOUND=false
for PACKAGE in $PACKAGES; do
is_pkg_installed "$PACKAGE"
if [ "$FNRET" = 0 ]; then
ok "$PACKAGE provides firewalling feature"
FOUND=true
fi
done
if [ "$FOUND" = false ]; then
crit "None of the following firewall packages are installed: $PACKAGES"
fi
}
# This function will be called if the script status is on enabled mode
apply() {
for PACKAGE in $PACKAGES; do
is_pkg_installed "$PACKAGE"
if [ "$FNRET" = 0 ]; then
ok "$PACKAGE provides firewalling feature"
FOUND=true
fi
done
if [ "$FOUND" = false ]; then
crit "None of the following firewall packages are installed: $PACKAGES, installing them"
apt_install "$PACKAGES"
fi
}
# This function will check config parameters required
check_config() {
:
}
# Source Root Dir Parameter
if [ -r /etc/default/cis-hardening ]; then
# shellcheck source=../../debian/default
. /etc/default/cis-hardening
fi
if [ -z "$CIS_LIB_DIR" ]; then
echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment."
echo "Cannot source CIS_LIB_DIR variable, aborting."
exit 128
fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r "${CIS_LIB_DIR}"/main.sh ]; then
# shellcheck source=../../lib/main.sh
. "${CIS_LIB_DIR}"/main.sh
else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening"
exit 128
fi

View File

@ -0,0 +1,77 @@
#!/bin/bash
# run-shellcheck
#
# CIS Debian Hardening
#
#
# Ensure password complexity is configured (Manual)
#
set -e # One error, it's over
set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=2
# shellcheck disable=2034
DESCRIPTION="Ensure password minimum length is configured "
OPTIONS=''
FILE_QUALITY='/etc/security/pwquality.conf'
# This function will be called if the script status is on enabled / audit mode
audit() {
for PW_OPT in $OPTIONS; do
PW_PARAM=$(echo "$PW_OPT" | cut -d= -f1)
PW_VALUE=$(echo "$PW_OPT" | cut -d= -f2)
# note : dont backslash regex characters, as 'does_pattern_exist_in_file' use "grep -E" which don't need it
PATTERN="${PW_PARAM}[[:space:]]?+=[[:space:]]?+$PW_VALUE"
does_pattern_exist_in_file "$FILE_QUALITY" "$PATTERN"
if [ "$FNRET" = 0 ]; then
ok "$PATTERN is present in $FILE_QUALITY"
else
crit "$PATTERN is not present in $FILE_QUALITY"
fi
done
}
# This function will be called if the script status is on enabled mode
apply() {
info "The values defined here should be adapted to one needs before applying."
}
# This function will create the config file for this check with default values
create_config() {
cat <<EOF
status=audit
# Put your custom configuration here
OPTIONS="minclass=3 dcredit=-1 ucredit=-2 ocredit=-1 lcredit=-1"
EOF
}
# This function will check config parameters required
check_config() {
:
}
# Source Root Dir Parameter
if [ -r /etc/default/cis-hardening ]; then
# shellcheck source=../../debian/default
. /etc/default/cis-hardening
fi
if [ -z "$CIS_LIB_DIR" ]; then
echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment."
echo "Cannot source CIS_LIB_DIR variable, aborting."
exit 128
fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r "${CIS_LIB_DIR}"/main.sh ]; then
# shellcheck source=../../lib/main.sh
. "${CIS_LIB_DIR}"/main.sh
else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening"
exit 128
fi

View File

@ -0,0 +1,94 @@
#!/bin/bash
# run-shellcheck
#
# CIS Debian Hardening
#
#
# Ensure password same consecutive characters is configured (Automated)
#
set -e # One error, it's over
set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=2
# shellcheck disable=2034
DESCRIPTION="Ensure password same consecutive characters is configured"
OPTIONS=''
FILE_QUALITY='/etc/security/pwquality.conf'
# This function will be called if the script status is on enabled / audit mode
audit() {
for PW_OPT in $OPTIONS; do
PW_PARAM=$(echo "$PW_OPT" | cut -d= -f1)
PW_VALUE=$(echo "$PW_OPT" | cut -d= -f2)
PATTERN="^${PW_PARAM}[[:space:]]?+=[[:space:]]?+$PW_VALUE"
does_pattern_exist_in_file "$FILE_QUALITY" "$PATTERN"
if [ "$FNRET" = 0 ]; then
ok "$PATTERN is present in $FILE_QUALITY"
else
crit "$PATTERN is not present in $FILE_QUALITY"
fi
done
}
# This function will be called if the script status is on enabled mode
apply() {
for PW_OPT in $OPTIONS; do
PW_PARAM=$(echo "$PW_OPT" | cut -d= -f1)
PW_VALUE=$(echo "$PW_OPT" | cut -d= -f2)
# note : dont backslash regex characters, as 'does_pattern_exist_in_file' use "grep -E" which don't need it
PATTERN="^${PW_PARAM}[[:space:]]?+=[[:space:]]?+$PW_VALUE"
does_pattern_exist_in_file "$FILE_QUALITY" "$PATTERN"
if [ "$FNRET" = 0 ]; then
ok "$PATTERN is present in $FILE_QUALITY"
else
warn "$PATTERN is not present in $FILE_QUALITY, adding it"
does_pattern_exist_in_file "$FILE_QUALITY" "^${PW_PARAM}"
if [ "$FNRET" != 0 ]; then
add_end_of_file "$FILE_QUALITY" "$PW_PARAM = $PW_VALUE"
else
info "Parameter $PW_PARAM is present but with the wrong value -- Fixing"
replace_in_file "$FILE_QUALITY" "^${PW_PARAM}*.*" "$PW_PARAM = $PW_VALUE"
fi
fi
done
}
# This function will create the config file for this check with default values
create_config() {
cat <<EOF
status=audit
# Put your custom configuration here
OPTIONS="maxrepeat=3"
EOF
}
# This function will check config parameters required
check_config() {
:
}
# Source Root Dir Parameter
if [ -r /etc/default/cis-hardening ]; then
# shellcheck source=../../debian/default
. /etc/default/cis-hardening
fi
if [ -z "$CIS_LIB_DIR" ]; then
echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment."
echo "Cannot source CIS_LIB_DIR variable, aborting."
exit 128
fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r "${CIS_LIB_DIR}"/main.sh ]; then
# shellcheck source=../../lib/main.sh
. "${CIS_LIB_DIR}"/main.sh
else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening"
exit 128
fi

View File

@ -0,0 +1,94 @@
#!/bin/bash
# run-shellcheck
#
# CIS Debian Hardening
#
#
# Ensure password maximum sequential characters is configured (Automated)
#
set -e # One error, it's over
set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=2
# shellcheck disable=2034
DESCRIPTION="Ensure password maximum sequential characters is configured"
OPTIONS=''
FILE_QUALITY='/etc/security/pwquality.conf'
# This function will be called if the script status is on enabled / audit mode
audit() {
for PW_OPT in $OPTIONS; do
PW_PARAM=$(echo "$PW_OPT" | cut -d= -f1)
PW_VALUE=$(echo "$PW_OPT" | cut -d= -f2)
# note : dont backslash regex characters, as 'does_pattern_exist_in_file' use "grep -E" which don't need it
PATTERN="^${PW_PARAM}[[:space:]]?+=[[:space:]]?+$PW_VALUE"
does_pattern_exist_in_file "$FILE_QUALITY" "$PATTERN"
if [ "$FNRET" = 0 ]; then
ok "$PATTERN is present in $FILE_QUALITY"
else
crit "$PATTERN is not present in $FILE_QUALITY"
fi
done
}
# This function will be called if the script status is on enabled mode
apply() {
for PW_OPT in $OPTIONS; do
PW_PARAM=$(echo "$PW_OPT" | cut -d= -f1)
PW_VALUE=$(echo "$PW_OPT" | cut -d= -f2)
PATTERN="^${PW_PARAM}[[:space:]]?+=[[:space:]]?+$PW_VALUE"
does_pattern_exist_in_file "$FILE_QUALITY" "$PATTERN"
if [ "$FNRET" = 0 ]; then
ok "$PATTERN is present in $FILE_QUALITY"
else
warn "$PATTERN is not present in $FILE_QUALITY, adding it"
does_pattern_exist_in_file "$FILE_QUALITY" "^${PW_PARAM}"
if [ "$FNRET" != 0 ]; then
add_end_of_file "$FILE_QUALITY" "$PW_PARAM = $PW_VALUE"
else
info "Parameter $PW_PARAM is present but with the wrong value -- Fixing"
replace_in_file "$FILE_QUALITY" "^${PW_PARAM}*.*" "$PW_PARAM = $PW_VALUE"
fi
fi
done
}
# This function will create the config file for this check with default values
create_config() {
cat <<EOF
status=audit
# Put your custom configuration here
OPTIONS="maxsequence=3"
EOF
}
# This function will check config parameters required
check_config() {
:
}
# Source Root Dir Parameter
if [ -r /etc/default/cis-hardening ]; then
# shellcheck source=../../debian/default
. /etc/default/cis-hardening
fi
if [ -z "$CIS_LIB_DIR" ]; then
echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment."
echo "Cannot source CIS_LIB_DIR variable, aborting."
exit 128
fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r "${CIS_LIB_DIR}"/main.sh ]; then
# shellcheck source=../../lib/main.sh
. "${CIS_LIB_DIR}"/main.sh
else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening"
exit 128
fi

View File

@ -0,0 +1,94 @@
#!/bin/bash
# run-shellcheck
#
# CIS Debian Hardening
#
#
# Ensure minimum password length is configured (Automated)
#
set -e # One error, it's over
set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=2
# shellcheck disable=2034
DESCRIPTION="Ensure password minimum length is configured "
OPTIONS=''
FILE_QUALITY='/etc/security/pwquality.conf'
# This function will be called if the script status is on enabled / audit mode
audit() {
for PW_OPT in $OPTIONS; do
PW_PARAM=$(echo "$PW_OPT" | cut -d= -f1)
PW_VALUE=$(echo "$PW_OPT" | cut -d= -f2)
# note : dont backslash regex characters, as 'does_pattern_exist_in_file' use "grep -E" which don't need it
PATTERN="^${PW_PARAM}[[:space:]]?+=[[:space:]]?+$PW_VALUE"
does_pattern_exist_in_file "$FILE_QUALITY" "$PATTERN"
if [ "$FNRET" = 0 ]; then
ok "$PATTERN is present in $FILE_QUALITY"
else
crit "$PATTERN is not present in $FILE_QUALITY"
fi
done
}
# This function will be called if the script status is on enabled mode
apply() {
for PW_OPT in $OPTIONS; do
PW_PARAM=$(echo "$PW_OPT" | cut -d= -f1)
PW_VALUE=$(echo "$PW_OPT" | cut -d= -f2)
PATTERN="^${PW_PARAM}[[:space:]]?+=[[:space:]]?+$PW_VALUE"
does_pattern_exist_in_file "$FILE_QUALITY" "$PATTERN"
if [ "$FNRET" = 0 ]; then
ok "$PATTERN is present in $FILE_QUALITY"
else
warn "$PATTERN is not present in $FILE_QUALITY, adding it"
does_pattern_exist_in_file "$FILE_QUALITY" "^${PW_PARAM}"
if [ "$FNRET" != 0 ]; then
add_end_of_file "$FILE_QUALITY" "$PW_PARAM = $PW_VALUE"
else
info "Parameter $PW_PARAM is present but with the wrong value -- Fixing"
replace_in_file "$FILE_QUALITY" "^${PW_PARAM}*.*" "$PW_PARAM = $PW_VALUE"
fi
fi
done
}
# This function will create the config file for this check with default values
create_config() {
cat <<EOF
status=audit
# Put your custom configuration here
OPTIONS="minlen=14"
EOF
}
# This function will check config parameters required
check_config() {
:
}
# Source Root Dir Parameter
if [ -r /etc/default/cis-hardening ]; then
# shellcheck source=../../debian/default
. /etc/default/cis-hardening
fi
if [ -z "$CIS_LIB_DIR" ]; then
echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment."
echo "Cannot source CIS_LIB_DIR variable, aborting."
exit 128
fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r "${CIS_LIB_DIR}"/main.sh ]; then
# shellcheck source=../../lib/main.sh
. "${CIS_LIB_DIR}"/main.sh
else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening"
exit 128
fi

View File

@ -0,0 +1,161 @@
#!/bin/bash
# run-shellcheck
#
# CIS Debian Hardening
#
#
# Ensure local interactive user home directories are configured (Automated)
#
set -e # One error, it's over
set -u # One variable unset, it's over
# shellcheck disable=2034
HARDENING_LEVEL=2
# shellcheck disable=2034
DESCRIPTION="Users are assigned valid home directories"
# a home is purposefully owned by another user
# format: <dir>:<user_name>:<owner_name>
# ex: HOME_OWNER_EXCEPTIONS="/usr/sbin:daemon:root"
HOME_OWNER_EXCEPTIONS=""
# space separated list of path, where permissions are different than 0750
HOME_PERM_EXCEPTIONS=""
ERRORS=0
check_home_owner() {
# user owns home
local user=$1
local home=$2
FNRET=0
owner=$(stat -L -c "%U" "$home")
if [ "$owner" != "$user" ]; then
EXCEP_FOUND=0
for excep in $HOME_OWNER_EXCEPTIONS; do
if [ "$home:$user:$owner" = "$excep" ]; then
ok "The home directory ($home) of user $user is owned by $owner but is part of exceptions ($home:$user:$owner)."
EXCEP_FOUND=1
break
fi
done
if [ "$EXCEP_FOUND" -eq 0 ]; then
crit "The home directory ($home) of user $user is owned by $owner."
FNRET=1
fi
fi
}
check_home_perm() {
# 750 or more restrictive
local home=$1
HOME_PERM_ERRORS=0
debug "Exceptions : $HOME_PERM_EXCEPTIONS"
debug "echo \"$HOME_PERM_EXCEPTIONS\" | grep -q $home"
if echo "$HOME_PERM_EXCEPTIONS" | grep -q "$home"; then
debug "$home is confirmed as an exception"
# shellcheck disable=SC2001
RESULT=$(sed "s!$home!!" <<<"$RESULT")
else
debug "$home not found in exceptions"
fi
if [ -d "$home" ]; then
dirperm=$(/bin/ls -ld "$home" | cut -f1 -d" ")
if [ "$(echo "$dirperm" | cut -c6)" != "-" ]; then
crit "Group Write permission set on directory $home"
HOME_PERM_ERRORS=$((HOME_PERM_ERRORS + 1))
fi
if [ "$(echo "$dirperm" | cut -c8)" != "-" ]; then
crit "Other Read permission set on directory $home"
HOME_PERM_ERRORS=$((HOME_PERM_ERRORS + 1))
fi
if [ "$(echo "$dirperm" | cut -c9)" != "-" ]; then
crit "Other Write permission set on directory $home"
HOME_PERM_ERRORS=$((HOME_PERM_ERRORS + 1))
fi
if [ "$(echo "$dirperm" | cut -c10)" != "-" ]; then
crit "Other Execute permission set on directory $home"
HOME_PERM_ERRORS=$((HOME_PERM_ERRORS + 1))
fi
fi
}
# This function will be called if the script status is on enabled / audit mode
audit() {
RESULT=$(get_db passwd | awk -F: '{ print $1 ":" $3 ":" $6 }')
for LINE in $RESULT; do
debug "Working on $LINE"
USER=$(awk -F: '{print $1}' <<<"$LINE")
USERID=$(awk -F: '{print $2}' <<<"$LINE")
DIR=$(awk -F: '{print $3}' <<<"$LINE")
if [ "$USERID" -ge 1000 ]; then
if [ ! -d "$DIR" ] && [ "$USER" != "nfsnobody" ] && [ "$USER" != "nobody" ] && [ "$DIR" != "/nonexistent" ]; then
crit "The home directory ($DIR) of user $USER does not exist."
ERRORS=$((ERRORS + 1))
fi
if [ -d "$DIR" ] && [ "$USER" != "nfsnobody" ]; then
check_home_owner "$USER" "$DIR"
[ $FNRET -ne 0 ] && ERRORS=$((ERRORS + 1))
fi
fi
done
for DIR in $(get_db passwd | grep -Ev '(root|halt|sync|shutdown)' | awk -F: '($7 != "/usr/sbin/nologin" && $7 != "/sbin/nologin" && $7 != "/bin/false" && $7 !="/nonexistent" ) { print $6 }'); do
check_home_perm "$DIR"
ERRORS=$((ERRORS + HOME_PERM_ERRORS))
done
if [ "$ERRORS" -eq 0 ]; then
ok "All home directories are correctly configured"
fi
}
# This function will be called if the script status is on enabled mode
apply() {
info "Modifying home directories may seriously harm your system, report only here"
}
create_config() {
cat <<EOF
status=audit
# Put here user home directories exceptions
# format: <dir>:<user_name>:<owner_name>
HOME_OWNER_EXCEPTIONS=""
# space separated list of path, where permissions are different than 0750
HOME_PERM_EXCEPTIONS=""
EOF
}
# This function will check config parameters required
check_config() {
if [ -z "$HOME_PERM_EXCEPTIONS" ]; then
HOME_PERM_EXCEPTIONS="@"
fi
}
# Source Root Dir Parameter
if [ -r /etc/default/cis-hardening ]; then
# shellcheck source=../../debian/default
. /etc/default/cis-hardening
fi
if [ -z "$CIS_LIB_DIR" ]; then
echo "There is no /etc/default/cis-hardening file nor cis-hardening directory in current environment."
echo "Cannot source CIS_LIB_DIR variable, aborting."
exit 128
fi
# Main function, will call the proper functions given the configuration (audit, enabled, disabled)
if [ -r "${CIS_LIB_DIR}"/main.sh ]; then
# shellcheck source=../../lib/main.sh
. "${CIS_LIB_DIR}"/main.sh
else
echo "Cannot find main.sh, have you correctly defined your root directory? Current value is $CIS_LIB_DIR in /etc/default/cis-hardening"
exit 128
fi

View File

@ -100,6 +100,15 @@ does_file_exist() {
fi fi
} }
is_file_empty() {
local FILE=$1
if $SUDO_CMD [ -s "$FILE" ]; then
FNRET=1
else
FNRET=0
fi
}
has_file_correct_ownership() { has_file_correct_ownership() {
local FILE=$1 local FILE=$1
local USER=$2 local USER=$2
@ -307,7 +316,17 @@ does_group_exist() {
is_service_enabled() { is_service_enabled() {
local SERVICE=$1 local SERVICE=$1
if [ "$($SUDO_CMD find /etc/rc?.d/ -name "S*$SERVICE" -print | wc -l)" -gt 0 ]; then
# if running in a container, it does not make much sense to test for systemd / service
# the var "IS_CONTAINER" defined in lib/constant may not be enough, in case we are using systemd slices
# currently, did not find a unified way to manage all cases, so we check this only for systemctl usage
is_using_sbin_init
if [ "$FNRET" -eq 1 ]; then
debug "host was not started using '/sbin/init', systemd should not be available"
FNRET=1
return
fi
if $SUDO_CMD systemctl -t service is-enabled "$SERVICE" >/dev/null; then
debug "Service $SERVICE is enabled" debug "Service $SERVICE is enabled"
FNRET=0 FNRET=0
else else
@ -319,95 +338,109 @@ is_service_enabled() {
# #
# Kernel Options checks # Kernel Options checks
# #
is_kernel_monolithic() {
is_kernel_option_enabled() { debug "Detect if /proc/modules is available, otherwise consider as a monolithic kernel"
local KERNEL_OPTION="$1" if $SUDO_CMD ls /proc/modules >/dev/null 2>&1; then
local MODULE_NAME="" IS_MONOLITHIC_KERNEL=1
local MODPROBE_FILTER="" else
local RESULT=""
local IS_MONOLITHIC_KERNEL=1
local DEF_MODULE=""
if [ $# -ge 2 ]; then
MODULE_NAME="$2"
fi
if [ $# -ge 3 ]; then
MODPROBE_FILTER="$3"
fi
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 IS_MONOLITHIC_KERNEL=0
fi fi
}
if [ $IS_MONOLITHIC_KERNEL -eq 1 ]; then is_kernel_option_enabled() {
if $SUDO_CMD [ -r "/proc/config.gz" ]; then # check if kernel option is configured for the running kernel
RESULT=$($SUDO_CMD zgrep "^$KERNEL_OPTION=" /proc/config.gz) || : local KERNEL_OPTION="$1"
elif $SUDO_CMD [ -r "/boot/config-$(uname -r)" ]; then local RESULT=""
is_kernel_monolithic
if [ "$IS_MONOLITHIC_KERNEL" -eq 0 ] && $SUDO_CMD [ -r "/proc/config.gz" ]; then
RESULT=$($SUDO_CMD zgrep "^$KERNEL_OPTION=" /proc/config.gz) || :
fi
# modular kernel, or no configuration found in /proc
if [[ "$RESULT" == "" ]]; then
if $SUDO_CMD [ -r "/boot/config-$(uname -r)" ]; then
RESULT=$($SUDO_CMD grep "^$KERNEL_OPTION=" "/boot/config-$(uname -r)") || : RESULT=$($SUDO_CMD grep "^$KERNEL_OPTION=" "/boot/config-$(uname -r)") || :
else else
debug "No information about kernel found, you're probably in a container" info "No information about kernel configuration found"
FNRET=127 FNRET=127
return return
fi fi
fi
ANSWER=$(cut -d = -f 2 <<<"$RESULT") local ANSWER=""
if [ "$ANSWER" = "y" ]; then ANSWER=$(cut -d = -f 2 <<<"$RESULT")
debug "Kernel option $KERNEL_OPTION enabled" if [ "$ANSWER" = "y" ]; then
FNRET=0 debug "Kernel option $KERNEL_OPTION enabled"
elif [ "$ANSWER" = "n" ]; then FNRET=0
debug "Kernel option $KERNEL_OPTION disabled" elif [ "$ANSWER" = "n" ]; then
FNRET=1 debug "Kernel option $KERNEL_OPTION disabled"
else FNRET=1
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
fi
else else
if [ "$MODPROBE_FILTER" != "" ]; then debug "Kernel option $KERNEL_OPTION not found"
DEF_MODULE="$($SUDO_CMD modprobe -n -v "$MODULE_NAME" 2>/dev/null | grep -E "$MODPROBE_FILTER" | tail -1 | xargs)" FNRET=2 # Not found
else fi
DEF_MODULE="$($SUDO_CMD modprobe -n -v "$MODULE_NAME" 2>/dev/null | tail -1 | xargs)" }
fi is_kernel_module_disabled() {
# check if a kernel module is disabled in the modprobe configuration
local MODULE_NAME="$1"
FNRET=1
if [ "$DEF_MODULE" == "install /bin/true" ] || [ "$DEF_MODULE" == "install /bin/false" ]; then local module_is_disabled=0
debug "$MODULE_NAME is disabled (blacklist with override)" # is it blacklisted ?
FNRET=1 if grep -qE "\s?+[^#]?blacklist\s+$MODULE_NAME\s?$" /etc/modprobe.d/*.conf; then
elif [ "$DEF_MODULE" == "" ]; then debug "$MODULE_NAME is blacklisted"
debug "$MODULE_NAME is disabled" module_is_disabled=1
FNRET=1 # maybe it is overriden ? check files in /etc/modprobe.d/ for "install xyz /bin/(true|false)"
else elif grep -qE "\s?+[^#]?install\s+$MODULE_NAME\s+/bin/(true|false)\s?$" /etc/modprobe.d/*.conf; then
debug "$MODULE_NAME is enabled" debug "$MODULE_NAME is disabled"
module_is_disabled=1
fi
if [ "$module_is_disabled" -eq 1 ]; then
debug "$MODULE_NAME is disabled in modprobe config"
FNRET=0
fi
}
is_kernel_module_available() {
# check if a kernel module is loadable, in a non monolithic kernel
local KERNEL_OPTION="$1"
FNRET=1
is_kernel_monolithic
if [ "$IS_MONOLITHIC_KERNEL" -eq 0 ]; then
info "your kernel is monolithic, no need to check for module availability"
return
fi
# look if a module is present as a loadable module in ANY available kernel, per CIS recommendation
# shellcheck disable=2013
for config_file in $($SUDO_CMD grep -l "^$KERNEL_OPTION=" /boot/config-*); do
module_config=$($SUDO_CMD grep "^$KERNEL_OPTION=" "$config_file" | cut -d= -f 2)
if [ "$module_config" == 'm' ]; then
debug "\"${KERNEL_OPTION}=m\" found in $config_file as module"
FNRET=0 FNRET=0
fi fi
done
}
if [ "$($SUDO_CMD lsmod | grep -E "$MODULE_NAME" 2>/dev/null)" != "" ]; then is_kernel_module_loaded() {
debug "$MODULE_NAME is enabled" # check if a kernel module is actually loaded
FNRET=0 local KERNEL_OPTION="$1"
fi local LOADED_MODULE_NAME="$2"
FNRET=1
is_kernel_monolithic
if [ "$IS_MONOLITHIC_KERNEL" -eq 0 ]; then
# check if module is compiled
# if yes, then it is loaded
is_kernel_option_enabled "$KERNEL_OPTION"
elif $SUDO_CMD grep -w "$LOADED_MODULE_NAME" /proc/modules >/dev/null 2>&1; then
debug "$LOADED_MODULE_NAME is loaded in the running kernel in /proc/modules"
FNRET=0 # Found!
fi fi
} }
@ -566,6 +599,20 @@ is_pkg_installed() {
fi fi
} }
is_pkg_a_dependency() {
# check if package is needed by another installed package
local PKG_NAME=$1
local dependencies=0
dependencies=$(grep -w "${PKG_NAME}$" /var/lib/dpkg/status | grep -cEi "depends|recommends")
if [ "$dependencies" -gt 0 ]; then
debug "$PKG_NAME is a dependency for another installed package"
FNRET=0
else
FNRET=1
debug "$PKG_NAME is not a dependency for another installed package"
fi
}
# Returns Debian major version # Returns Debian major version
get_debian_major_version() { get_debian_major_version() {
@ -598,3 +645,26 @@ get_distribution() {
is_running_in_container() { is_running_in_container() {
awk -F/ '$2 == "'"$1"'"' /proc/self/cgroup awk -F/ '$2 == "'"$1"'"' /proc/self/cgroup
} }
is_using_sbin_init() {
FNRET=0
# remove '\0' to avoid 'command substitution: ignored null byte in input'
if [[ $($SUDO_CMD cat /proc/1/cmdline | tr -d '\0') != "/sbin/init" ]]; then
debug "init process is not '/sbin/init'"
FNRET=1
fi
}
manage_service() {
local action="$1"
local service="$2"
is_using_sbin_init
if [ "$FNRET" -ne 0 ]; then
debug "/sbin/init not used, systemctl wont manage service $service"
return
fi
systemctl "$action" "$service" >/dev/null 2>&1
}

View File

@ -0,0 +1,40 @@
# shellcheck shell=bash
# run-shellcheck
test_audit() {
local APT_KEY_FILE="/etc/apt/trusted.gpg"
local APT_KEY_PATH="/etc/apt/trusted.gpg.d"
local unsecure_source="/etc/apt/sources.list.d/unsecure.list"
local unsecure_conf_file="/etc/apt/apt.conf.d/unsecure"
# make sure we don't have any key
[ -f "$APT_KEY_FILE" ] && mv "$APT_KEY_FILE" /tmp
[ -d "$APT_KEY_PATH" ] && mv "$APT_KEY_PATH" /tmp
describe Running non compliant missing keys
register_test retvalshouldbe 1
# shellcheck disable=2154
run noncompliant "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
# fix the situation
[ -d /tmp/trusted.gpg.d ] && mv /tmp/trusted.gpg.d /etc/apt/
[ -f /tmp/trusted.gpg ] && mv /tmp/trusted.gpg /etc/apt/
describe Checking resolved state
register_test retvalshouldbe 0
run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
echo 'deb [allow-insecure=yes] http://deb.debian.org/debian bookworm main' >"$unsecure_source"
describe Running non compliant unsecure option in sources list
register_test retvalshouldbe 1
run noncompliant "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
rm -f "$unsecure_source"
echo 'Acquire::AllowInsecureRepositories=true' >"$unsecure_conf_file"
describe Running non compliant unsecure option in apt conf
register_test retvalshouldbe 1
run noncompliant "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
rm -f "$unsecure_conf_file"
}

View File

@ -0,0 +1,16 @@
# 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 "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
##################################################################
# For this test, we only check that it runs properly on a blank #
# host, and we check root/sudo consistency. But, we don't test #
# the apply function because it can't be automated or it is very #
# long to test and not very useful. #
##################################################################
}

View File

@ -1,9 +1,11 @@
# shellcheck shell=bash # shellcheck shell=bash
# run-shellcheck # run-shellcheck
test_audit() { test_audit() {
describe Prepare failing test
apt remove -y auditd
describe Running on blank host describe Running on blank host
register_test retvalshouldbe 0 register_test retvalshouldbe 1
dismiss_count_for_test
# shellcheck disable=2154 # shellcheck disable=2154
run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
@ -12,7 +14,8 @@ test_audit() {
"${CIS_CHECKS_DIR}/${script}.sh" || true "${CIS_CHECKS_DIR}/${script}.sh" || true
describe Checking resolved state describe Checking resolved state
register_test retvalshouldbe 0 # service still wont be enabled due to tests running inside a docker container
register_test contain "[ OK ] auditd is enabled" register_test retvalshouldbe 1
register_test contain "[ OK ] auditd is installed"
run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
} }

View File

@ -0,0 +1,21 @@
# shellcheck shell=bash
# run-shellcheck
test_audit() {
PATTERN_COMMON='pam_pwquality.so'
FILE_COMMON='/etc/pam.d/common-password'
# create issue
sed -i '/'$PATTERN_COMMON'/d' "$FILE_COMMON"
describe Running non compliant
register_test retvalshouldbe 1
# shellcheck disable=2154
run noncompliant "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
sed -i 's/audit/enabled/' "${CIS_CONF_DIR}/conf.d/${script}.cfg"
"${CIS_CHECKS_DIR}/${script}.sh" || true
describe Checking resolved state
register_test retvalshouldbe 0
run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
}

View File

@ -0,0 +1,16 @@
# 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 "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
##################################################################
# For this test, we only check that it runs properly on a blank #
# host, and we check root/sudo consistency. But, we don't test #
# the apply function because it can't be automated or it is very #
# long to test and not very useful. #
##################################################################
}

View File

@ -0,0 +1,16 @@
# 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 "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
##################################################################
# For this test, we only check that it runs properly on a blank #
# host, and we check root/sudo consistency. But, we don't test #
# the apply function because it can't be automated or it is very #
# long to test and not very useful. #
##################################################################
}

View File

@ -0,0 +1,16 @@
# 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 "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
##################################################################
# For this test, we only check that it runs properly on a blank #
# host, and we check root/sudo consistency. But, we don't test #
# the apply function because it can't be automated or it is very #
# long to test and not very useful. #
##################################################################
}

View File

@ -0,0 +1,28 @@
# shellcheck shell=bash
# run-shellcheck
test_audit() {
local OPTIONS="minclass=3 dcredit=-1 ucredit=-2 ocredit=-1 lcredit=-1"
local FILE_QUALITY='/etc/security/pwquality.conf'
# install dependencies
apt-get update
apt-get install -y libpam-pwquality
# prepare to fail
describe Prepare on purpose failed test
sed -i '/minclass/d' $FILE_QUALITY
describe Running on purpose failed test
register_test retvalshouldbe 1
# shellcheck disable=2154
run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
describe Correcting situation
echo "$OPTIONS" >>"$FILE_QUALITY"
describe Checking resolved state
register_test retvalshouldbe 0
run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
}

View File

@ -0,0 +1,28 @@
# shellcheck shell=bash
# run-shellcheck
test_audit() {
local OPTIONS="maxrepeat=3"
local FILE_QUALITY='/etc/security/pwquality.conf'
# install dependencies
apt-get update
apt-get install -y libpam-pwquality
# prepare to fail
describe Prepare on purpose failed test
sed -i '/maxrepeat/d' $FILE_QUALITY
describe Running on purpose failed test
register_test retvalshouldbe 1
# shellcheck disable=2154
run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
describe Correcting situation
echo "$OPTIONS" >>"$FILE_QUALITY"
describe Checking resolved state
register_test retvalshouldbe 0
run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
}

View File

@ -0,0 +1,28 @@
# shellcheck shell=bash
# run-shellcheck
test_audit() {
local OPTIONS="maxsequence=3"
local FILE_QUALITY='/etc/security/pwquality.conf'
# install dependencies
apt-get update
apt-get install -y libpam-pwquality
# prepare to fail
describe Prepare on purpose failed test
sed -i '/maxsequence/d' $FILE_QUALITY
describe Running on purpose failed test
register_test retvalshouldbe 1
# shellcheck disable=2154
run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
describe Correcting situation
echo "$OPTIONS" >>"$FILE_QUALITY"
describe Checking resolved state
register_test retvalshouldbe 0
run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
}

View File

@ -0,0 +1,27 @@
# shellcheck shell=bash
# run-shellcheck
test_audit() {
local OPTIONS="minlen=14"
local FILE_QUALITY='/etc/security/pwquality.conf'
# install dependencies
apt-get update
apt-get install -y libpam-pwquality
# prepare to fail
describe Prepare on purpose failed test
sed -i '/minlen/d' $FILE_QUALITY
describe Running on purpose failed test
register_test retvalshouldbe 1
# shellcheck disable=2154
run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
describe Correcting situation
echo "$OPTIONS" >>"$FILE_QUALITY"
describe Checking resolved state
register_test retvalshouldbe 0
run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
}

View File

@ -0,0 +1,88 @@
# shellcheck shell=bash
# run-shellcheck
test_audit() {
local no_home_test_user="userwithouthome"
local owner_test_user="testhomeuser"
local perm_test_user="testhomepermuser"
describe Running on blank host
register_test retvalshouldbe 0
# shellcheck disable=2154
run blank "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
home_dir_missing "$no_home_test_user"
home_dir_ownership "$owner_test_user"
home_dir_perm "$perm_test_user"
fix_home "$no_home_test_user" "$owner_test_user" "$perm_test_user"
describe Checking resolved state
register_test retvalshouldbe 0
run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
cleanup "$no_home_test_user" "$owner_test_user" "$perm_test_user"
}
home_dir_missing() {
local test_user="$1"
useradd -d /home/"$test_user" "$test_user"
describe Tests purposely failing that a homdedir does not exists
register_test retvalshouldbe 1
register_test contain "does not exist."
run noncompliant "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
}
home_dir_ownership() {
local test_user="$1"
describe Test purposely failing that a user does not own its home
useradd -d /home/"$test_user" -m "$test_user"
chown root:root /home/"$test_user"
chmod 0750 /home/"$test_user"
register_test retvalshouldbe 1
register_test contain "[ KO ] The home directory (/home/$test_user) of user $test_user is owned by root"
run noncompliant "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
}
home_dir_perm() {
local test_user="$1"
describe Tests purposely failing for wrong permissions on home
useradd -d /home/"$test_user" --create-home "$test_user"
chmod 777 /home/"$test_user"
register_test retvalshouldbe 1
register_test contain "Group Write permission set on directory"
register_test contain "Other Read permission set on directory"
register_test contain "Other Write permission set on directory"
register_test contain "Other Execute permission set on directory"
run noncompliant "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
}
fix_home() {
local missing_home_test_user="$1"
local owner_test_user="$2"
local perm_test_user="$3"
describe correcting situation for missing home
install -d -m 0750 -o "$missing_home_test_user" /home/"$missing_home_test_user"
describe correcting situation for ownership
# we don't want to erase default configurations, or others checks could fail
# shellcheck disable=2086
sed -i '/^HOME_OWNER_EXCEPTIONS/s|HOME_OWNER_EXCEPTIONS=\"|HOME_OWNER_EXCEPTIONS=\"/home/'$owner_test_user':'$owner_test_user':root |' ${CIS_CONF_DIR}/conf.d/${script}.cfg
describe correcting situation for permissions
chmod 0750 /home/"$perm_test_user"
}
cleanup() {
local users="$*"
for user in $users; do
# owner_test_user del will fail as its home is owned by another user
userdel -r "$user" || true
rm -rf /home/"${user:?}" || true
done
}

View File

@ -1 +1 @@
../../bin/hardening/limit_password_reuse.sh ../../bin/hardening/password_history_remember.sh

View File

@ -1 +1 @@
../../bin/hardening/last_password_change_past.sh ../../bin/hardening/password_last_change_past.sh