From f175cf4639466b378bd6cd0f7d140e27710623ba Mon Sep 17 00:00:00 2001 From: Samson-W Date: Mon, 16 Aug 2021 00:57:51 +0800 Subject: [PATCH 1/2] Update auditd rules of 8.1.26: replaced pam_tally2 with faillock in debian 11. --- .../8.1.26_record_pam_tally_cmd_usage.sh | 11 +++++++++++ lib/utils.sh | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/bin/hardening/8.1.26_record_pam_tally_cmd_usage.sh b/bin/hardening/8.1.26_record_pam_tally_cmd_usage.sh index 81d9052..6875fdd 100755 --- a/bin/hardening/8.1.26_record_pam_tally_cmd_usage.sh +++ b/bin/hardening/8.1.26_record_pam_tally_cmd_usage.sh @@ -6,6 +6,7 @@ # # 8.1.26 Recored pam_tally/pam_tally2 command usage(Only for Debian) (Scored) +# Replaced pam_tally2 with faillock in debian 11 # Author : Samson wen, Samson Author add this # @@ -74,13 +75,23 @@ apply () { } # This function will check config parameters required +# Replaced pam_tally2 with faillock in debian 11 check_config() { + is_debian_11 if [ $DONT_AUDITD_BY_UID -eq 1 ]; then + if [ $FNRET = 1 ]; then AUDIT_PARAMS='-a always,exit -F path=/sbin/pam_tally -F perm=wxa -k privileged-pam -a always,exit -F path=/sbin/pam_tally2 -F perm=wxa -k privileged-pam' + elif [ $FNRET = 0 ]; then +AUDIT_PARAMS='-a always,exit -F path=/usr/sbin/faillock -F perm=wxa -k privileged-pam' + fi else + if [ $FNRET = 1 ]; then AUDIT_PARAMS='-a always,exit -F path=/sbin/pam_tally -F perm=wxa -F auid>=1000 -F auid!=4294967295 -k privileged-pam -a always,exit -F path=/sbin/pam_tally2 -F perm=wxa -F auid>=1000 -F auid!=4294967295 -k privileged-pam' + elif [ $FNRET = 0 ]; then +AUDIT_PARAMS='-a always,exit -F path=/usr/sbin/faillock -F perm=wxa -F auid>=1000 -F auid!=4294967295 -k privileged-pam' + fi fi } diff --git a/lib/utils.sh b/lib/utils.sh index 1105daf..8cbb6ba 100644 --- a/lib/utils.sh +++ b/lib/utils.sh @@ -98,6 +98,22 @@ is_debian_10() fi } +is_debian_11() +{ + if [ -r /etc/debian_version ]; then + if $(cat /etc/debian_version | grep -q "^11.[0-9]"); then + debug "Debian version is 11." + FNRET=0 + else + debug "Debian version is not 11." + FNRET=1 + fi + else + debug "Current OS is not Debian." + FNRET=2 + fi +} + is_64bit_arch() { if $(uname -m | grep -q "64"); then From 79670bde38a782613c58adda03579c834df1f6da Mon Sep 17 00:00:00 2001 From: Samson-W Date: Mon, 16 Aug 2021 02:14:00 +0800 Subject: [PATCH 2/2] Fix bug: Replaced pam_tally2 with pam_faillock in debian 11. --- bin/hardening/9.2.11_pam_deny_times_tally2.sh | 118 ++++++++++++++++-- .../9.2.12_pam_lockout_failed_tally2.sh | 112 +++++++++++++++-- .../9.2.13_pam_even_deny_root_tally2.sh | 105 ++++++++++++++-- lib/utils.sh | 25 ++++ 4 files changed, 331 insertions(+), 29 deletions(-) diff --git a/bin/hardening/9.2.11_pam_deny_times_tally2.sh b/bin/hardening/9.2.11_pam_deny_times_tally2.sh index 6ee3500..bed0969 100755 --- a/bin/hardening/9.2.11_pam_deny_times_tally2.sh +++ b/bin/hardening/9.2.11_pam_deny_times_tally2.sh @@ -6,6 +6,7 @@ # # 9.2.11 Set deny times for Password Attempts (Scored) +# Replaced pam_tally2 with pam_faillock in debian 11 # The number in the original document is 9.2.2 # for login and ssh service # Author : Samson wen, Samson @@ -17,30 +18,27 @@ set -u # One variable unset, it's over HARDENING_LEVEL=3 PACKAGE='libpam-modules-bin' -PAMLIBNAME='pam_tally2.so' -AUTHPATTERN='^auth[[:space:]]*required[[:space:]]*pam_tally2.so' AUTHFILE='/etc/pam.d/common-auth' -AUTHRULE='auth required pam_tally2.so deny=3 even_deny_root unlock_time=900' ADDPATTERNLINE='# pam-auth-update(8) for details.' DENYOPTION='deny' DENY_VAL=3 # This function will be called if the script status is on enabled / audit mode -audit () { +audit_before11 () { is_pkg_installed $PACKAGE if [ $FNRET != 0 ]; then crit "$PACKAGE is not installed!" - FNRET=1 + FNRET=11 else ok "$PACKAGE is installed" does_pattern_exist_in_file $AUTHFILE $AUTHPATTERN if [ $FNRET = 0 ]; then ok "$AUTHPATTERN is present in $AUTHFILE." - check_param_pair_by_pam $AUTHFILE $PAMLIBNAME $DENYOPTION le $DENY_VAL + check_param_pair_by_pam $AUTHFILE $PAMLIBNAME $DENYOPTION le $DENY_VAL if [ $FNRET = 0 ]; then - ok "$DENYOPTION set condition is less-than-or-equal-to $DENY_VAL" + ok "$DENYOPTION set condition is less-than-or-equal-to $DENY_VAL" else - crit "$DENYOPTION set condition is not $DENY_VAL" + crit "$DENYOPTION set condition is not $DENY_VAL" fi else crit "$AUTHPATTERN is not present in $AUTHFILE" @@ -49,11 +47,45 @@ audit () { fi } -# This function will be called if the script status is on enabled mode -apply () { +audit_debian11 () { + is_pkg_installed $PACKAGE + if [ $FNRET != 0 ]; then + crit "$PACKAGE is not installed!" + FNRET=11 + else + ok "$PACKAGE is installed" + does_pattern_exist_in_file $AUTHFILE $AUTHPATTERN + if [ $FNRET = 0 ]; then + ok "$AUTHPATTERN is present in $AUTHFILE." + check_param_pair_by_value $SECCONFFILE $DENYOPTION le $DENY_VAL + if [ $FNRET = 0 ]; then + ok "Option $DENYOPTION set condition is less than or equal to $DENY_VAL in $SECCONFFILE" + elif [ $FNRET = 1 ]; then + crit "Option $DENYOPTION set condition is greater than $DENY_VAL in $SECCONFFILE" + elif [ $FNRET = 2 ]; then + crit "Option $DENYOPTION is not conf in $SECCONFFILE" + elif [ $FNRET = 3 ]; then + crit "Config file $SECCONFFILE is not exist!" + fi + else + crit "$AUTHPATTERN is not present in $AUTHFILE" + FNRET=12 + fi + fi +} + +audit () { + if [ $ISDEBIAN11 = 1 ]; then + audit_debian11 + else + audit_before11 + fi +} + +apply_before11 () { if [ $FNRET = 0 ]; then ok "$DENYOPTION set condition is less-than-or-equal-to $DENY_VAL" - elif [ $FNRET = 1 ]; then + elif [ $FNRET = 11 ]; then warn "Apply:$PACKAGE is absent, installing it" install_package $PACKAGE elif [ $FNRET = 2 ]; then @@ -74,6 +106,56 @@ apply () { fi } +# Input: +# Param1: return-value of call check_param_pair_by_value +# Function: Perform corresponding repair actions based on the return value of the error. +apply_secconffile() { + FNRET=$1 + if [ $FNRET = 0 ]; then + ok "Option $DENYOPTION set condition is less than or equal to $DENY_VAL in $SECCONFFILE" + elif [ $FNRET = 1 ]; then + warn "Reset option $DENYOPTION to $DENY_VAL in $SECCONFFILE" + replace_in_file $SECCONFFILE "^$DENYOPTION.*" "$DENYOPTION = $DENY_VAL" + elif [ $FNRET = 2 ]; then + warn "$DENYOPTION is not conf, add to $SECCONFFILE" + add_end_of_file $SECCONFFILE "$DENYOPTION = $DENY_VAL" + elif [ $FNRET = 3 ]; then + warn "Config file $SECCONFFILE is not exist! Please check it by youself" + else + warn "This param $FNRET was not defined!!!" + fi +} + +apply_debian11 () { + if [ $FNRET = 0 ]; then + ok "$DENYOPTION set condition is less than or equal to $DENY_VAL in $SECCONFFILE" + elif [ $FNRET = 11 ]; then + warn "Apply:$PACKAGE is absent, installing it" + install_package $PACKAGE + does_pattern_exist_in_file $AUTHFILE $AUTHPATTERN + if [ $FNRET != 0 ]; then + add_line_file_after_pattern "$AUTHFILE" "$AUTHRULE" "$ADDPATTERNLINE" + check_param_pair_by_value $SECCONFFILE $DENYOPTION le $DENY_VAL + apply_secconffile $FNRET + fi + elif [ $FNRET = 12 ]; then + add_line_file_after_pattern "$AUTHFILE" "$AUTHRULE" "$ADDPATTERNLINE" + check_param_pair_by_value $SECCONFFILE $DENYOPTION le $DENY_VAL + apply_secconffile $FNRET + else + apply_secconffile $FNRET + fi +} + +# This function will be called if the script status is on enabled mode +apply () { + if [ $ISDEBIAN11 = 1 ]; then + apply_debian11 + else + apply_before11 + fi +} + # This function will check config parameters required check_config() { if [ $OS_RELEASE -eq 2 ]; then @@ -84,7 +166,19 @@ check_config() { AUTHRULE='auth required pam_failloc.so deny=3 even_deny_root unlock_time=900' ADDPATTERNLINE='auth[[:space:]]*required' else - : + is_debian_11 + # faillock for Debian 11 + if [ $FNRET = 0 ]; then + ISDEBIAN11=1 + SECCONFFILE='/etc/security/faillock.conf' + AUTHPATTERN='^auth[[:space:]]*required[[:space:]]*pam_faillock.so' + AUTHRULE='auth required pam_faillock.so' + else + ISDEBIAN11=0 + PAMLIBNAME='pam_tally2.so' + AUTHPATTERN='^auth[[:space:]]*required[[:space:]]*pam_tally2.so' + AUTHRULE='auth required pam_tally2.so deny=3 even_deny_root unlock_time=900' + fi fi } diff --git a/bin/hardening/9.2.12_pam_lockout_failed_tally2.sh b/bin/hardening/9.2.12_pam_lockout_failed_tally2.sh index 15c42a8..2eb44a3 100755 --- a/bin/hardening/9.2.12_pam_lockout_failed_tally2.sh +++ b/bin/hardening/9.2.12_pam_lockout_failed_tally2.sh @@ -6,6 +6,7 @@ # # 9.2.12 Set Lockout for Failed Password Attempts (Scored) +# Replaced pam_tally2 with pam_faillock in debian 11 # for login and ssh service # @@ -15,20 +16,17 @@ set -u # One variable unset, it's over HARDENING_LEVEL=3 PACKAGE='libpam-modules-bin' -PAMLIBNAME='pam_tally2.so' -AUTHPATTERN='^auth[[:space:]]*required[[:space:]]*pam_tally2.so' AUTHFILE='/etc/pam.d/common-auth' -AUTHRULE='auth required pam_tally2.so deny=3 even_deny_root unlock_time=900' ADDPATTERNLINE='# pam-auth-update(8) for details.' UNLOCKOPTION='unlock_time' UNLOCK_VAL=900 # This function will be called if the script status is on enabled / audit mode -audit () { +audit_before11 () { is_pkg_installed $PACKAGE if [ $FNRET != 0 ]; then crit "$PACKAGE is not installed!" - FNRET=1 + FNRET=11 else ok "$PACKAGE is installed" does_pattern_exist_in_file $AUTHFILE $AUTHPATTERN @@ -47,15 +45,49 @@ audit () { fi } -# This function will be called if the script status is on enabled mode -apply () { +audit_debian11 () { + is_pkg_installed $PACKAGE + if [ $FNRET != 0 ]; then + crit "$PACKAGE is not installed!" + FNRET=11 + else + ok "$PACKAGE is installed" + does_pattern_exist_in_file $AUTHFILE $AUTHPATTERN + if [ $FNRET = 0 ]; then + ok "$AUTHPATTERN is present in $AUTHFILE." + check_param_pair_by_value $SECCONFFILE $UNLOCKOPTION le $UNLOCK_VAL + if [ $FNRET = 0 ]; then + ok "Option $UNLOCKOPTION set condition is less than or equal to $UNLOCK_VAL in $SECCONFFILE" + elif [ $FNRET = 1 ]; then + crit "Option $UNLOCKOPTION set condition is greater than $UNLOCK_VAL in $SECCONFFILE" + elif [ $FNRET = 2 ]; then + crit "Option $UNLOCKOPTION is not conf in $SECCONFFILE" + elif [ $FNRET = 3 ]; then + crit "Config file $SECCONFFILE is not exist!" + fi + else + crit "$AUTHPATTERN is not present in $AUTHFILE" + FNRET=12 + fi + fi +} + +audit () { + if [ $ISDEBIAN11 = 1 ]; then + audit_debian11 + else + audit_before11 + fi +} + +apply_before11 () { if [ $FNRET = 0 ]; then ok "$UNLOCKOPTION set condition is greater-than-or-equal-to $UNLOCK_VAL" elif [ $FNRET = 1 ]; then warn "Apply:$PACKAGE is absent, installing it" install_package $PACKAGE elif [ $FNRET = 2 ]; then - warn "Apply:$AUTHPATTERN is not present in $AUTHFILE" + warn "Apply:$AUTHPATTERN is not present in $AUTHFILE" if [ $OS_RELEASE -eq 2 ]; then add_line_file_after_pattern_lastline "$AUTHFILE" "$AUTHRULE" "$ADDPATTERNLINE" else @@ -72,6 +104,56 @@ apply () { fi } +# Input: +# Param1: return-value of call check_param_pair_by_value +# Function: Perform corresponding repair actions based on the return value of the error. +apply_secconffile() { + FNRET=$1 + if [ $FNRET = 0 ]; then + ok "Option $UNLOCKOPTION set condition is less than or equal to $UNLOCK_VAL in $SECCONFFILE" + elif [ $FNRET = 1 ]; then + warn "Reset option $UNLOCKOPTION to $UNLOCK_VAL in $SECCONFFILE" + replace_in_file $SECCONFFILE "^$UNLOCKOPTION.*" "$UNLOCKOPTION = $UNLOCK_VAL" + elif [ $FNRET = 2 ]; then + warn "$UNLOCKOPTION is not conf, add to $SECCONFFILE" + add_end_of_file $SECCONFFILE "$UNLOCKOPTION = $UNLOCK_VAL" + elif [ $FNRET = 3 ]; then + warn "Config file $SECCONFFILE is not exist! Please check it by youself" + else + warn "This param $FNRET was not defined!!!" + fi +} + +apply_debian11 () { + if [ $FNRET = 0 ]; then + ok "$UNLOCKOPTION set condition is less than or equal to $UNLOCK_VAL in $SECCONFFILE" + elif [ $FNRET = 11 ]; then + warn "Apply:$PACKAGE is absent, installing it" + install_package $PACKAGE + does_pattern_exist_in_file $AUTHFILE $AUTHPATTERN + if [ $FNRET != 0 ]; then + add_line_file_after_pattern "$AUTHFILE" "$AUTHRULE" "$ADDPATTERNLINE" + check_param_pair_by_value $SECCONFFILE $UNLOCKOPTION le $UNLOCK_VAL + apply_secconffile $FNRET + fi + elif [ $FNRET = 12 ]; then + add_line_file_after_pattern "$AUTHFILE" "$AUTHRULE" "$ADDPATTERNLINE" + check_param_pair_by_value $SECCONFFILE $UNLOCKOPTION le $UNLOCK_VAL + apply_secconffile $FNRET + else + apply_secconffile $FNRET + fi +} + +# This function will be called if the script status is on enabled mode +apply () { + if [ $ISDEBIAN11 = 1 ]; then + apply_debian11 + else + apply_before11 + fi +} + # This function will check config parameters required check_config() { if [ $OS_RELEASE -eq 2 ]; then @@ -82,7 +164,19 @@ check_config() { AUTHRULE='auth required pam_failloc.so deny=3 even_deny_root unlock_time=900' ADDPATTERNLINE='auth[[:space:]]*required' else - : + is_debian_11 + # faillock for Debian 11 + if [ $FNRET = 0 ]; then + ISDEBIAN11=1 + SECCONFFILE='/etc/security/faillock.conf' + AUTHPATTERN='^auth[[:space:]]*required[[:space:]]*pam_faillock.so' + AUTHRULE='auth required pam_faillock.so' + else + ISDEBIAN11=0 + PAMLIBNAME='pam_tally2.so' + AUTHPATTERN='^auth[[:space:]]*required[[:space:]]*pam_tally2.so' + AUTHRULE='auth required pam_tally2.so deny=3 even_deny_root unlock_time=900' + fi fi } diff --git a/bin/hardening/9.2.13_pam_even_deny_root_tally2.sh b/bin/hardening/9.2.13_pam_even_deny_root_tally2.sh index 9cb465d..a67dc68 100755 --- a/bin/hardening/9.2.13_pam_even_deny_root_tally2.sh +++ b/bin/hardening/9.2.13_pam_even_deny_root_tally2.sh @@ -5,7 +5,8 @@ # # -# 9.2.17 Ensure unsuccessful root logon occur the associated account must be locked. (Scored) +# 9.2.13 Ensure unsuccessful root logon occur the associated account must be locked. (Scored) +# Replaced pam_tally2 with pam_faillock in debian 11 # Author : Samson wen, Samson # for login and ssh service # @@ -16,15 +17,12 @@ set -u # One variable unset, it's over HARDENING_LEVEL=3 PACKAGE='libpam-modules-bin' -PAMLIBNAME='pam_tally2.so' -AUTHPATTERN='^auth[[:space:]]*required[[:space:]]*pam_tally2.so' AUTHFILE='/etc/pam.d/common-auth' -AUTHRULE='auth required pam_tally2.so deny=3 even_deny_root unlock_time=900' ADDPATTERNLINE='# pam-auth-update(8) for details.' DENYROOT='even_deny_root' # This function will be called if the script status is on enabled / audit mode -audit () { +audit_before11 () { is_pkg_installed $PACKAGE if [ $FNRET != 0 ]; then crit "$PACKAGE is not installed!" @@ -47,8 +45,40 @@ audit () { fi } -# This function will be called if the script status is on enabled mode -apply () { +audit_debian11 () { + is_pkg_installed $PACKAGE + if [ $FNRET != 0 ]; then + crit "$PACKAGE is not installed!" + FNRET=11 + else + ok "$PACKAGE is installed" + does_pattern_exist_in_file $AUTHFILE $AUTHPATTERN + if [ $FNRET = 0 ]; then + ok "$AUTHPATTERN is present in $AUTHFILE." + check_no_param_option_by_value $SECCONFFILE $DENYROOT + if [ $FNRET = 0 ]; then + ok "Option $DENYROOT is conf in $SECCONFFILE" + elif [ $FNRET = 1 ]; then + crit "Config file $SECCONFFILE is not exist!" + elif [ $FNRET = 2 ]; then + crit "Option $DENYROOT is not conf in $SECCONFFILE" + fi + else + crit "$AUTHPATTERN is not present in $AUTHFILE" + FNRET=12 + fi + fi +} + +audit () { + if [ $ISDEBIAN11 = 1 ]; then + audit_debian11 + else + audit_before11 + fi +} + +apply_before11 () { if [ $FNRET = 0 ]; then ok "$DENYROOT is already configured" elif [ $FNRET = 1 ]; then @@ -69,6 +99,53 @@ apply () { fi } +# Input: +# Param1: return-value of call check_no_param_option_by_value +# Function: Perform corresponding repair actions based on the return value of the error. +apply_secconffile() { + FNRET=$1 + if [ $FNRET = 0 ]; then + ok "Option $DENYROOT is conf in $SECCONFFILE" + elif [ $FNRET = 1 ]; then + warn "Config file $SECCONFFILE is not exist! Please check it by youself" + elif [ $FNRET = 2 ]; then + warn "Option $DENYROOT is not conf in $SECCONFFILE, add it " + add_end_of_file $SECCONFFILE "$DENYROOT" + else + warn "This param $FNRET was not defined!!!" + fi +} + +apply_debian11 () { + if [ $FNRET = 0 ]; then + ok "Option $DENYROOT is conf in $SECCONFFILE" + elif [ $FNRET = 11 ]; then + warn "Apply:$PACKAGE is absent, installing it" + install_package $PACKAGE + does_pattern_exist_in_file $AUTHFILE $AUTHPATTERN + if [ $FNRET != 0 ]; then + add_line_file_after_pattern "$AUTHFILE" "$AUTHRULE" "$ADDPATTERNLINE" + check_no_param_option_by_value $SECCONFFILE $DENYROOT + apply_secconffile $FNRET + fi + elif [ $FNRET = 12 ]; then + add_line_file_after_pattern "$AUTHFILE" "$AUTHRULE" "$ADDPATTERNLINE" + check_no_param_option_by_value $SECCONFFILE $DENYROOT + apply_secconffile $FNRET + else + apply_secconffile $FNRET + fi +} + +# This function will be called if the script status is on enabled mode +apply () { + if [ $ISDEBIAN11 = 1 ]; then + apply_debian11 + else + apply_before11 + fi +} + # This function will check config parameters required check_config() { if [ $OS_RELEASE -eq 2 ]; then @@ -80,7 +157,19 @@ check_config() { ADDPATTERNLINE='auth[[:space:]]*required' DENYROOT='even_deny_root' else - : + is_debian_11 + # faillock for Debian 11 + if [ $FNRET = 0 ]; then + ISDEBIAN11=1 + SECCONFFILE='/etc/security/faillock.conf' + AUTHPATTERN='^auth[[:space:]]*required[[:space:]]*pam_faillock.so' + AUTHRULE='auth required pam_faillock.so' + else + ISDEBIAN11=0 + PAMLIBNAME='pam_tally2.so' + AUTHPATTERN='^auth[[:space:]]*required[[:space:]]*pam_tally2.so' + AUTHRULE='auth required pam_tally2.so deny=3 even_deny_root unlock_time=900' + fi fi } diff --git a/lib/utils.sh b/lib/utils.sh index 8cbb6ba..2bbdd75 100644 --- a/lib/utils.sh +++ b/lib/utils.sh @@ -768,6 +768,31 @@ check_param_pair_by_value () fi } +# Only check option name +check_no_param_option_by_value() +{ + LOCATION=$1 + OPTION=$2 + + #Example: + #LOCATION="/etc/security/faillock.conf" + #OPTION="even_deny_root" + + if [ -f "$LOCATION" ];then + RESULT=$(sed -e '/^#/d' -e '/^[ \t][ \t]*#/d' -e 's/#.*$//' -e '/^$/d' $LOCATION | grep "$OPTION" | wc -l) + if [ "$RESULT" -eq 1 ]; then + debug "$OPTION is conf" + FNRET=0 + else + debug "$OPTION is not conf" + FNRET=2 + fi + else + debug "$LOCATION is not exist" + FNRET=1 + fi +} + check_param_pair_by_pam() { LOCATION=$1