Compare commits

...

8 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
ab0dba9f95 chore: drop debian 10 and below support (#264)
Currently, the only LTS Debian are 11 and 12
We only support CIS for LTS debian

Co-authored-by: Damien Cavagnini <damien.cavagnini@corp.ovh.com>
2025-07-04 14:18:56 +02:00
f2c6f36b94 fix: ipv6_is_enabled related checks (#263)
fix issue #251 : https://github.com/ovh/debian-cis/issues/251

the 'is_ipv6_enabled' function was doing some 'crit' actions, which is not the expected behaviour: we don't want to fail if ipv6 is enabled, it is just an infor that checks are going to use.

Also, it was overriding the SYSCTL_PARAMS that could have been defined in the checks.

Co-authored-by: Damien Cavagnini <damien.cavagnini@corp.ovh.com>
2025-07-04 09:08:50 +02:00
6123a56653 fix: update record_mac_edit.sh to use apparmor instead of selinux (#262)
Update record_mac_edit.sh to be compliant with debian11 and debian12 CIS recommendations.

fix issue #195

Co-authored-by: Damien Cavagnini <damien.cavagnini@corp.ovh.com>
2025-07-03 09:27:09 +02:00
67 changed files with 1905 additions and 401 deletions

View File

@ -4,13 +4,6 @@ on:
- pull_request - pull_request
- push - push
jobs: jobs:
functionnal-tests-docker-debian10:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Run the tests debian10
run: ./tests/docker_build_and_run_tests.sh debian10
functionnal-tests-docker-debian11: functionnal-tests-docker-debian11:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

View File

@ -4,7 +4,7 @@
# NAME # NAME
cis-hardening - CIS Debian 10/11/12 Hardening cis-hardening - CIS Debian 11/12 Hardening
# SYNOPSIS # SYNOPSIS
@ -12,7 +12,7 @@ cis-hardening - CIS Debian 10/11/12 Hardening
# DESCRIPTION # DESCRIPTION
Modular Debian 10/11/12 security hardening scripts based on the CIS (https://www.cisecurity.org) recommendations. Modular Debian 11/12 security hardening scripts based on the CIS (https://www.cisecurity.org) recommendations.
We use it at OVHcloud (https://www.ovhcloud.com) to harden our PCI-DSS infrastructure. We use it at OVHcloud (https://www.ovhcloud.com) to harden our PCI-DSS infrastructure.

View File

@ -1,4 +1,4 @@
# :lock: CIS Debian 10/11/12 Hardening # :lock: CIS Debian 11/12 Hardening
<p align="center"> <p align="center">
@ -13,7 +13,7 @@
![License](https://img.shields.io/github/license/ovh/debian-cis) ![License](https://img.shields.io/github/license/ovh/debian-cis)
--- ---
Modular Debian 10/11/12 security hardening scripts based on [cisecurity.org](https://www.cisecurity.org) Modular Debian 11/12 security hardening scripts based on [cisecurity.org](https://www.cisecurity.org)
recommendations. We use it at [OVHcloud](https://www.ovhcloud.com) to harden our PCI-DSS infrastructure. recommendations. We use it at [OVHcloud](https://www.ovhcloud.com) to harden our PCI-DSS infrastructure.
NB : Although Debian 12 CIS Hardening guide is still in development, we do use this set of scripts NB : Although Debian 12 CIS Hardening guide is still in development, we do use this set of scripts
@ -174,7 +174,7 @@ Functional tests are available. They are to be run in a Docker environment.
$ ./tests/docker_build_and_run_tests.sh <target> [name of test script...] $ ./tests/docker_build_and_run_tests.sh <target> [name of test script...]
``` ```
With `target` being like `debian10` or `debian11`. With `target` being like `debian11` or `debian12`.
Running without script arguments will run all tests in `./tests/hardening/` directory. Running without script arguments will run all tests in `./tests/hardening/` directory.
Or you can specify one or several test script to be run. Or you can specify one or several test script to be run.

View File

@ -254,7 +254,7 @@ if [ "$DISTRIBUTION" != "debian" ]; then
echo "You can deactivate this message by setting the LOGLEVEL variable in /etc/hardening.cfg" echo "You can deactivate this message by setting the LOGLEVEL variable in /etc/hardening.cfg"
fi fi
else else
if [ "$DEB_MAJ_VER" = "sid" ] || [ "$DEB_MAJ_VER" -gt "$HIGHEST_SUPPORTED_DEBIAN_VERSION" ]; then if [ "$DEB_MAJ_VER" -gt "$HIGHEST_SUPPORTED_DEBIAN_VERSION" ]; then
echo "Your debian version is too recent and is not supported yet because there is no official CIS PDF for this version yet." echo "Your debian version is too recent and is not supported yet because there is no official CIS PDF for this version yet."
if [ "$ALLOW_UNSUPPORTED_DISTRIBUTION" -eq 0 ]; then if [ "$ALLOW_UNSUPPORTED_DISTRIBUTION" -eq 0 ]; then
echo "If you want to run it anyway, you can use the flag --allow-unsupported-distribution" echo "If you want to run it anyway, you can use the flag --allow-unsupported-distribution"

View File

@ -59,17 +59,9 @@ check_config() {
: :
} }
# As we use DEB_MAJ_VER, which is set by constants.sh, itself sourced by main.sh below,
# We need to call this in the subs called by main.sh when it is sourced, otherwise it would
# either be too soon (DEB_MAJ_VER not defined) or too late (test has already been run)
_set_vars_jit() { _set_vars_jit() {
if [ "$DEB_MAJ_VER" = "sid" ] || [ "$DEB_MAJ_VER" -ge "11" ]; then CONF_LINE_REGEX="ENCRYPT_METHOD (SHA512|yescrypt|YESCRYPT)"
CONF_LINE_REGEX="ENCRYPT_METHOD (SHA512|yescrypt|YESCRYPT)" CONF_LINE="ENCRYPT_METHOD YESCRYPT"
CONF_LINE="ENCRYPT_METHOD YESCRYPT"
else
CONF_LINE_REGEX="ENCRYPT_METHOD SHA512"
CONF_LINE="ENCRYPT_METHOD SHA512"
fi
} }
# Source Root Dir Parameter # Source Root Dir Parameter

View File

@ -49,11 +49,7 @@ apply() {
ok "$CONF_LINE is present in $CONF_FILE" ok "$CONF_LINE is present in $CONF_FILE"
else else
warn "$CONF_LINE is not present in $CONF_FILE" warn "$CONF_LINE is not present in $CONF_FILE"
if [ "$DEB_MAJ_VER" = "sid" ] || [ "$DEB_MAJ_VER" -ge "11" ]; then add_line_file_before_pattern "$CONF_FILE" "password [success=1 default=ignore] pam_unix.so yescrypt" "# pam-auth-update(8) for details."
add_line_file_before_pattern "$CONF_FILE" "password [success=1 default=ignore] pam_unix.so yescrypt" "# pam-auth-update(8) for details."
else
add_line_file_before_pattern "$CONF_FILE" "password [success=1 default=ignore] pam_unix.so sha512" "# pam-auth-update(8) for details."
fi
fi fi
fi fi
} }
@ -67,11 +63,7 @@ check_config() {
# We need to call this in the subs called by main.sh when it is sourced, otherwise it would # We need to call this in the subs called by main.sh when it is sourced, otherwise it would
# either be too soon (DEB_MAJ_VER not defined) or too late (test has already been run) # either be too soon (DEB_MAJ_VER not defined) or too late (test has already been run)
_set_vars_jit() { _set_vars_jit() {
if [ "$DEB_MAJ_VER" = "sid" ] || [ "$DEB_MAJ_VER" -ge "11" ]; then CONF_LINE="^\s*password\s.+\s+pam_unix\.so\s+.*(sha512|yescrypt)" # https://github.com/ovh/debian-cis/issues/158
CONF_LINE="^\s*password\s.+\s+pam_unix\.so\s+.*(sha512|yescrypt)" # https://github.com/ovh/debian-cis/issues/158
else
CONF_LINE="^\s*password\s.+\s+pam_unix\.so\s+.*sha512"
fi
} }
# Source Root Dir Parameter # Source Root Dir Parameter

View File

@ -37,7 +37,7 @@ audit() {
pw_found+="$user " pw_found+="$user "
ok "User $user has a disabled password." ok "User $user has a disabled password."
# yescrypt: Check password against $y$<salt>$<base64> # yescrypt: Check password against $y$<salt>$<base64>
elif [ "$DEB_MAJ_VER" -ge "11" ] && [[ $passwd =~ ^\$y\$[./A-Za-z0-9]+\$[./A-Za-z0-9]{,86}\$[./A-Za-z0-9]{43} ]]; then elif [[ $passwd =~ ^\$y\$[./A-Za-z0-9]+\$[./A-Za-z0-9]{,86}\$[./A-Za-z0-9]{43} ]]; then
pw_found+="$user " pw_found+="$user "
ok "User $user has suitable yescrypt hashed password." ok "User $user has suitable yescrypt hashed password."
# sha512: Check password against $6$<salt>$<base64>, see `man 3 crypt` # sha512: Check password against $6$<salt>$<base64>, see `man 3 crypt`
@ -46,11 +46,7 @@ audit() {
ok "User $user has suitable sha512crypt hashed password." ok "User $user has suitable sha512crypt hashed password."
else else
pw_found+="$user " pw_found+="$user "
if [ "$DEB_MAJ_VER" -ge "11" ]; then crit "User $user has a password that is not sha512crypt nor yescrypt hashed."
crit "User $user has a password that is not sha512crypt nor yescrypt hashed."
else
crit "User $user has a password that is not sha512crypt hashed."
fi
fi fi
done done
if [[ -z "$users_reviewed" ]]; then if [[ -z "$users_reviewed" ]]; then

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

@ -6,7 +6,7 @@
# #
# #
# Ensure that the distribution version is debian and that the version is 9 or 10 # Ensure that the distribution version is debian and supported
# #
set -e # One error, it's over set -e # One error, it's over
@ -22,7 +22,7 @@ audit() {
if [ "$DISTRIBUTION" != "debian" ]; then if [ "$DISTRIBUTION" != "debian" ]; then
crit "Your distribution has been identified as $DISTRIBUTION which is not debian" crit "Your distribution has been identified as $DISTRIBUTION which is not debian"
else else
if [ "$DEB_MAJ_VER" = "sid" ] || [ "$DEB_MAJ_VER" -gt "$HIGHEST_SUPPORTED_DEBIAN_VERSION" ]; then if [ "$DEB_MAJ_VER" -gt "$HIGHEST_SUPPORTED_DEBIAN_VERSION" ]; then
crit "Your distribution is too recent and is not yet supported." crit "Your distribution is too recent and is not yet supported."
elif [ "$DEB_MAJ_VER" -lt "$SMALLEST_SUPPORTED_DEBIAN_VERSION" ]; then elif [ "$DEB_MAJ_VER" -lt "$SMALLEST_SUPPORTED_DEBIAN_VERSION" ]; then
crit "Your distribution is debian but is deprecated. Consider upgrading to a supported version." crit "Your distribution is debian but is deprecated. Consider upgrading to a supported version."

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

@ -59,23 +59,14 @@ apply() {
ok "$PATTERN_AUTH is present in $FILE_AUTH" ok "$PATTERN_AUTH is present in $FILE_AUTH"
else else
warn "$PATTERN_AUTH is not present in $FILE_AUTH, adding it" warn "$PATTERN_AUTH is not present in $FILE_AUTH, adding it"
if [ 10 -ge "$DEB_MAJ_VER" ]; then add_line_file_before_pattern "$FILE_AUTH" "auth required pam_faillock.so onerr=fail audit silent deny=5 unlock_time=900" "# pam-auth-update(8) for details."
add_line_file_before_pattern "$FILE_AUTH" "auth required pam_tally2.so onerr=fail audit silent deny=5 unlock_time=900" "# pam-auth-update(8) for details."
else
add_line_file_before_pattern "$FILE_AUTH" "auth required pam_faillock.so onerr=fail audit silent deny=5 unlock_time=900" "# pam-auth-update(8) for details."
fi
fi fi
does_pattern_exist_in_file "$FILE_ACCOUNT" "$PATTERN_ACCOUNT" does_pattern_exist_in_file "$FILE_ACCOUNT" "$PATTERN_ACCOUNT"
if [ "$FNRET" = 0 ]; then if [ "$FNRET" = 0 ]; then
ok "$PATTERN_ACCOUNT is present in $FILE_ACCOUNT" ok "$PATTERN_ACCOUNT is present in $FILE_ACCOUNT"
else else
warn "$PATTERN_ACCOUNT is not present in $FILE_ACCOUNT, adding it" warn "$PATTERN_ACCOUNT is not present in $FILE_ACCOUNT, adding it"
if [ 10 -ge "$DEB_MAJ_VER" ]; then add_line_file_before_pattern "$FILE_ACCOUNT" "account required pam_faillock.so" "# pam-auth-update(8) for details."
add_line_file_before_pattern "$FILE_ACCOUNT" "account required pam_tally2.so" "# pam-auth-update(8) for details."
else
add_line_file_before_pattern "$FILE_ACCOUNT" "account required pam_faillock.so" "# pam-auth-update(8) for details."
fi
fi 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

@ -17,64 +17,48 @@ HARDENING_LEVEL=4
# shellcheck disable=2034 # shellcheck disable=2034
DESCRIPTION="Record events that modify the system's mandatory access controls (MAC)." DESCRIPTION="Record events that modify the system's mandatory access controls (MAC)."
AUDIT_PARAMS='-w /etc/selinux/ -p wa -k MAC-policy' AUDIT_PARAMS=("-w /etc/apparmor/ -p wa -k MAC-policy" "-w /etc/apparmor.d/ -p wa -k MAC-policy")
FILES_TO_SEARCH='/etc/audit/audit.rules /etc/audit/rules.d/audit.rules' AUDIT_FILE='/etc/audit/audit.rules'
FILE='/etc/audit/rules.d/audit.rules' ADDITIONAL_PATH="/etc/audit/rules.d"
FILE_TO_WRITE='/etc/audit/rules.d/audit.rules'
# 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() {
# define custom IFS and save default one MISSING_PARAMS=()
d_IFS=$IFS index=0
c_IFS=$'\n' # use find here in order to simplify test usage with sudo using secaudit user
IFS=$c_IFS FILES_TO_SEARCH="$(sudo_wrapper find $ADDITIONAL_PATH -name '*.rules' | paste -s) $AUDIT_FILE"
for AUDIT_VALUE in $AUDIT_PARAMS; do for i in "${!AUDIT_PARAMS[@]}"; do
debug "$AUDIT_VALUE should be in file $FILES_TO_SEARCH" debug "${AUDIT_PARAMS[i]} should be in file $FILES_TO_SEARCH"
IFS=$d_IFS
SEARCH_RES=0 SEARCH_RES=0
for FILE_SEARCHED in $FILES_TO_SEARCH; do for FILE_SEARCHED in $FILES_TO_SEARCH; do
does_pattern_exist_in_file "$FILE_SEARCHED" "$AUDIT_VALUE" does_pattern_exist_in_file "$FILE_SEARCHED" "${AUDIT_PARAMS[i]}"
IFS=$c_IFS
if [ "$FNRET" != 0 ]; then if [ "$FNRET" != 0 ]; then
debug "$AUDIT_VALUE is not in file $FILE_SEARCHED" debug "${AUDIT_PARAMS[i]} is not in file $FILE_SEARCHED"
else else
ok "$AUDIT_VALUE is present in $FILE_SEARCHED" ok "${AUDIT_PARAMS[i]} is present in $FILE_SEARCHED"
SEARCH_RES=1 SEARCH_RES=1
fi fi
done done
if [ "$SEARCH_RES" = 0 ]; then if [ "$SEARCH_RES" = 0 ]; then
crit "$AUDIT_VALUE is not present in $FILES_TO_SEARCH" crit "${AUDIT_PARAMS[i]} is not present in $FILES_TO_SEARCH"
MISSING_PARAMS[i]="${AUDIT_PARAMS[i]}"
index=$((index + 1))
fi fi
done done
IFS=$d_IFS
} }
# This function will be called if the script status is on enabled mode # This function will be called if the script status is on enabled mode
apply() { apply() {
# define custom IFS and save default one audit
d_IFS=$IFS changes=0
c_IFS=$'\n' for i in "${!MISSING_PARAMS[@]}"; do
IFS=$c_IFS info "${MISSING_PARAMS[i]} is not present in $FILES_TO_SEARCH, adding it"
for AUDIT_VALUE in $AUDIT_PARAMS; do add_end_of_file "$FILE_TO_WRITE" "${MISSING_PARAMS[i]}"
debug "$AUDIT_VALUE should be in file $FILES_TO_SEARCH" changes=1
IFS=$d_IFS
SEARCH_RES=0
for FILE_SEARCHED in $FILES_TO_SEARCH; do
does_pattern_exist_in_file "$FILE_SEARCHED" "$AUDIT_VALUE"
IFS=$c_IFS
if [ "$FNRET" != 0 ]; then
debug "$AUDIT_VALUE is not in file $FILE_SEARCHED"
else
ok "$AUDIT_VALUE is present in $FILE_SEARCHED"
SEARCH_RES=1
fi
done
if [ "$SEARCH_RES" = 0 ]; then
warn "$AUDIT_VALUE is not present in $FILES_TO_SEARCH, adding it to $FILE"
add_end_of_file "$FILE" "$AUDIT_VALUE"
eval "$(pkill -HUP -P 1 auditd)"
fi
done done
IFS=$d_IFS
[ "$changes" -eq 0 ] || eval "$(pkill -HUP -P 1 auditd)"
} }
# This function will check config parameters required # This function will check config parameters required

View File

@ -73,14 +73,7 @@ apply() {
} }
create_config() { create_config() {
set +u KEX='curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256'
debug "Debian version : $DEB_MAJ_VER "
if [[ "$DEB_MAJ_VER" -le 7 ]]; then
KEX='diffie-hellman-group-exchange-sha256'
else
KEX='curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256'
fi
set -u
cat <<EOF cat <<EOF
status=audit status=audit
# Put your KexAlgorithms # Put your KexAlgorithms

View File

@ -30,11 +30,7 @@ audit() {
crit "Cannot get Debian version. Aborting..." crit "Cannot get Debian version. Aborting..."
return return
fi fi
if [[ "${DEB_MAJ_VER}" != "sid" ]] && [[ "${DEB_MAJ_VER}" -lt "8" ]]; then
set -u
warn "Debian version too old (${DEB_MAJ_VER}), check does not apply, you should disable this check."
return
fi
set -u set -u
is_pkg_installed "$PACKAGE" is_pkg_installed "$PACKAGE"
if [ "$FNRET" != 0 ]; then if [ "$FNRET" != 0 ]; then

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

9
debian/changelog vendored
View File

@ -1,3 +1,12 @@
cis-hardening (4.1-5) unstable; urgency=medium
* drop debian10 and below support
* fix: ipv6_is_enabled (#251)
* fix: record_mac_edit.sh (#195)
* add --set-version to manage multiple cis versions in the future
-- Damien Cavagnini <damien.cavagnini@ovhcloud.com> Fri, 04 Jul 2025 10:27:18 +0200
cis-hardening (4.1-4) unstable; urgency=medium cis-hardening (4.1-4) unstable; urgency=medium
* allow multiple users in 5.2.18 (#228) * allow multiple users in 5.2.18 (#228)

View File

@ -4,13 +4,13 @@
.hy .hy
.SH NAME .SH NAME
.PP .PP
cis-hardening - CIS Debian 10/11/12 Hardening cis-hardening - CIS Debian 11/12 Hardening
.SH SYNOPSIS .SH SYNOPSIS
.PP .PP
\f[B]hardening.sh\f[R] RUN_MODE OPTIONS \f[B]hardening.sh\f[R] RUN_MODE OPTIONS
.SH DESCRIPTION .SH DESCRIPTION
.PP .PP
Modular Debian 10/11/12 security hardening scripts based on the CIS Modular Debian 11/12 security hardening scripts based on the CIS
(https://www.cisecurity.org) recommendations. (https://www.cisecurity.org) recommendations.
.PP .PP
We use it at OVHcloud (https://www.ovhcloud.com) to harden our PCI-DSS We use it at OVHcloud (https://www.ovhcloud.com) to harden our PCI-DSS

2
debian/control vendored
View File

@ -10,7 +10,7 @@ Vcs-Browser: https://github.com/ovh/debian-cis/
Package: cis-hardening Package: cis-hardening
Architecture: all Architecture: all
Depends: ${misc:Depends}, patch Depends: ${misc:Depends}, patch, coreutils
Description: Suite of configurable scripts to audit or harden a Debian. Description: Suite of configurable scripts to audit or harden a Debian.
Modular Debian security hardening scripts based on cisecurity.org Modular Debian security hardening scripts based on cisecurity.org
⟨cisecurity.org⟩ recommendations. We use it at OVH ⟨https://www.ovh.com⟩ to ⟨cisecurity.org⟩ recommendations. We use it at OVH ⟨https://www.ovh.com⟩ to

View File

@ -57,6 +57,6 @@ get_distribution
get_debian_major_version get_debian_major_version
# shellcheck disable=SC2034 # shellcheck disable=SC2034
SMALLEST_SUPPORTED_DEBIAN_VERSION=10 SMALLEST_SUPPORTED_DEBIAN_VERSION=11
# shellcheck disable=SC2034 # shellcheck disable=SC2034
HIGHEST_SUPPORTED_DEBIAN_VERSION=12 HIGHEST_SUPPORTED_DEBIAN_VERSION=12

View File

@ -53,7 +53,7 @@ set_sysctl_param() {
# #
is_ipv6_enabled() { is_ipv6_enabled() {
SYSCTL_PARAMS='net.ipv6.conf.all.disable_ipv6=1 net.ipv6.conf.default.disable_ipv6=1 net.ipv6.conf.lo.disable_ipv6=1' local SYSCTL_PARAMS='net.ipv6.conf.all.disable_ipv6=1 net.ipv6.conf.default.disable_ipv6=1 net.ipv6.conf.lo.disable_ipv6=1'
does_sysctl_param_exists "net.ipv6" does_sysctl_param_exists "net.ipv6"
local ENABLE=1 local ENABLE=1
@ -64,7 +64,9 @@ is_ipv6_enabled() {
debug "$SYSCTL_PARAM should be set to $SYSCTL_EXP_RESULT" debug "$SYSCTL_PARAM should be set to $SYSCTL_EXP_RESULT"
has_sysctl_param_expected_result "$SYSCTL_PARAM" "$SYSCTL_EXP_RESULT" has_sysctl_param_expected_result "$SYSCTL_PARAM" "$SYSCTL_EXP_RESULT"
if [ "$FNRET" != 0 ]; then if [ "$FNRET" != 0 ]; then
crit "$SYSCTL_PARAM was not set to $SYSCTL_EXP_RESULT" # we don't want to fail because ipv6 is enabled
# it's just an info that some scripts are going to use to decide what to do
info "$SYSCTL_PARAM was not set to $SYSCTL_EXP_RESULT"
ENABLE=0 ENABLE=0
fi fi
done done
@ -98,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
@ -305,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
@ -317,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
} }
@ -564,17 +599,27 @@ 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() {
DEB_MAJ_VER="" DEB_MAJ_VER=""
does_file_exist /etc/debian_version does_file_exist /etc/debian_version
if [ "$FNRET" = 0 ]; then if [ "$FNRET" = 0 ]; then
if grep -q "sid" /etc/debian_version; then DEB_MAJ_VER=$(cut -d '.' -f1 /etc/debian_version)
DEB_MAJ_VER="sid"
else
DEB_MAJ_VER=$(cut -d '.' -f1 /etc/debian_version)
fi
else else
# shellcheck disable=2034 # shellcheck disable=2034
DEB_MAJ_VER=$(lsb_release -r | cut -f2 | cut -d '.' -f 1) DEB_MAJ_VER=$(lsb_release -r | cut -f2 | cut -d '.' -f 1)
@ -600,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

@ -1,22 +0,0 @@
FROM debian:buster
LABEL vendor="OVH"
LABEL project="debian-cis"
LABEL url="https://github.com/ovh/debian-cis"
LABEL description="This image is used to run tests"
RUN groupadd -g 500 secaudit && useradd -u 500 -g 500 -s /bin/bash secaudit && install -m 700 -o secaudit -g secaudit -d /home/secaudit
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y openssh-server sudo syslog-ng net-tools auditd
COPY --chown=500:500 . /opt/debian-cis/
COPY debian/default /etc/default/cis-hardening
RUN sed -i 's#cis-hardening#debian-cis#' /etc/default/cis-hardening
COPY cisharden.sudoers /etc/sudoers.d/secaudit
RUN sed -i 's#cisharden#secaudit#' /etc/sudoers.d/secaudit
ENTRYPOINT ["/opt/debian-cis/tests/launch_tests.sh"]

View File

@ -36,35 +36,4 @@ test_audit() {
register_test contain "is present in /etc/login.defs" register_test contain "is present in /etc/login.defs"
run sha512pass "${CIS_CHECKS_DIR}/${script}.sh" --audit-all run sha512pass "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
# DEB_MAJ_VER cannot be overwritten here;
# therefore we need to trick get_debian_major_version
ORIGINAL_DEB_VER="$(cat /etc/debian_version)"
echo "sid" >/etc/debian_version
describe Running on blank host as sid
register_test retvalshouldbe 0
register_test contain "(SHA512|yescrypt|YESCRYPT)"
# shellcheck disable=2154
run blanksid "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
cp /etc/login.defs /tmp/login.defs.bak
sed -ir 's/ENCRYPT_METHOD[[:space:]]\+.*/ENCRYPT_METHOD MD5/' /etc/login.defs
describe Fail: wrong hash function configuration as sid
register_test retvalshouldbe 1
register_test contain "(SHA512|yescrypt|YESCRYPT)"
run wrongconfsid "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
describe Correcting situation as sid
sed -i 's/audit/enabled/' "${CIS_CONF_DIR}/conf.d/${script}.cfg"
"${CIS_CHECKS_DIR}/${script}.sh" || true
describe Checking resolved state as sid
register_test retvalshouldbe 0
register_test contain "(SHA512|yescrypt|YESCRYPT)"
run sha512passsid "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
# Cleanup
echo -n "$ORIGINAL_DEB_VER" >/etc/debian_version
unset ORIGINAL_DEB_VER
} }

View File

@ -21,35 +21,6 @@ test_audit() {
describe Checking resolved state describe Checking resolved state
register_test retvalshouldbe 0 register_test retvalshouldbe 0
register_test contain "is present in /etc/pam.d/common-password" register_test contain "is present in /etc/pam.d/common-password"
run solvedsid "${CIS_CHECKS_DIR}/${script}.sh" --audit-all run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
# DEB_MAJ_VER cannot be overwritten here;
# therefore we need to trick get_debian_major_version
ORIGINAL_DEB_VER="$(cat /etc/debian_version)"
echo "sid" >/etc/debian_version
describe Running on blank host as sid
register_test retvalshouldbe 0
register_test contain "(sha512|yescrypt)"
run blanksid "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
describe Tests purposely failing as sid
sed -i '/pam_unix.so/ s/sha512/sha256/' "/etc/pam.d/common-password" # Debian 10
sed -i '/pam_unix.so/ s/yescrypt/sha256/' "/etc/pam.d/common-password" # Debian 11+
register_test retvalshouldbe 1
register_test contain "is not present"
run noncompliantsid "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
describe correcting situation as sid
sed -i 's/audit/enabled/' "${CIS_CONF_DIR}/conf.d/${script}.cfg"
"${CIS_CHECKS_DIR}/${script}.sh" --apply || true
describe Checking resolved state as sid
register_test retvalshouldbe 0
register_test contain "is present in /etc/pam.d/common-password"
run solvedsid "${CIS_CHECKS_DIR}/${script}.sh" --audit-all
# Cleanup
echo -n "$ORIGINAL_DEB_VER" >/etc/debian_version
unset ORIGINAL_DEB_VER
} }

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

@ -2,8 +2,7 @@
# run-shellcheck # run-shellcheck
test_audit() { test_audit() {
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
@ -13,6 +12,6 @@ test_audit() {
describe Checking resolved state describe Checking resolved state
register_test retvalshouldbe 0 register_test retvalshouldbe 0
register_test contain "[ OK ] -w /etc/selinux/ -p wa -k MAC-policy is present in /etc/audit/rules.d/audit.rules" register_test contain "[ OK ] -w /etc/apparmor/ -p wa -k MAC-policy is present in /etc/audit/rules.d/audit.rules"
run resolved "${CIS_CHECKS_DIR}/${script}.sh" --audit-all 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