contains 35 rules |
System Settings
[ref]groupContains rules that check correct system settings. |
contains 21 rules |
Installing and Maintaining Software
[ref]groupThe following sections contain information on
security-relevant choices during the initial operating system
installation process and the setup of software
updates. |
contains 1 rule |
Updating Software
[ref]groupThe apt_get command line tool is used to install and
update software packages. The system also provides a graphical
software update tool in the System menu, in the Administration submenu,
called Software Update.
Debian 12 systems contain an installed software catalog called
the RPM database, which records metadata of installed packages. Consistently using
apt_get or the graphical Software Update for all software installation
allows for insight into the current inventory of installed software on the system.
|
contains 1 rule |
Ensure Software Patches Installed
[ref]rule
If the system has an apt repository available, run the following command to install updates:
$ apt update && apt full-upgrade
NOTE: U.S. Defense systems are required to be patched within 30 days or sooner as local policy
dictates.Warning:
The OVAL feed of Debian 12 is not a XML file, which may not be understood by all scanners. Rationale:Installing software updates is a fundamental mitigation against
the exploitation of publicly-known vulnerabilities. If the most
recent security patches and updates are not installed, unauthorized
users may take advantage of weaknesses in the unpatched software. The
lack of prompt attention to patching could result in a system compromise. References:
R61, 18, 20, 4, 5.10.4.1, APO12.01, APO12.02, APO12.03, APO12.04, BAI03.10, DSS05.01, DSS05.02, CCI-000366, 4.2.3, 4.2.3.12, 4.2.3.7, 4.2.3.9, A.12.6.1, A.14.2.3, A.16.1.3, A.18.2.2, A.18.2.3, SI-2(5), SI-2(c), CM-6(a), ID.RA-1, PR.IP-12, FMT_MOF_EXT.1, Req-6.2, 6.3.3, 6.3, SRG-OS-000480-GPOS-00227 |
Account and Access Control
[ref]groupIn traditional Unix security, if an attacker gains
shell access to a certain login account, they can perform any action
or access any file to which that account has access. Therefore,
making it more difficult for unauthorized people to gain shell
access to accounts, particularly to privileged accounts, is a
necessary part of securing a system. This section introduces
mechanisms for restricting access to accounts under
Debian 12. |
contains 15 rules |
Protect Accounts by Configuring PAM
[ref]groupPAM, or Pluggable Authentication Modules, is a system
which implements modular authentication for Linux programs. PAM provides
a flexible and configurable architecture for authentication, and it should be configured
to minimize exposure to unnecessary risk. This section contains
guidance on how to accomplish that.
PAM is implemented as a set of shared objects which are
loaded and invoked whenever an application wishes to authenticate a
user. Typically, the application must be running as root in order
to take advantage of PAM, because PAM's modules often need to be able
to access sensitive stores of account information, such as /etc/shadow.
Traditional privileged network listeners
(e.g. sshd) or SUID programs (e.g. sudo) already meet this
requirement. An SUID root application, userhelper, is provided so
that programs which are not SUID or privileged themselves can still
take advantage of PAM.
PAM looks in the directory /etc/pam.d for
application-specific configuration information. For instance, if
the program login attempts to authenticate a user, then PAM's
libraries follow the instructions in the file /etc/pam.d/login
to determine what actions should be taken.
One very important file in /etc/pam.d is
/etc/pam.d/system-auth . This file, which is included by
many other PAM configuration files, defines 'default' system authentication
measures. Modifying this file is a good way to make far-reaching
authentication changes, for instance when implementing a
centralized authentication service. Warning:
Be careful when making changes to PAM's configuration files.
The syntax for these files is complex, and modifications can
have unexpected consequences. The default configurations shipped
with applications should be sufficient for most users. |
contains 13 rules |
Set Lockouts for Failed Password Attempts
[ref]groupThe pam_faillock PAM module provides the capability to
lock out user accounts after a number of failed login attempts. Its
documentation is available in
/usr/share/doc/pam-VERSION/txts/README.pam_faillock .
Warning:
Locking out user accounts presents the
risk of a denial-of-service attack. The lockout policy
must weigh whether the risk of such a
denial-of-service attack outweighs the benefits of thwarting
password guessing attacks. |
contains 4 rules |
Limit Password Reuse
[ref]ruleDo not allow users to reuse recent passwords. This can be accomplished by using the
remember option for the pam_unix or pam_pwhistory PAM modules. Warning:
If the system relies on authselect tool to manage PAM settings, the remediation
will also use authselect tool. However, if any manual modification was made in
PAM files, the authselect integrity check will fail and the remediation will be
aborted in order to preserve intentional changes. In this case, an informative message will
be shown in the remediation report. Warning:
Newer versions of authselect contain an authselect feature to easily and properly
enable pam_pwhistory.so module. If this feature is not yet available in your
system, an authselect custom profile must be used to avoid integrity issues in PAM files. Rationale:Preventing re-use of previous passwords helps ensure that a compromised password is not
re-used by a user. References:
R31, 1, 12, 15, 16, 5, 5.6.2.1.1, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, 3.5.8, CCI-000200, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(f), IA-5(1)(e), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.2.5, 8.3.7, 8.3, SRG-OS-000077-GPOS-00045 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | medium |
---|
Reboot: | false |
---|
Strategy: | configure |
---|
- name: Gather the package facts
package_facts:
manager: auto
tags:
- CJIS-5.6.2.1.1
- NIST-800-171-3.5.8
- NIST-800-53-IA-5(1)(e)
- NIST-800-53-IA-5(f)
- PCI-DSS-Req-8.2.5
- PCI-DSSv4-8.3
- PCI-DSSv4-8.3.7
- accounts_password_pam_unix_remember
- configure_strategy
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- name: XCCDF Value var_password_pam_unix_remember # promote to variable
set_fact:
var_password_pam_unix_remember: !!str 2
tags:
- always
- name: Limit Password Reuse - Check if the required PAM module option is present
in /etc/pam.d/common-password
ansible.builtin.lineinfile:
path: /etc/pam.d/common-password
regexp: ^\s*password\s+\[success=[A-Za-z0-9].*\]\s+pam_unix.so\s*.*\sremember\b
state: absent
check_mode: true
changed_when: false
register: result_pam_module_remember_option_present
when: '"libpam-runtime" in ansible_facts.packages'
tags:
- CJIS-5.6.2.1.1
- NIST-800-171-3.5.8
- NIST-800-53-IA-5(1)(e)
- NIST-800-53-IA-5(f)
- PCI-DSS-Req-8.2.5
- PCI-DSSv4-8.3
- PCI-DSSv4-8.3.7
- accounts_password_pam_unix_remember
- configure_strategy
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- name: Limit Password Reuse - Ensure the "remember" PAM option for "pam_unix.so"
is included in /etc/pam.d/common-password
ansible.builtin.lineinfile:
path: /etc/pam.d/common-password
backrefs: true
regexp: ^(\s*password\s+\[success=[A-Za-z0-9].*\]\s+pam_unix.so.*)
line: \1 remember={{ var_password_pam_unix_remember }}
state: present
register: result_pam_remember_add
when:
- '"libpam-runtime" in ansible_facts.packages'
- result_pam_module_remember_option_present.found == 0
tags:
- CJIS-5.6.2.1.1
- NIST-800-171-3.5.8
- NIST-800-53-IA-5(1)(e)
- NIST-800-53-IA-5(f)
- PCI-DSS-Req-8.2.5
- PCI-DSSv4-8.3
- PCI-DSSv4-8.3.7
- accounts_password_pam_unix_remember
- configure_strategy
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- name: Limit Password Reuse - Ensure the required value for "remember" PAM option
from "pam_unix.so" in /etc/pam.d/common-password
ansible.builtin.lineinfile:
path: /etc/pam.d/common-password
backrefs: true
regexp: ^(\s*password\s+\[success=[A-Za-z0-9].*\]\s+pam_unix.so\s+.*)(remember)=[0-9a-zA-Z]+\s*(.*)
line: \1\2={{ var_password_pam_unix_remember }} \3
register: result_pam_remember_edit
when:
- '"libpam-runtime" in ansible_facts.packages'
- result_pam_module_remember_option_present.found > 0
tags:
- CJIS-5.6.2.1.1
- NIST-800-171-3.5.8
- NIST-800-53-IA-5(1)(e)
- NIST-800-53-IA-5(f)
- PCI-DSS-Req-8.2.5
- PCI-DSSv4-8.3
- PCI-DSSv4-8.3.7
- accounts_password_pam_unix_remember
- configure_strategy
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
Remediation Shell script: (show)
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_password_pam_unix_remember='2'
if [ -e "/etc/pam.d/common-password" ] ; then
valueRegex="$var_password_pam_unix_remember" defaultValue="$var_password_pam_unix_remember"
# non-empty values need to be preceded by an equals sign
[ -n "${valueRegex}" ] && valueRegex="=${valueRegex}"
# add an equals sign to non-empty values
[ -n "${defaultValue}" ] && defaultValue="=${defaultValue}"
# fix 'type' if it's wrong
if grep -q -P "^\\s*(?"'!'"password\\s)[[:alnum:]]+\\s+[[:alnum:]]+\\s+pam_unix.so" < "/etc/pam.d/common-password" ; then
sed --follow-symlinks -i -E -e "s/^(\\s*)[[:alnum:]]+(\\s+[[:alnum:]]+\\s+pam_unix.so)/\\1password\\2/" "/etc/pam.d/common-password"
fi
# fix 'control' if it's wrong
if grep -q -P "^\\s*password\\s+(?"'!'"\[success=[[:alnum:]].*\])[[:alnum:]]+\\s+pam_unix.so" < "/etc/pam.d/common-password" ; then
sed --follow-symlinks -i -E -e "s/^(\\s*password\\s+)[[:alnum:]]+(\\s+pam_unix.so)/\\1\[success=[[:alnum:]].*\]\\2/" "/etc/pam.d/common-password"
fi
# fix the value for 'option' if one exists but does not match 'valueRegex'
if grep -q -P "^\\s*password\\s+\[success=[[:alnum:]].*\]\\s+pam_unix.so(\\s.+)?\\s+remember(?"'!'"${valueRegex}(\\s|\$))" < "/etc/pam.d/common-password" ; then
sed --follow-symlinks -i -E -e "s/^(\\s*password\\s+\[success=[[:alnum:]].*\]\\s+pam_unix.so(\\s.+)?\\s)remember=[^[:space:]]*/\\1remember${defaultValue}/" "/etc/pam.d/common-password"
# add 'option=default' if option is not set
elif grep -q -E "^\\s*password\\s+\[success=[[:alnum:]].*\]\\s+pam_unix.so" < "/etc/pam.d/common-password" &&
grep -E "^\\s*password\\s+\[success=[[:alnum:]].*\]\\s+pam_unix.so" < "/etc/pam.d/common-password" | grep -q -E -v "\\sremember(=|\\s|\$)" ; then
sed --follow-symlinks -i -E -e "s/^(\\s*password\\s+\[success=[[:alnum:]].*\]\\s+pam_unix.so[^\\n]*)/\\1 remember${defaultValue}/" "/etc/pam.d/common-password"
# add a new entry if none exists
elif ! grep -q -P "^\\s*password\\s+\[success=[[:alnum:]].*\]\\s+pam_unix.so(\\s.+)?\\s+remember${valueRegex}(\\s|\$)" < "/etc/pam.d/common-password" ; then
echo "password \[success=[[:alnum:]].*\] pam_unix.so remember${defaultValue}" >> "/etc/pam.d/common-password"
fi
else
echo "/etc/pam.d/common-password doesn't exist" >&2
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Lock Accounts After Failed Password Attempts
[ref]ruleThis rule configures the system to lock out accounts after a number of incorrect login attempts
using pam_faillock.so .
pam_faillock.so module requires multiple entries in pam files. These entries must be carefully
defined to work as expected.
Ensure that the file /etc/security/faillock.conf contains the following entry:
deny = <count>
Where count should be less than or equal to
3 and greater than 0. Warning:
If the system relies on authselect tool to manage PAM settings, the remediation
will also use authselect tool. However, if any manual modification was made in
PAM files, the authselect integrity check will fail and the remediation will be
aborted in order to preserve intentional changes. In this case, an informative message will
be shown in the remediation report.
If the system supports the /etc/security/faillock.conf file, the pam_faillock
parameters should be defined in faillock.conf file. Rationale:By limiting the number of failed logon attempts, the risk of unauthorized system access via
user password guessing, also known as brute-forcing, is reduced. Limits are imposed by locking
the account. References:
R31, 1, 12, 15, 16, 5.5.3, DSS05.04, DSS05.10, DSS06.10, 3.1.8, CCI-000044, CCI-002238, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9, 0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561, A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3, CM-6(a), AC-7(a), PR.AC-7, FIA_AFL.1, Req-8.1.6, 8.3.4, 8.3, SRG-OS-000329-GPOS-00128, SRG-OS-000021-GPOS-00005 Remediation Shell script: (show)
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_accounts_passwords_pam_faillock_deny='3'
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
authselect enable-feature with-faillock
authselect apply-changes -b
else
pam_file="/etc/pam.d/common-auth"
if ! grep -qE '^\s*auth\s+required\s+pam_faillock\.so\s+preauth.*$' "$pam_file" ; then
# insert at the top
sed -i --follow-symlinks '/^# here are the per-package modules/i auth required pam_faillock.so preauth' "$pam_file"
fi
if ! grep -qE '^\s*auth\s+\[default=die\]\s+pam_faillock\.so\s+authfail.*$' "$pam_file" ; then
num_lines=$(sed -n 's/^\s*auth.*success=\([1-9]\).*pam_unix\.so.*/\1/p' "$pam_file")
if [ ! -z "$num_lines" ]; then
# Add pam_faillock (authfail) module below pam_unix, skipping N-1 lines, where N is
# the number of jumps in the pam_unix success=N statement. Ignore commented and empty lines.
append_position=$(cat -n "${pam_file}" \
| grep -P "^\s+\d+\s+auth\s+.*$" \
| grep -w "pam_unix.so" -A $(( num_lines - 1 )) \
| tail -n 1 | cut -f 1 | tr -d ' '
)
sed -i --follow-symlinks ''${append_position}'a auth [default=die] pam_faillock.so authfail' "$pam_file"
else
sed -i --follow-symlinks '/^auth.*pam_unix\.so.*/a auth [default=die] pam_faillock.so authfail' "$pam_file"
fi
fi
if ! grep -qE '^\s*auth\s+sufficient\s+pam_faillock\.so\s+authsucc.*$' "$pam_file" ; then
sed -i --follow-symlinks '/^auth.*pam_faillock\.so.*authfail.*/a auth sufficient pam_faillock.so authsucc' "$pam_file"
fi
pam_file="/etc/pam.d/common-account"
if ! grep -qE '^\s*account\s+required\s+pam_faillock\.so.*$' "$pam_file" ; then
echo 'account required pam_faillock.so' >> "$pam_file"
fi
fi
AUTH_FILES=("/etc/pam.d/system-auth" "/etc/pam.d/password-auth")
SKIP_FAILLOCK_CHECK=false
FAILLOCK_CONF="/etc/security/faillock.conf"
if [ -f $FAILLOCK_CONF ] || [ "$SKIP_FAILLOCK_CHECK" = "true" ]; then
regex="^\s*deny\s*="
line="deny = $var_accounts_passwords_pam_faillock_deny"
if ! grep -q $regex $FAILLOCK_CONF; then
echo $line >> $FAILLOCK_CONF
else
sed -i --follow-symlinks 's|^\s*\(deny\s*=\s*\)\(\S\+\)|\1'"$var_accounts_passwords_pam_faillock_deny"'|g' $FAILLOCK_CONF
fi
for pam_file in "${AUTH_FILES[@]}"
do
if [ -e "$pam_file" ] ; then
PAM_FILE_PATH="$pam_file"
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
CURRENT_PROFILE=$(authselect current -r | awk '{ print $1 }')
# If not already in use, a custom profile is created preserving the enabled features.
if [[ ! $CURRENT_PROFILE == custom/* ]]; then
ENABLED_FEATURES=$(authselect current | tail -n+3 | awk '{ print $2 }')
# The "local" profile does not contain essential security features required by multiple Benchmarks.
# If currently used, it is replaced by "sssd", which is the best option in this case.
if [[ $CURRENT_PROFILE == local ]]; then
CURRENT_PROFILE="sssd"
fi
authselect create-profile hardening -b $CURRENT_PROFILE
CURRENT_PROFILE="custom/hardening"
authselect apply-changes -b --backup=before-hardening-custom-profile
authselect select $CURRENT_PROFILE
for feature in $ENABLED_FEATURES; do
authselect enable-feature $feature;
done
authselect apply-changes -b --backup=after-hardening-custom-profile
fi
PAM_FILE_NAME=$(basename "$pam_file")
PAM_FILE_PATH="/etc/authselect/$CURRENT_PROFILE/$PAM_FILE_NAME"
authselect apply-changes -b
fi
if grep -qP "^\s*auth\s.*\bpam_faillock.so\s.*\bdeny\b" "$PAM_FILE_PATH"; then
sed -i -E --follow-symlinks "s/(.*auth.*pam_faillock.so.*)\bdeny\b=?[[:alnum:]]*(.*)/\1\2/g" "$PAM_FILE_PATH"
fi
if [ -f /usr/bin/authselect ]; then
authselect apply-changes -b
fi
else
echo "$pam_file was not found" >&2
fi
done
else
for pam_file in "${AUTH_FILES[@]}"
do
if ! grep -qE '^\s*auth.*pam_faillock\.so (preauth|authfail).*deny' "$pam_file"; then
sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*preauth.*silent.*/ s/$/ deny='"$var_accounts_passwords_pam_faillock_deny"'/' "$pam_file"
sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*authfail.*/ s/$/ deny='"$var_accounts_passwords_pam_faillock_deny"'/' "$pam_file"
else
sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*preauth.*silent.*\)\('"deny"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_deny"'\3/' "$pam_file"
sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*authfail.*\)\('"deny"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_deny"'\3/' "$pam_file"
fi
done
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Set Interval For Counting Failed Password Attempts
[ref]ruleUtilizing pam_faillock.so , the fail_interval directive configures the system
to lock out an account after a number of incorrect login attempts within a specified time
period.
Ensure that the file /etc/security/faillock.conf contains the following entry:
fail_interval = <interval-in-seconds> where interval-in-seconds is 900 or greater. Warning:
If the system relies on authselect tool to manage PAM settings, the remediation
will also use authselect tool. However, if any manual modification was made in
PAM files, the authselect integrity check will fail and the remediation will be
aborted in order to preserve intentional changes. In this case, an informative message will
be shown in the remediation report.
If the system supports the /etc/security/faillock.conf file, the pam_faillock
parameters should be defined in faillock.conf file. Rationale:By limiting the number of failed logon attempts the risk of unauthorized system
access via user password guessing, otherwise known as brute-forcing, is reduced.
Limits are imposed by locking the account. References:
R31, 1, 12, 15, 16, DSS05.04, DSS05.10, DSS06.10, CCI-000044, CCI-002238, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9, 0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561, A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3, CM-6(a), AC-7(a), PR.AC-7, FIA_AFL.1, SRG-OS-000329-GPOS-00128, SRG-OS-000021-GPOS-00005 Remediation Shell script: (show)
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_accounts_passwords_pam_faillock_fail_interval='900'
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
authselect enable-feature with-faillock
authselect apply-changes -b
else
pam_file="/etc/pam.d/common-auth"
if ! grep -qE '^\s*auth\s+required\s+pam_faillock\.so\s+preauth.*$' "$pam_file" ; then
# insert at the top
sed -i --follow-symlinks '/^# here are the per-package modules/i auth required pam_faillock.so preauth' "$pam_file"
fi
if ! grep -qE '^\s*auth\s+\[default=die\]\s+pam_faillock\.so\s+authfail.*$' "$pam_file" ; then
num_lines=$(sed -n 's/^\s*auth.*success=\([1-9]\).*pam_unix\.so.*/\1/p' "$pam_file")
if [ ! -z "$num_lines" ]; then
# Add pam_faillock (authfail) module below pam_unix, skipping N-1 lines, where N is
# the number of jumps in the pam_unix success=N statement. Ignore commented and empty lines.
append_position=$(cat -n "${pam_file}" \
| grep -P "^\s+\d+\s+auth\s+.*$" \
| grep -w "pam_unix.so" -A $(( num_lines - 1 )) \
| tail -n 1 | cut -f 1 | tr -d ' '
)
sed -i --follow-symlinks ''${append_position}'a auth [default=die] pam_faillock.so authfail' "$pam_file"
else
sed -i --follow-symlinks '/^auth.*pam_unix\.so.*/a auth [default=die] pam_faillock.so authfail' "$pam_file"
fi
fi
if ! grep -qE '^\s*auth\s+sufficient\s+pam_faillock\.so\s+authsucc.*$' "$pam_file" ; then
sed -i --follow-symlinks '/^auth.*pam_faillock\.so.*authfail.*/a auth sufficient pam_faillock.so authsucc' "$pam_file"
fi
pam_file="/etc/pam.d/common-account"
if ! grep -qE '^\s*account\s+required\s+pam_faillock\.so.*$' "$pam_file" ; then
echo 'account required pam_faillock.so' >> "$pam_file"
fi
fi
AUTH_FILES=("/etc/pam.d/system-auth" "/etc/pam.d/password-auth")
SKIP_FAILLOCK_CHECK=false
FAILLOCK_CONF="/etc/security/faillock.conf"
if [ -f $FAILLOCK_CONF ] || [ "$SKIP_FAILLOCK_CHECK" = "true" ]; then
regex="^\s*fail_interval\s*="
line="fail_interval = $var_accounts_passwords_pam_faillock_fail_interval"
if ! grep -q $regex $FAILLOCK_CONF; then
echo $line >> $FAILLOCK_CONF
else
sed -i --follow-symlinks 's|^\s*\(fail_interval\s*=\s*\)\(\S\+\)|\1'"$var_accounts_passwords_pam_faillock_fail_interval"'|g' $FAILLOCK_CONF
fi
for pam_file in "${AUTH_FILES[@]}"
do
if [ -e "$pam_file" ] ; then
PAM_FILE_PATH="$pam_file"
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
CURRENT_PROFILE=$(authselect current -r | awk '{ print $1 }')
# If not already in use, a custom profile is created preserving the enabled features.
if [[ ! $CURRENT_PROFILE == custom/* ]]; then
ENABLED_FEATURES=$(authselect current | tail -n+3 | awk '{ print $2 }')
# The "local" profile does not contain essential security features required by multiple Benchmarks.
# If currently used, it is replaced by "sssd", which is the best option in this case.
if [[ $CURRENT_PROFILE == local ]]; then
CURRENT_PROFILE="sssd"
fi
authselect create-profile hardening -b $CURRENT_PROFILE
CURRENT_PROFILE="custom/hardening"
authselect apply-changes -b --backup=before-hardening-custom-profile
authselect select $CURRENT_PROFILE
for feature in $ENABLED_FEATURES; do
authselect enable-feature $feature;
done
authselect apply-changes -b --backup=after-hardening-custom-profile
fi
PAM_FILE_NAME=$(basename "$pam_file")
PAM_FILE_PATH="/etc/authselect/$CURRENT_PROFILE/$PAM_FILE_NAME"
authselect apply-changes -b
fi
if grep -qP "^\s*auth\s.*\bpam_faillock.so\s.*\bfail_interval\b" "$PAM_FILE_PATH"; then
sed -i -E --follow-symlinks "s/(.*auth.*pam_faillock.so.*)\bfail_interval\b=?[[:alnum:]]*(.*)/\1\2/g" "$PAM_FILE_PATH"
fi
if [ -f /usr/bin/authselect ]; then
authselect apply-changes -b
fi
else
echo "$pam_file was not found" >&2
fi
done
else
for pam_file in "${AUTH_FILES[@]}"
do
if ! grep -qE '^\s*auth.*pam_faillock\.so (preauth|authfail).*fail_interval' "$pam_file"; then
sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*preauth.*silent.*/ s/$/ fail_interval='"$var_accounts_passwords_pam_faillock_fail_interval"'/' "$pam_file"
sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*authfail.*/ s/$/ fail_interval='"$var_accounts_passwords_pam_faillock_fail_interval"'/' "$pam_file"
else
sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*preauth.*silent.*\)\('"fail_interval"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_fail_interval"'\3/' "$pam_file"
sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*authfail.*\)\('"fail_interval"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_fail_interval"'\3/' "$pam_file"
fi
done
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Set Lockout Time for Failed Password Attempts
[ref]ruleThis rule configures the system to lock out accounts during a specified time period after a
number of incorrect login attempts using pam_faillock.so .
Ensure that the file /etc/security/faillock.conf contains the following entry:
unlock_time=<interval-in-seconds> where
interval-in-seconds is 900 or greater.
pam_faillock.so module requires multiple entries in pam files. These entries must be carefully
defined to work as expected. In order to avoid any errors when manually editing these files,
it is recommended to use the appropriate tools, such as authselect or authconfig ,
depending on the OS version.
If unlock_time is set to 0 , manual intervention by an administrator is required
to unlock a user. This should be done using the faillock tool. Warning:
If the system supports the new /etc/security/faillock.conf file but the
pam_faillock.so parameters are defined directly in /etc/pam.d/system-auth and
/etc/pam.d/password-auth , the remediation will migrate the unlock_time parameter
to /etc/security/faillock.conf to ensure compatibility with authselect tool.
The parameters deny and fail_interval , if used, also have to be migrated
by their respective remediation. Warning:
If the system relies on authselect tool to manage PAM settings, the remediation
will also use authselect tool. However, if any manual modification was made in
PAM files, the authselect integrity check will fail and the remediation will be
aborted in order to preserve intentional changes. In this case, an informative message will
be shown in the remediation report.
If the system supports the /etc/security/faillock.conf file, the pam_faillock
parameters should be defined in faillock.conf file. Rationale:By limiting the number of failed logon attempts the risk of unauthorized system
access via user password guessing, otherwise known as brute-forcing, is reduced.
Limits are imposed by locking the account. References:
R31, 1, 12, 15, 16, 5.5.3, DSS05.04, DSS05.10, DSS06.10, 3.1.8, CCI-000044, CCI-002238, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, SR 1.1, SR 1.10, SR 1.2, SR 1.5, SR 1.7, SR 1.8, SR 1.9, 0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561, A.18.1.4, A.9.2.1, A.9.2.4, A.9.3.1, A.9.4.2, A.9.4.3, CM-6(a), AC-7(b), PR.AC-7, FIA_AFL.1, Req-8.1.7, 8.3.4, 8.3, SRG-OS-000329-GPOS-00128, SRG-OS-000021-GPOS-00005 Remediation Shell script: (show)
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_accounts_passwords_pam_faillock_unlock_time='900'
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
authselect enable-feature with-faillock
authselect apply-changes -b
else
pam_file="/etc/pam.d/common-auth"
if ! grep -qE '^\s*auth\s+required\s+pam_faillock\.so\s+preauth.*$' "$pam_file" ; then
# insert at the top
sed -i --follow-symlinks '/^# here are the per-package modules/i auth required pam_faillock.so preauth' "$pam_file"
fi
if ! grep -qE '^\s*auth\s+\[default=die\]\s+pam_faillock\.so\s+authfail.*$' "$pam_file" ; then
num_lines=$(sed -n 's/^\s*auth.*success=\([1-9]\).*pam_unix\.so.*/\1/p' "$pam_file")
if [ ! -z "$num_lines" ]; then
# Add pam_faillock (authfail) module below pam_unix, skipping N-1 lines, where N is
# the number of jumps in the pam_unix success=N statement. Ignore commented and empty lines.
append_position=$(cat -n "${pam_file}" \
| grep -P "^\s+\d+\s+auth\s+.*$" \
| grep -w "pam_unix.so" -A $(( num_lines - 1 )) \
| tail -n 1 | cut -f 1 | tr -d ' '
)
sed -i --follow-symlinks ''${append_position}'a auth [default=die] pam_faillock.so authfail' "$pam_file"
else
sed -i --follow-symlinks '/^auth.*pam_unix\.so.*/a auth [default=die] pam_faillock.so authfail' "$pam_file"
fi
fi
if ! grep -qE '^\s*auth\s+sufficient\s+pam_faillock\.so\s+authsucc.*$' "$pam_file" ; then
sed -i --follow-symlinks '/^auth.*pam_faillock\.so.*authfail.*/a auth sufficient pam_faillock.so authsucc' "$pam_file"
fi
pam_file="/etc/pam.d/common-account"
if ! grep -qE '^\s*account\s+required\s+pam_faillock\.so.*$' "$pam_file" ; then
echo 'account required pam_faillock.so' >> "$pam_file"
fi
fi
AUTH_FILES=("/etc/pam.d/system-auth" "/etc/pam.d/password-auth")
SKIP_FAILLOCK_CHECK=false
FAILLOCK_CONF="/etc/security/faillock.conf"
if [ -f $FAILLOCK_CONF ] || [ "$SKIP_FAILLOCK_CHECK" = "true" ]; then
regex="^\s*unlock_time\s*="
line="unlock_time = $var_accounts_passwords_pam_faillock_unlock_time"
if ! grep -q $regex $FAILLOCK_CONF; then
echo $line >> $FAILLOCK_CONF
else
sed -i --follow-symlinks 's|^\s*\(unlock_time\s*=\s*\)\(\S\+\)|\1'"$var_accounts_passwords_pam_faillock_unlock_time"'|g' $FAILLOCK_CONF
fi
for pam_file in "${AUTH_FILES[@]}"
do
if [ -e "$pam_file" ] ; then
PAM_FILE_PATH="$pam_file"
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
CURRENT_PROFILE=$(authselect current -r | awk '{ print $1 }')
# If not already in use, a custom profile is created preserving the enabled features.
if [[ ! $CURRENT_PROFILE == custom/* ]]; then
ENABLED_FEATURES=$(authselect current | tail -n+3 | awk '{ print $2 }')
# The "local" profile does not contain essential security features required by multiple Benchmarks.
# If currently used, it is replaced by "sssd", which is the best option in this case.
if [[ $CURRENT_PROFILE == local ]]; then
CURRENT_PROFILE="sssd"
fi
authselect create-profile hardening -b $CURRENT_PROFILE
CURRENT_PROFILE="custom/hardening"
authselect apply-changes -b --backup=before-hardening-custom-profile
authselect select $CURRENT_PROFILE
for feature in $ENABLED_FEATURES; do
authselect enable-feature $feature;
done
authselect apply-changes -b --backup=after-hardening-custom-profile
fi
PAM_FILE_NAME=$(basename "$pam_file")
PAM_FILE_PATH="/etc/authselect/$CURRENT_PROFILE/$PAM_FILE_NAME"
authselect apply-changes -b
fi
if grep -qP "^\s*auth\s.*\bpam_faillock.so\s.*\bunlock_time\b" "$PAM_FILE_PATH"; then
sed -i -E --follow-symlinks "s/(.*auth.*pam_faillock.so.*)\bunlock_time\b=?[[:alnum:]]*(.*)/\1\2/g" "$PAM_FILE_PATH"
fi
if [ -f /usr/bin/authselect ]; then
authselect apply-changes -b
fi
else
echo "$pam_file was not found" >&2
fi
done
else
for pam_file in "${AUTH_FILES[@]}"
do
if ! grep -qE '^\s*auth.*pam_faillock\.so (preauth|authfail).*unlock_time' "$pam_file"; then
sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*preauth.*silent.*/ s/$/ unlock_time='"$var_accounts_passwords_pam_faillock_unlock_time"'/' "$pam_file"
sed -i --follow-symlinks '/^auth.*required.*pam_faillock\.so.*authfail.*/ s/$/ unlock_time='"$var_accounts_passwords_pam_faillock_unlock_time"'/' "$pam_file"
else
sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*preauth.*silent.*\)\('"unlock_time"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_unlock_time"'\3/' "$pam_file"
sed -i --follow-symlinks 's/\(^auth.*required.*pam_faillock\.so.*authfail.*\)\('"unlock_time"'=\)[0-9]\+\(.*\)/\1\2'"$var_accounts_passwords_pam_faillock_unlock_time"'\3/' "$pam_file"
fi
done
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Set Password Quality Requirements
[ref]groupThe default pam_pwquality PAM module provides strength
checking for passwords. It performs a number of checks, such as
making sure passwords are not similar to dictionary words, are of
at least a certain length, are not the previous password reversed,
and are not simply a change of case from the previous password. It
can also require passwords to be in certain character classes. The
pam_pwquality module is the preferred way of configuring
password requirements.
The man pages pam_pwquality(8)
provide information on the capabilities and configuration of
each. |
contains 7 rules |
Set Password Quality Requirements with pam_pwquality
[ref]groupThe pam_pwquality PAM module can be configured to meet
requirements for a variety of policies.
For example, to configure pam_pwquality to require at least one uppercase
character, lowercase character, digit, and other (special)
character, make sure that pam_pwquality exists in /etc/pam.d/system-auth :
password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
If no such line exists, add one as the first line of the password section in /etc/pam.d/system-auth .
Next, modify the settings in /etc/security/pwquality.conf to match the following:
difok = 4
minlen = 14
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
maxrepeat = 3
The arguments can be modified to ensure compliance with
your organization's security policy. Discussion of each parameter follows. |
contains 7 rules |
Ensure PAM Enforces Password Requirements - Minimum Digit Characters
[ref]ruleThe pam_pwquality module's dcredit parameter controls requirements for
usage of digits in a password. When set to a negative number, any password will be required to
contain that many digits. When set to a positive number, pam_pwquality will grant +1 additional
length credit for each digit. Modify the dcredit setting in
/etc/security/pwquality.conf to require the use of a digit in passwords. Rationale:Use of a complex password helps to increase the time and resources required
to compromise the password. Password complexity, or strength, is a measure of
the effectiveness of a password in resisting attempts at guessing and brute-force
attacks.
Password complexity is one factor of several that determines how long it takes
to crack a password. The more complex the password, the greater the number of
possible combinations that need to be tested before the password is compromised.
Requiring digits makes password guessing attacks more difficult by ensuring a larger
search space. References:
R31, 1, 12, 15, 16, 5, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-004066, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, 0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(a), CM-6(a), IA-5(4), PR.AC-1, PR.AC-6, PR.AC-7, FMT_SMF_EXT.1, Req-8.2.3, 8.3.6, 8.3, SRG-OS-000071-GPOS-00039 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
- name: Gather the package facts
package_facts:
manager: auto
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- PCI-DSS-Req-8.2.3
- PCI-DSSv4-8.3
- PCI-DSSv4-8.3.6
- accounts_password_pam_dcredit
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: XCCDF Value var_password_pam_dcredit # promote to variable
set_fact:
var_password_pam_dcredit: !!str -1
tags:
- always
- name: Ensure PAM Enforces Password Requirements - Minimum Digit Characters - Ensure
PAM variable dcredit is set accordingly
ansible.builtin.lineinfile:
create: true
dest: /etc/security/pwquality.conf
regexp: ^#?\s*dcredit
line: dcredit = {{ var_password_pam_dcredit }}
when: '"libpam-runtime" in ansible_facts.packages'
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- PCI-DSS-Req-8.2.3
- PCI-DSSv4-8.3
- PCI-DSSv4-8.3.6
- accounts_password_pam_dcredit
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_password_pam_dcredit='-1'
# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^dcredit")
# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_dcredit"
# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^dcredit\\>" "/etc/security/pwquality.conf"; then
escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
LC_ALL=C sed -i --follow-symlinks "s/^dcredit\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
fi
printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters
[ref]ruleThe pam_pwquality module's lcredit parameter controls requirements for
usage of lowercase letters in a password. When set to a negative number, any password will be required to
contain that many lowercase characters. When set to a positive number, pam_pwquality will grant +1 additional
length credit for each lowercase character. Modify the lcredit setting in
/etc/security/pwquality.conf to require the use of a lowercase character in passwords. Rationale:Use of a complex password helps to increase the time and resources required
to compromise the password. Password complexity, or strength, is a measure of
the effectiveness of a password in resisting attempts at guessing and brute-force
attacks.
Password complexity is one factor of several that determines how long it takes
to crack a password. The more complex the password, the greater the number of
possble combinations that need to be tested before the password is compromised.
Requiring a minimum number of lowercase characters makes password guessing attacks
more difficult by ensuring a larger search space. References:
R31, 1, 12, 15, 16, 5, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-004066, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, 0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(a), CM-6(a), IA-5(4), PR.AC-1, PR.AC-6, PR.AC-7, FMT_SMF_EXT.1, Req-8.2.3, 8.3.6, 8.3, SRG-OS-000070-GPOS-00038 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
- name: Gather the package facts
package_facts:
manager: auto
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- PCI-DSS-Req-8.2.3
- PCI-DSSv4-8.3
- PCI-DSSv4-8.3.6
- accounts_password_pam_lcredit
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: XCCDF Value var_password_pam_lcredit # promote to variable
set_fact:
var_password_pam_lcredit: !!str -1
tags:
- always
- name: Ensure PAM Enforces Password Requirements - Minimum Lowercase Characters -
Ensure PAM variable lcredit is set accordingly
ansible.builtin.lineinfile:
create: true
dest: /etc/security/pwquality.conf
regexp: ^#?\s*lcredit
line: lcredit = {{ var_password_pam_lcredit }}
when: '"libpam-runtime" in ansible_facts.packages'
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- PCI-DSS-Req-8.2.3
- PCI-DSSv4-8.3
- PCI-DSSv4-8.3.6
- accounts_password_pam_lcredit
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_password_pam_lcredit='-1'
# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^lcredit")
# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_lcredit"
# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^lcredit\\>" "/etc/security/pwquality.conf"; then
escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
LC_ALL=C sed -i --follow-symlinks "s/^lcredit\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
fi
printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Ensure PAM Enforces Password Requirements - Minimum Different Categories
[ref]ruleThe pam_pwquality module's minclass parameter controls
requirements for usage of different character classes, or types, of character
that must exist in a password before it is considered valid. For example,
setting this value to three (3) requires that any password must have characters
from at least three different categories in order to be approved. The default
value is zero (0), meaning there are no required classes. There are four
categories available:
* Upper-case characters
* Lower-case characters
* Digits
* Special characters (for example, punctuation)
Modify the minclass setting in /etc/security/pwquality.conf entry
to require 4
differing categories of characters when changing passwords.Rationale:Use of a complex password helps to increase the time and resources required to compromise the password.
Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts
at guessing and brute-force attacks.
Password complexity is one factor of several that determines how long it takes to crack a password. The
more complex the password, the greater the number of possible combinations that need to be tested before
the password is compromised.
Requiring a minimum number of character categories makes password guessing attacks more difficult
by ensuring a larger search space. References:
R68, 1, 12, 15, 16, 5, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-004066, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, 0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(a), CM-6(a), IA-5(4), PR.AC-1, PR.AC-6, PR.AC-7, SRG-OS-000072-GPOS-00040 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
- name: Gather the package facts
package_facts:
manager: auto
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- accounts_password_pam_minclass
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: XCCDF Value var_password_pam_minclass # promote to variable
set_fact:
var_password_pam_minclass: !!str 4
tags:
- always
- name: Ensure PAM Enforces Password Requirements - Minimum Different Categories -
Ensure PAM variable minclass is set accordingly
ansible.builtin.lineinfile:
create: true
dest: /etc/security/pwquality.conf
regexp: ^#?\s*minclass
line: minclass = {{ var_password_pam_minclass }}
when: '"libpam-runtime" in ansible_facts.packages'
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- accounts_password_pam_minclass
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_password_pam_minclass='4'
# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^minclass")
# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_minclass"
# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^minclass\\>" "/etc/security/pwquality.conf"; then
escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
LC_ALL=C sed -i --follow-symlinks "s/^minclass\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
fi
printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Ensure PAM Enforces Password Requirements - Minimum Length
[ref]ruleThe pam_pwquality module's minlen parameter controls requirements for
minimum characters required in a password. Add minlen=15
after pam_pwquality to set minimum password length requirements. Rationale:The shorter the password, the lower the number of possible combinations
that need to be tested before the password is compromised.
Password complexity, or strength, is a measure of the effectiveness of a
password in resisting attempts at guessing and brute-force attacks.
Password length is one factor of several that helps to determine strength
and how long it takes to crack a password. Use of more characters in a password
helps to exponentially increase the time and/or resources required to
compromise the password. References:
R31, R68, 1, 12, 15, 16, 5, 5.6.2.1.1, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-004066, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, 0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(a), CM-6(a), IA-5(4), PR.AC-1, PR.AC-6, PR.AC-7, FMT_SMF_EXT.1, Req-8.2.3, 8.3.6, 8.3, SRG-OS-000078-GPOS-00046 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
- name: Gather the package facts
package_facts:
manager: auto
tags:
- CJIS-5.6.2.1.1
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- PCI-DSS-Req-8.2.3
- PCI-DSSv4-8.3
- PCI-DSSv4-8.3.6
- accounts_password_pam_minlen
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: XCCDF Value var_password_pam_minlen # promote to variable
set_fact:
var_password_pam_minlen: !!str 15
tags:
- always
- name: Ensure PAM Enforces Password Requirements - Minimum Length - Ensure PAM variable
minlen is set accordingly
ansible.builtin.lineinfile:
create: true
dest: /etc/security/pwquality.conf
regexp: ^#?\s*minlen
line: minlen = {{ var_password_pam_minlen }}
when: '"libpam-runtime" in ansible_facts.packages'
tags:
- CJIS-5.6.2.1.1
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- PCI-DSS-Req-8.2.3
- PCI-DSSv4-8.3
- PCI-DSSv4-8.3.6
- accounts_password_pam_minlen
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_password_pam_minlen='15'
# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^minlen")
# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_minlen"
# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^minlen\\>" "/etc/security/pwquality.conf"; then
escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
LC_ALL=C sed -i --follow-symlinks "s/^minlen\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
fi
printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Ensure PAM Enforces Password Requirements - Minimum Special Characters
[ref]ruleThe pam_pwquality module's ocredit= parameter controls requirements for
usage of special (or "other") characters in a password. When set to a negative number,
any password will be required to contain that many special characters.
When set to a positive number, pam_pwquality will grant +1
additional length credit for each special character. Modify the ocredit setting
in /etc/security/pwquality.conf to equal -1
to require use of a special character in passwords. Rationale:Use of a complex password helps to increase the time and resources required
to compromise the password. Password complexity, or strength, is a measure of
the effectiveness of a password in resisting attempts at guessing and brute-force
attacks.
Password complexity is one factor of several that determines how long it takes
to crack a password. The more complex the password, the greater the number of
possible combinations that need to be tested before the password is compromised.
Requiring a minimum number of special characters makes password guessing attacks
more difficult by ensuring a larger search space. References:
R31, 1, 12, 15, 16, 5, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-004066, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, 0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(a), CM-6(a), IA-5(4), PR.AC-1, PR.AC-6, PR.AC-7, FMT_SMF_EXT.1, SRG-OS-000266-GPOS-00101 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
- name: Gather the package facts
package_facts:
manager: auto
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- accounts_password_pam_ocredit
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: XCCDF Value var_password_pam_ocredit # promote to variable
set_fact:
var_password_pam_ocredit: !!str -1
tags:
- always
- name: Ensure PAM Enforces Password Requirements - Minimum Special Characters - Ensure
PAM variable ocredit is set accordingly
ansible.builtin.lineinfile:
create: true
dest: /etc/security/pwquality.conf
regexp: ^#?\s*ocredit
line: ocredit = {{ var_password_pam_ocredit }}
when: '"libpam-runtime" in ansible_facts.packages'
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- accounts_password_pam_ocredit
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_password_pam_ocredit='-1'
# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^ocredit")
# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_ocredit"
# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^ocredit\\>" "/etc/security/pwquality.conf"; then
escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
LC_ALL=C sed -i --follow-symlinks "s/^ocredit\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
fi
printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session
[ref]ruleTo configure the number of retry prompts that are permitted per-session:
Edit the pam_pwquality.so statement in
/etc/pam.d/common-password to show
retry=3 , or a lower value if site
policy is more restrictive. The DoD requirement is a maximum of 3 prompts
per session. Rationale:Setting the password retry prompts that are permitted on a per-session basis to a low value
requires some software, such as SSH, to re-connect. This can slow down and
draw additional attention to some types of password-guessing attacks. Note that this
is different from account lockout, which is provided by the pam_faillock module. References:
R68, 1, 11, 12, 15, 16, 3, 5, 9, 5.5.3, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-004066, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 7.6, A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, CM-6(a), AC-7(a), IA-5(4), PR.AC-1, PR.AC-6, PR.AC-7, PR.IP-1, SRG-OS-000069-GPOS-00037, SRG-OS-000480-GPOS-00227 Remediation Shell script: (show)
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_password_pam_retry='3'
if [ -e "/etc/pam.d/common-password" ] ; then
valueRegex="$var_password_pam_retry" defaultValue="$var_password_pam_retry"
# non-empty values need to be preceded by an equals sign
[ -n "${valueRegex}" ] && valueRegex="=${valueRegex}"
# add an equals sign to non-empty values
[ -n "${defaultValue}" ] && defaultValue="=${defaultValue}"
# fix 'type' if it's wrong
if grep -q -P "^\\s*(?"'!'"password\\s)[[:alnum:]]+\\s+[[:alnum:]]+\\s+pam_pwquality.so" < "/etc/pam.d/common-password" ; then
sed --follow-symlinks -i -E -e "s/^(\\s*)[[:alnum:]]+(\\s+[[:alnum:]]+\\s+pam_pwquality.so)/\\1password\\2/" "/etc/pam.d/common-password"
fi
# fix 'control' if it's wrong
if grep -q -P "^\\s*password\\s+(?"'!'"requisite)[[:alnum:]]+\\s+pam_pwquality.so" < "/etc/pam.d/common-password" ; then
sed --follow-symlinks -i -E -e "s/^(\\s*password\\s+)[[:alnum:]]+(\\s+pam_pwquality.so)/\\1requisite\\2/" "/etc/pam.d/common-password"
fi
# fix the value for 'option' if one exists but does not match 'valueRegex'
if grep -q -P "^\\s*password\\s+requisite\\s+pam_pwquality.so(\\s.+)?\\s+retry(?"'!'"${valueRegex}(\\s|\$))" < "/etc/pam.d/common-password" ; then
sed --follow-symlinks -i -E -e "s/^(\\s*password\\s+requisite\\s+pam_pwquality.so(\\s.+)?\\s)retry=[^[:space:]]*/\\1retry${defaultValue}/" "/etc/pam.d/common-password"
# add 'option=default' if option is not set
elif grep -q -E "^\\s*password\\s+requisite\\s+pam_pwquality.so" < "/etc/pam.d/common-password" &&
grep -E "^\\s*password\\s+requisite\\s+pam_pwquality.so" < "/etc/pam.d/common-password" | grep -q -E -v "\\sretry(=|\\s|\$)" ; then
sed --follow-symlinks -i -E -e "s/^(\\s*password\\s+requisite\\s+pam_pwquality.so[^\\n]*)/\\1 retry${defaultValue}/" "/etc/pam.d/common-password"
# add a new entry if none exists
elif ! grep -q -P "^\\s*password\\s+requisite\\s+pam_pwquality.so(\\s.+)?\\s+retry${valueRegex}(\\s|\$)" < "/etc/pam.d/common-password" ; then
echo "password requisite pam_pwquality.so retry${defaultValue}" >> "/etc/pam.d/common-password"
fi
else
echo "/etc/pam.d/common-password doesn't exist" >&2
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters
[ref]ruleThe pam_pwquality module's ucredit= parameter controls requirements for
usage of uppercase letters in a password. When set to a negative number, any password will be required to
contain that many uppercase characters. When set to a positive number, pam_pwquality will grant +1 additional
length credit for each uppercase character. Modify the ucredit setting in
/etc/security/pwquality.conf to require the use of an uppercase character in passwords. Rationale:Use of a complex password helps to increase the time and resources required to compromise the password.
Password complexity, or strength, is a measure of the effectiveness of a password in resisting attempts
at guessing and brute-force attacks.
Password complexity is one factor of several that determines how long it takes to crack a password. The more
complex the password, the greater the number of possible combinations that need to be tested before
the password is compromised. References:
R31, 1, 12, 15, 16, 5, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, CCI-004066, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, 0421, 0422, 0431, 0974, 1173, 1401, 1504, 1505, 1546, 1557, 1558, 1559, 1560, 1561, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(a), CM-6(a), IA-5(4), PR.AC-1, PR.AC-6, PR.AC-7, FMT_SMF_EXT.1, Req-8.2.3, SRG-OS-000069-GPOS-00037, SRG-OS-000070-GPOS-00038 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
- name: Gather the package facts
package_facts:
manager: auto
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- PCI-DSS-Req-8.2.3
- accounts_password_pam_ucredit
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: XCCDF Value var_password_pam_ucredit # promote to variable
set_fact:
var_password_pam_ucredit: !!str -1
tags:
- always
- name: Ensure PAM Enforces Password Requirements - Minimum Uppercase Characters -
Ensure PAM variable ucredit is set accordingly
ansible.builtin.lineinfile:
create: true
dest: /etc/security/pwquality.conf
regexp: ^#?\s*ucredit
line: ucredit = {{ var_password_pam_ucredit }}
when: '"libpam-runtime" in ansible_facts.packages'
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-IA-5(1)(a)
- NIST-800-53-IA-5(4)
- NIST-800-53-IA-5(c)
- PCI-DSS-Req-8.2.3
- accounts_password_pam_ucredit
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_password_pam_ucredit='-1'
# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^ucredit")
# shellcheck disable=SC2059
printf -v formatted_output "%s = %s" "$stripped_key" "$var_password_pam_ucredit"
# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^ucredit\\>" "/etc/security/pwquality.conf"; then
escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
LC_ALL=C sed -i --follow-symlinks "s/^ucredit\\>.*/$escaped_formatted_output/gi" "/etc/security/pwquality.conf"
else
if [[ -s "/etc/security/pwquality.conf" ]] && [[ -n "$(tail -c 1 -- "/etc/security/pwquality.conf" || true)" ]]; then
LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/security/pwquality.conf"
fi
printf '%s\n' "$formatted_output" >> "/etc/security/pwquality.conf"
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Set Password Hashing Algorithm
[ref]groupThe system's default algorithm for storing password hashes in
/etc/shadow is SHA-512. This can be configured in several
locations. |
contains 1 rule |
Set Password Hashing Algorithm in /etc/login.defs
[ref]ruleIn /etc/login.defs , add or update the following line to ensure the system will use
YESCRYPT as the hashing algorithm:
ENCRYPT_METHOD YESCRYPT Rationale:Passwords need to be protected at all times, and encryption is the standard method for
protecting passwords. If passwords are not encrypted, they can be plainly read
(i.e., clear text) and easily compromised. Passwords that are encrypted with a weak algorithm
are no more protected than if they are kept in plain text.
Using a stronger hashing algorithm makes password cracking attacks more difficult. References:
1, 12, 15, 16, 5, 5.6.2.2, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.03, DSS06.10, 3.13.11, CCI-004062, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.2, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.7, SR 1.8, SR 1.9, SR 2.1, 0418, 1055, 1402, A.18.1.4, A.7.1.1, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.2, A.9.4.3, IA-5(c), IA-5(1)(c), CM-6(a), PR.AC-1, PR.AC-6, PR.AC-7, Req-8.2.1, 8.3.2, 8.3, SRG-OS-000073-GPOS-00041 Remediation Shell script: (show)
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'login' 2>/dev/null | grep -q '^installed'; then
var_password_hashing_algorithm='YESCRYPT'
# Allow multiple algorithms, but choose the first one for remediation
#
var_password_hashing_algorithm="$(echo $var_password_hashing_algorithm | cut -d \| -f 1)"
# Strip any search characters in the key arg so that the key can be replaced without
# adding any search characters to the config file.
stripped_key=$(sed 's/[\^=\$,;+]*//g' <<< "^ENCRYPT_METHOD")
# shellcheck disable=SC2059
printf -v formatted_output "%s %s" "$stripped_key" "$var_password_hashing_algorithm"
# If the key exists, change it. Otherwise, add it to the config_file.
# We search for the key string followed by a word boundary (matched by \>),
# so if we search for 'setting', 'setting2' won't match.
if LC_ALL=C grep -q -m 1 -i -e "^ENCRYPT_METHOD\\>" "/etc/login.defs"; then
escaped_formatted_output=$(sed -e 's|/|\\/|g' <<< "$formatted_output")
LC_ALL=C sed -i --follow-symlinks "s/^ENCRYPT_METHOD\\>.*/$escaped_formatted_output/gi" "/etc/login.defs"
else
if [[ -s "/etc/login.defs" ]] && [[ -n "$(tail -c 1 -- "/etc/login.defs" || true)" ]]; then
LC_ALL=C sed -i --follow-symlinks '$a'\\ "/etc/login.defs"
fi
printf '%s\n' "$formatted_output" >> "/etc/login.defs"
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Install pam_pwquality Package
[ref]rule
The libpam-pwquality package can be installed with the following command:
$ apt-get install libpam-pwquality Rationale:Use of a complex password helps to increase the time and resources required
to compromise the password. Password complexity, or strength, is a measure
of the effectiveness of a password in resisting attempts at guessing and
brute-force attacks. "pwquality" enforces complex password construction
configuration and has the ability to limit brute-force attacks on the system. Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | enable |
---|
- name: Gather the package facts
package_facts:
manager: auto
tags:
- enable_strategy
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- package_pam_pwquality_installed
- name: Ensure libpam-pwquality is installed
package:
name: libpam-pwquality
state: present
when: '"libpam-runtime" in ansible_facts.packages'
tags:
- enable_strategy
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- package_pam_pwquality_installed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | enable |
---|
include install_libpam-pwquality
class install_libpam-pwquality {
package { 'libpam-pwquality':
ensure => 'installed',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | enable |
---|
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
DEBIAN_FRONTEND=noninteractive apt-get install -y "libpam-pwquality"
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
Remediation script: (show)
[[packages]]
name = "libpam-pwquality"
version = "*"
|
Protect Accounts by Restricting Password-Based Login
[ref]groupConventionally, Unix shell accounts are accessed by
providing a username and password to a login program, which tests
these values for correctness using the /etc/passwd and
/etc/shadow files. Password-based login is vulnerable to
guessing of weak passwords, and to sniffing and man-in-the-middle
attacks against passwords entered over a network or at an insecure
console. Therefore, mechanisms for accessing accounts by entering
usernames and passwords should be restricted to those which are
operationally necessary. |
contains 2 rules |
Set Password Expiration Parameters
[ref]groupThe file /etc/login.defs controls several
password-related settings. Programs such as passwd ,
su , and
login consult /etc/login.defs to determine
behavior with regard to password aging, expiration warnings,
and length. See the man page login.defs(5) for more information.
Users should be forced to change their passwords, in order to
decrease the utility of compromised passwords. However, the need to
change passwords often should be balanced against the risk that
users will reuse or write down passwords if forced to change them
too often. Forcing password changes every 90-360 days, depending on
the environment, is recommended. Set the appropriate value as
PASS_MAX_DAYS and apply it to existing accounts with the
-M flag.
The PASS_MIN_DAYS (-m ) setting prevents password
changes for 7 days after the first change, to discourage password
cycling. If you use this setting, train users to contact an administrator
for an emergency password change in case a new password becomes
compromised. The PASS_WARN_AGE (-W ) setting gives
users 7 days of warnings at login time that their passwords are about to expire.
For example, for each existing human user USER, expiration parameters
could be adjusted to a 180 day maximum password age, 7 day minimum password
age, and 7 day warning period with the following command:
$ sudo chage -M 180 -m 7 -W 7 USER |
contains 1 rule |
Set Root Account Password Maximum Age
[ref]ruleConfigure the root account to enforce a 365-day maximum password lifetime restriction by running the following command:
$ sudo chage -M 365 root Rationale:Any password, no matter how complex, can eventually be cracked. Therefore,
passwords need to be changed periodically. If the operating system does
not limit the lifetime of passwords and force users to change their
passwords, there is the risk that the operating system passwords could be
compromised. Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
var_accounts_maximum_age_root='365'
chage -M $var_accounts_maximum_age_root root
|
Verify Proper Storage and Existence of Password
Hashes
[ref]groupBy default, password hashes for local accounts are stored
in the second field (colon-separated) in
/etc/shadow . This file should be readable only by
processes running with root credentials, preventing users from
casually accessing others' password hashes and attempting
to crack them.
However, it remains possible to misconfigure the system
and store password hashes
in world-readable files such as /etc/passwd , or
to even store passwords themselves in plaintext on the system.
Using system-provided tools for password change/creation
should allow administrators to avoid such misconfiguration. |
contains 1 rule |
Set number of Password Hashing Rounds - password-auth
[ref]ruleConfigure the number or rounds for the password hashing algorithm. This can be
accomplished by using the rounds option for the pam_unix PAM module.
In file /etc/pam.d/common-password append rounds=11
to the pam_unix.so entry, as shown below:
password [success=1 default=ignore] pam_unix.so ...existing_options... rounds=11 Warning:
Setting a high number of hashing rounds makes it more difficult to brute force the password,
but requires more CPU resources to authenticate users. Rationale:Using a higher number of rounds makes password cracking attacks more difficult. Remediation Shell script: (show)
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}\n' 'libpam-runtime' 2>/dev/null | grep -q '^installed'; then
var_password_pam_unix_rounds='11'
if [ -e "/etc/pam.d/common-password" ] ; then
PAM_FILE_PATH="/etc/pam.d/common-password"
if [ -f /usr/bin/authselect ]; then
if ! authselect check; then
echo "
authselect integrity check failed. Remediation aborted!
This remediation could not be applied because an authselect profile was not selected or the selected profile is not intact.
It is not recommended to manually edit the PAM files when authselect tool is available.
In cases where the default authselect profile does not cover a specific demand, a custom authselect profile is recommended."
exit 1
fi
CURRENT_PROFILE=$(authselect current -r | awk '{ print $1 }')
# If not already in use, a custom profile is created preserving the enabled features.
if [[ ! $CURRENT_PROFILE == custom/* ]]; then
ENABLED_FEATURES=$(authselect current | tail -n+3 | awk '{ print $2 }')
# The "local" profile does not contain essential security features required by multiple Benchmarks.
# If currently used, it is replaced by "sssd", which is the best option in this case.
if [[ $CURRENT_PROFILE == local ]]; then
CURRENT_PROFILE="sssd"
fi
authselect create-profile hardening -b $CURRENT_PROFILE
CURRENT_PROFILE="custom/hardening"
authselect apply-changes -b --backup=before-hardening-custom-profile
authselect select $CURRENT_PROFILE
for feature in $ENABLED_FEATURES; do
authselect enable-feature $feature;
done
authselect apply-changes -b --backup=after-hardening-custom-profile
fi
PAM_FILE_NAME=$(basename "/etc/pam.d/common-password")
PAM_FILE_PATH="/etc/authselect/$CURRENT_PROFILE/$PAM_FILE_NAME"
authselect apply-changes -b
fi
if ! grep -qP "^\s*password\s+\\[success=1 default=ignore\\]\s+pam_unix.so\s*.*" "$PAM_FILE_PATH"; then
# Line matching group + control + module was not found. Check group + module.
if [ "$(grep -cP '^\s*password\s+.*\s+pam_unix.so\s*' "$PAM_FILE_PATH")" -eq 1 ]; then
# The control is updated only if one single line matches.
sed -i -E --follow-symlinks "s/^(\s*password\s+).*(\bpam_unix.so.*)/\1\[success=1 default=ignore\] \2/" "$PAM_FILE_PATH"
else
echo "password \[success=1 default=ignore\] pam_unix.so" >> "$PAM_FILE_PATH"
fi
fi
# Check the option
if ! grep -qP "^\s*password\s+\\[success=1 default=ignore\\]\s+pam_unix.so\s*.*\srounds\b" "$PAM_FILE_PATH"; then
sed -i -E --follow-symlinks "/\s*password\s+\\[success=1 default=ignore\\]\s+pam_unix.so.*/ s/$/ rounds=$var_password_pam_unix_rounds/" "$PAM_FILE_PATH"
else
sed -i -E --follow-symlinks "s/(\s*password\s+\\[success=1 default=ignore\\]\s+pam_unix.so\s+.*)(rounds=)[[:alnum:]]+\s*(.*)/\1\2$var_password_pam_unix_rounds \3/" "$PAM_FILE_PATH"
fi
if [ -f /usr/bin/authselect ]; then
authselect apply-changes -b
fi
else
echo "/etc/pam.d/common-password was not found" >&2
fi
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
File Permissions and Masks
[ref]groupTraditional Unix security relies heavily on file and
directory permissions to prevent unauthorized users from reading or
modifying files to which they should not have access.
Several of the commands in this section search filesystems
for files or directories with certain characteristics, and are
intended to be run on every local partition on a given system.
When the variable PART appears in one of the commands below,
it means that the command is intended to be run repeatedly, with the
name of each local partition substituted for PART in turn.
The following command prints a list of all xfs partitions on the local
system, which is the default filesystem for Debian 12
installations:
$ mount -t xfs | awk '{print $3}'
For any systems that use a different
local filesystem type, modify this command as appropriate. |
contains 5 rules |
Verify Permissions on Important Files and
Directories
[ref]groupPermissions for many files on a system must be set
restrictively to ensure sensitive information is properly protected.
This section discusses important
permission restrictions which can be verified
to ensure that no harmful discrepancies have
arisen. |
contains 5 rules |
Ensure All World-Writable Directories Are Owned by root User
[ref]ruleAll directories in local partitions which are world-writable should be owned by root.
If any world-writable directories are not owned by root, this should be investigated.
Following this, the files should be deleted or assigned to root user. Rationale:Allowing a user account to own a world-writable directory is undesirable because it allows the
owner of that directory to remove or replace any files that may be placed in the directory by
other users. Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | medium |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
- name: Ensure All World-Writable Directories Are Owned by root User - Define Excluded
(Non-Local) File Systems and Paths
ansible.builtin.set_fact:
excluded_fstypes:
- afs
- ceph
- cifs
- smb3
- smbfs
- sshfs
- ncpfs
- ncp
- nfs
- nfs4
- gfs
- gfs2
- glusterfs
- gpfs
- pvfs2
- ocfs2
- lustre
- davfs
- fuse.sshfs
excluded_paths:
- dev
- proc
- run
- sys
search_paths: []
tags:
- dir_perms_world_writable_root_owned
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: Ensure All World-Writable Directories Are Owned by root User - Find Relevant
Root Directories Ignoring Pre-Defined Excluded Paths
ansible.builtin.find:
paths: /
file_type: directory
excludes: '{{ excluded_paths }}'
hidden: true
recurse: false
register: result_relevant_root_dirs
tags:
- dir_perms_world_writable_root_owned
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: Ensure All World-Writable Directories Are Owned by root User - Include Relevant
Root Directories in a List of Paths to be Searched
ansible.builtin.set_fact:
search_paths: '{{ search_paths | union([item.path]) }}'
loop: '{{ result_relevant_root_dirs.files }}'
tags:
- dir_perms_world_writable_root_owned
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: Ensure All World-Writable Directories Are Owned by root User - Increment Search
Paths List with Local Partitions Mount Points
ansible.builtin.set_fact:
search_paths: '{{ search_paths | union([item.mount]) }}'
loop: '{{ ansible_mounts }}'
when:
- item.fstype not in excluded_fstypes
- item.mount != '/'
tags:
- dir_perms_world_writable_root_owned
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: Ensure All World-Writable Directories Are Owned by root User - Increment Search
Paths List with Local NFS File System Targets
ansible.builtin.set_fact:
search_paths: '{{ search_paths | union([item.device.split('':'')[1]]) }}'
loop: '{{ ansible_mounts }}'
when: item.device is search("localhost:")
tags:
- dir_perms_world_writable_root_owned
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: Ensure All World-Writable Directories Are Owned by root User - Define Rule
Specific Facts
ansible.builtin.set_fact:
world_writable_dirs: []
tags:
- dir_perms_world_writable_root_owned
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: Ensure All World-Writable Directories Are Owned by root User - Find All Uncompliant
Directories in Local File Systems
ansible.builtin.command:
cmd: find {{ item }} -xdev -type d -perm -0002 -uid +0
loop: '{{ search_paths }}'
changed_when: false
register: result_found_dirs
tags:
- dir_perms_world_writable_root_owned
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: Ensure All World-Writable Directories Are Owned by root User - Create List
of World Writable Directories Not Owned by root
ansible.builtin.set_fact:
world_writable_dirs: '{{ world_writable_dirs | union(item.stdout_lines) | list
}}'
loop: '{{ result_found_dirs.results }}'
when: item is not skipped
tags:
- dir_perms_world_writable_root_owned
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
- name: Ensure All World-Writable Directories Are Owned by root User - Ensure root
Ownership on Local World Writable Directories
ansible.builtin.file:
path: '{{ item }}'
owner: root
loop: '{{ world_writable_dirs }}'
tags:
- dir_perms_world_writable_root_owned
- low_complexity
- medium_disruption
- medium_severity
- no_reboot_needed
- restrict_strategy
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | medium |
---|
Reboot: | false |
---|
Strategy: | restrict |
---|
# At least under containerized env /proc can have files w/o possilibity to
# modify even as root. And touching /proc is not good idea anyways.
find / -path /proc -prune -o \
-not -fstype afs -not -fstype ceph -not -fstype cifs -not -fstype smb3 -not -fstype smbfs \
-not -fstype sshfs -not -fstype ncpfs -not -fstype ncp -not -fstype nfs -not -fstype nfs4 \
-not -fstype gfs -not -fstype gfs2 -not -fstype glusterfs -not -fstype gpfs \
-not -fstype pvfs2 -not -fstype ocfs2 -not -fstype lustre -not -fstype davfs \
-not -fstype fuse.sshfs -type d -perm -0002 -uid +0 -exec chown root {} \;
|
Verify that All World-Writable Directories Have Sticky Bits Set
[ref]ruleWhen the so-called 'sticky bit' is set on a directory, only the owner of a given file may
remove that file from the directory. Without the sticky bit, any user with write access to a
directory may remove any file in the directory. Setting the sticky bit prevents users from
removing each other's files. In cases where there is no reason for a directory to be
world-writable, a better solution is to remove that permission rather than to set the sticky
bit. However, if a directory is used by a particular application, consult that application's
documentation instead of blindly changing modes.
To set the sticky bit on a world-writable directory DIR, run the following command:
$ sudo chmod +t DIR Warning:
This rule can take a long time to perform the check and might consume a considerable
amount of resources depending on the number of directories present on the system. It is
not a problem in most cases, but especially systems with a large number of directories can
be affected. See https://access.redhat.com/articles/6999111 . Rationale:Failing to set the sticky bit on public directories allows unauthorized users to delete files
in the directory structure.
The only authorized public directories are those temporary directories supplied with the
system, or those designed to be temporary file repositories. The setting is normally reserved
for directories used by the system, by users for temporary file storage (such as /tmp ),
and for directories requiring global read/write access. References:
R54, 12, 13, 14, 15, 16, 18, 3, 5, APO01.06, DSS05.04, DSS05.07, DSS06.02, CCI-001090, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, 2.2.6, 2.2, SRG-OS-000138-GPOS-00069 |
Ensure No World-Writable Files Exist
[ref]ruleIt is generally a good idea to remove global (other) write access to a file when it is
discovered. However, check with documentation for specific applications before making changes.
Also, monitor for recurring world-writable files, as these may be symptoms of a misconfigured
application or user account. Finally, this applies to real files and not virtual files that
are a part of pseudo file systems such as sysfs or procfs . Warning:
This rule can take a long time to perform the check and might consume a considerable
amount of resources depending on the number of files present on the system. It is not a
problem in most cases, but especially systems with a large number of files can be affected.
See https://access.redhat.com/articles/6999111 . Rationale:Data in world-writable files can be modified by any user on the system. In almost all
circumstances, files can be configured using a combination of user and group permissions to
support whatever legitimate access is needed without the risk caused by world-writable files. References:
R54, 12, 13, 14, 15, 16, 18, 3, 5, APO01.06, DSS05.04, DSS05.07, DSS06.02, 4.3.3.7.3, SR 2.1, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CIP-003-8 R5.1.1, CIP-003-8 R5.3, CIP-004-6 R2.3, CIP-007-3 R2.1, CIP-007-3 R2.2, CIP-007-3 R2.3, CIP-007-3 R5.1, CIP-007-3 R5.1.1, CIP-007-3 R5.1.2, CM-6(a), AC-6(1), PR.AC-4, PR.DS-5, 2.2.6, 2.2 Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | configure |
---|
FILTER_NODEV=$(awk '/nodev/ { print $2 }' /proc/filesystems | paste -sd,)
# Do not consider /sysroot partition because it contains only the physical
# read-only root on bootable containers.
PARTITIONS=$(findmnt -n -l -k -it $FILTER_NODEV | awk '{ print $1 }' | grep -v "/sysroot")
for PARTITION in $PARTITIONS; do
find "${PARTITION}" -xdev -type f -perm -002 -exec chmod o-w {} \; 2>/dev/null
done
# Ensure /tmp is also fixed when tmpfs is used.
if grep "^tmpfs /tmp" /proc/mounts; then
find /tmp -xdev -type f -perm -002 -exec chmod o-w {} \; 2>/dev/null
fi
|
Ensure All Files Are Owned by a Group
[ref]ruleIf any file is not group-owned by a valid defined group, the cause of the lack of
group-ownership must be investigated. Following this, those files should be deleted or
assigned to an appropriate group. The groups need to be defined in /etc/group
or in /usr/lib/group if nss-altfiles are configured to be used
in /etc/nsswitch.conf .
Locate the mount points related to local devices by the following command:
$ findmnt -n -l -k -it $(awk '/nodev/ { print $2 }' /proc/filesystems | paste -sd,)
For all mount points listed by the previous command, it is necessary to search for files which
do not belong to a valid group using the following command:
$ sudo find MOUNTPOINT -xdev -nogroup 2>/dev/null Warning:
This rule only considers local groups as valid groups.
If you have your groups defined outside /etc/group or /usr/lib/group , the rule won't consider those. Warning:
This rule can take a long time to perform the check and might consume a considerable
amount of resources depending on the number of files present on the system. It is not a
problem in most cases, but especially systems with a large number of files can be affected.
See https://access.redhat.com/articles/6999111 . Rationale:Unowned files do not directly imply a security problem, but they are generally a sign that
something is amiss. They may be caused by an intruder, by incorrect software installation or
draft software removal, or by failure to remove all files belonging to a deleted account, or
other similar cases. The files should be repaired so they will not cause problems when
accounts are created in the future, and the cause should be discovered and addressed. References:
R53, 1, 11, 12, 13, 14, 15, 16, 18, 3, 5, APO01.06, DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS05.10, DSS06.02, DSS06.03, DSS06.06, DSS06.10, CCI-000366, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 5.2, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.18.1.4, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.1, A.9.2.2, A.9.2.3, A.9.2.4, A.9.2.6, A.9.3.1, A.9.4.1, A.9.4.2, A.9.4.3, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-1, PR.AC-4, PR.AC-6, PR.AC-7, PR.DS-5, PR.PT-3, 2.2.6, 2.2, SRG-OS-000480-GPOS-00227 |
Ensure All Files Are Owned by a User
[ref]ruleIf any files are not owned by a user, then the cause of their lack of ownership should be
investigated. Following this, the files should be deleted or assigned to an appropriate user.
Locate the mount points related to local devices by the following command:
$ findmnt -n -l -k -it $(awk '/nodev/ { print $2 }' /proc/filesystems | paste -sd,)
For all mount points listed by the previous command, it is necessary to search for files which
do not belong to a valid user using the following command:
$ sudo find MOUNTPOINT -xdev -nouser 2>/dev/null Warning:
For this rule to evaluate centralized user accounts, getent must be working properly
so that running the command getent passwd returns a list of all users in your organization.
If using the System Security Services Daemon (SSSD), enumerate = true must be configured
in your organization's domain to return a complete list of users Warning:
This rule can take a long time to perform the check and might consume a considerable
amount of resources depending on the number of files present on the system. It is not a
problem in most cases, but especially systems with a large number of files can be affected.
See https://access.redhat.com/articles/6999111 . Rationale:Unowned files do not directly imply a security problem, but they are generally a sign that
something is amiss. They may be caused by an intruder, by incorrect software installation or
draft software removal, or by failure to remove all files belonging to a deleted account, or
other similar cases. The files should be repaired so they will not cause problems when
accounts are created in the future, and the cause should be discovered and addressed. References:
R53, 11, 12, 13, 14, 15, 16, 18, 3, 5, 9, APO01.06, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.02, DSS05.04, DSS05.05, DSS05.07, DSS06.02, DSS06.03, DSS06.06, CCI-000366, 4.3.3.2.2, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3, SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 5.2, SR 7.6, A.10.1.1, A.11.1.4, A.11.1.5, A.11.2.1, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.1.3, A.13.2.1, A.13.2.3, A.13.2.4, A.14.1.2, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.1.2, A.7.1.1, A.7.1.2, A.7.3.1, A.8.2.2, A.8.2.3, A.9.1.1, A.9.1.2, A.9.2.1, A.9.2.3, A.9.4.1, A.9.4.4, A.9.4.5, CM-6(a), AC-6(1), PR.AC-4, PR.AC-6, PR.DS-5, PR.IP-1, PR.PT-3, 2.2.6, 2.2, SRG-OS-000480-GPOS-00227 |
Services
[ref]groupThe best protection against vulnerable software is running less software. This section describes how to review
the software which Debian 12 installs on a system and disable software which is not needed. It
then enumerates the software packages installed on a default Debian 12 system and provides guidance about which
ones can be safely disabled.
Debian 12 provides a convenient minimal install option that essentially installs the bare necessities for a functional
system. When building Debian 12 systems, it is highly recommended to select the minimal packages and then build up
the system from there. |
contains 14 rules |
The Dynamic Host Configuration Protocol (DHCP) allows
systems to request and obtain an IP address and other configuration
parameters from a server.
This guide recommends configuring networking on clients by manually editing
the appropriate files under /etc/sysconfig . Use of DHCP can make client
systems vulnerable to compromise by rogue DHCP servers, and should be avoided
unless necessary. If using DHCP is necessary, however, there are best practices
that should be followed to minimize security risk. |
contains 2 rules |
Disable DHCP Server
[ref]groupThe DHCP server dhcpd is not installed or activated by
default. If the software was installed and activated, but the
system does not need to act as a DHCP server, it should be disabled
and removed. |
contains 2 rules |
Uninstall DHCP Server Package
[ref]ruleIf the system does not need to act as a DHCP server,
the dhcp package can be uninstalled.
The dhcp package can be removed with the following command:
$ apt-get remove dhcp Rationale:Removing the DHCP server ensures that it cannot be easily or
accidentally reactivated and disrupt network operation. References:
R62, 11, 14, 3, 9, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.02, DSS05.05, DSS06.06, CCI-000366, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3, SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 7.6, A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4, A.9.1.2, CM-7(a), CM-7(b), CM-6(a), PR.IP-1, PR.PT-3, 2.2.4, 2.2 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure dhcp is removed
package:
name: dhcp
state: absent
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- package_dhcp_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_dhcp
class remove_dhcp {
package { 'dhcp':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove dhcp
# from the system, and may remove any packages
# that depend on dhcp. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "dhcp"
|
Uninstall kea Package
[ref]ruleIf the system does not need to act as a DHCP server,
the kea package can be uninstalled. Rationale:Removing the DHCP server ensures that it cannot be easily or
accidentally reactivated and disrupt network operation. Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure kea is removed
package:
name: kea
state: absent
tags:
- disable_strategy
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- package_kea_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_kea
class remove_kea {
package { 'kea':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove kea
# from the system, and may remove any packages
# that depend on kea. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "kea"
|
Mail Server Software
[ref]groupMail servers are used to send and receive email over the network.
Mail is a very common service, and Mail Transfer Agents (MTAs) are obvious
targets of network attack.
Ensure that systems are not running MTAs unnecessarily,
and configure needed MTAs as defensively as possible.
Very few systems at any site should be configured to directly receive email over the
network. Users should instead use mail client programs to retrieve email
from a central server that supports protocols such as IMAP or POP3.
However, it is normal for most systems to be independently capable of sending email,
for instance so that cron jobs can report output to an administrator.
Most MTAs, including Postfix, support a submission-only mode in which mail can be sent from
the local system to a central site MTA (or directly delivered to a local account),
but the system still cannot receive mail directly over a network.
The alternatives program in Debian 12 permits selection of other mail server software
(such as Sendmail), but Postfix is the default and is preferred.
Postfix was coded with security in mind and can also be more effectively contained by
SELinux as its modular design has resulted in separate processes performing specific actions.
More information is available on its website,
http://www.postfix.org. |
contains 1 rule |
Uninstall Sendmail Package
[ref]ruleSendmail is not the default mail transfer agent and is
not installed by default.
The sendmail package can be removed with the following command:
$ apt-get remove sendmail Rationale:The sendmail software was not developed with security in mind and
its design prevents it from being effectively contained by SELinux. Postfix
should be used instead. References:
R62, 11, 14, 3, 9, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS05.02, DSS05.05, DSS06.06, CCI-000366, CCI-000381, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3, SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 7.6, A.12.1.2, A.12.5.1, A.12.6.2, A.14.2.2, A.14.2.3, A.14.2.4, A.9.1.2, CM-7(a), CM-7(b), CM-6(a), PR.IP-1, PR.PT-3, SRG-OS-000480-GPOS-00227, SRG-OS-000095-GPOS-00049 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Gather the package facts
package_facts:
manager: auto
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- disable_strategy
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- package_sendmail_removed
- name: Ensure sendmail is removed
package:
name: sendmail
state: absent
when: '"linux-base" in ansible_facts.packages'
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- disable_strategy
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- package_sendmail_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_sendmail
class remove_sendmail {
package { 'sendmail':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then
# CAUTION: This remediation script will remove sendmail
# from the system, and may remove any packages
# that depend on sendmail. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "sendmail"
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
Obsolete Services
[ref]groupThis section discusses a number of network-visible
services which have historically caused problems for system
security, and for which disabling or severely limiting the service
has been the best available guidance for some time. As a result of
this, many of these services are not installed as part of Debian 12
by default.
Organizations which are running these services should
switch to more secure equivalents as soon as possible.
If it remains absolutely necessary to run one of
these services for legacy reasons, care should be taken to restrict
the service as much as possible, for instance by configuring host
firewall software such as iptables to restrict access to the
vulnerable service to only those remote hosts which have a known
need to use it. |
contains 11 rules |
Xinetd
[ref]groupThe xinetd service acts as a dedicated listener for some
network services (mostly, obsolete ones) and can be used to provide access
controls and perform some logging. It has been largely obsoleted by other
features, and it is not installed by default. The older Inetd service
is not even available as part of Debian 12. |
contains 1 rule |
Uninstall xinetd Package
[ref]ruleThe xinetd package can be removed with the following command:
$ apt-get remove xinetd Rationale:Removing the xinetd package decreases the risk of the
xinetd service's accidental (or intentional) activation. References:
R62, 11, 12, 14, 15, 3, 8, 9, APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06, CCI-000305, 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii), 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3, SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6, A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2, CM-7(a), CM-7(b), CM-6(a), PR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4, 2.2.4, 2.2 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Gather the package facts
package_facts:
manager: auto
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- low_complexity
- low_disruption
- low_severity
- no_reboot_needed
- package_xinetd_removed
- name: Ensure xinetd is removed
package:
name: xinetd
state: absent
when: '"linux-base" in ansible_facts.packages'
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- low_complexity
- low_disruption
- low_severity
- no_reboot_needed
- package_xinetd_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_xinetd
class remove_xinetd {
package { 'xinetd':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# Remediation is applicable only in certain platforms
if dpkg-query --show --showformat='${db:Status-Status}
' 'linux-base' 2>/dev/null | grep -q ^installed; then
# CAUTION: This remediation script will remove xinetd
# from the system, and may remove any packages
# that depend on xinetd. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "xinetd"
else
>&2 echo 'Remediation is not applicable, nothing was done'
fi
|
The Network Information Service (NIS), also known as 'Yellow
Pages' (YP), and its successor NIS+ have been made obsolete by
Kerberos, LDAP, and other modern centralized authentication
services. NIS should not be used because it suffers from security
problems inherent in its design, such as inadequate protection of
important authentication information. |
contains 2 rules |
Remove NIS Client
[ref]ruleThe Network Information Service (NIS), formerly known as Yellow Pages,
is a client-server directory service protocol used to distribute system configuration
files. The NIS client (ypbind ) was used to bind a system to an NIS server
and receive the distributed configuration files. Rationale:The NIS service is inherently an insecure system that has been vulnerable
to DOS attacks, buffer overflows and has poor authentication for querying
NIS maps. NIS generally has been replaced by such protocols as Lightweight
Directory Access Protocol (LDAP). It is recommended that the service be
removed. Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure ypbind-mt is removed
package:
name: ypbind-mt
state: absent
tags:
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- low_complexity
- low_disruption
- no_reboot_needed
- package_ypbind_removed
- unknown_severity
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_ypbind-mt
class remove_ypbind-mt {
package { 'ypbind-mt':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove ypbind-mt
# from the system, and may remove any packages
# that depend on ypbind-mt. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "ypbind-mt"
|
Uninstall ypserv Package
[ref]ruleThe ypserv package can be removed with the following command:
$ apt-get remove ypserv Rationale:The NIS service provides an unencrypted authentication service which does
not provide for the confidentiality and integrity of user passwords or the
remote session.
Removing the ypserv package decreases the risk of the accidental
(or intentional) activation of NIS or NIS+ services. References:
R62, 11, 12, 14, 15, 3, 8, 9, APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06, CCI-000381, 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii), 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3, SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6, A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2, CM-7(a), CM-7(b), CM-6(a), IA-5(1)(c), PR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4, Req-2.2.2, 2.2.4, 2.2, SRG-OS-000095-GPOS-00049 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure ypserv is removed
package:
name: ypserv
state: absent
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- NIST-800-53-IA-5(1)(c)
- PCI-DSS-Req-2.2.2
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- high_severity
- low_complexity
- low_disruption
- no_reboot_needed
- package_ypserv_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_ypserv
class remove_ypserv {
package { 'ypserv':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove ypserv
# from the system, and may remove any packages
# that depend on ypserv. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "ypserv"
|
Rlogin, Rsh, and Rexec
[ref]groupThe Berkeley r-commands are legacy services which
allow cleartext remote access and have an insecure trust
model. |
contains 2 rules |
Uninstall rsh-server Package
[ref]ruleThe rsh-server package can be removed with the following command:
$ apt-get remove rsh-server Rationale:The rsh-server service provides unencrypted remote access service which does not
provide for the confidentiality and integrity of user passwords or the remote session and has very weak
authentication. If a privileged user were to login using this service, the privileged user password
could be compromised. The rsh-server package provides several obsolete and insecure
network services. Removing it decreases the risk of those services' accidental (or intentional)
activation. References:
R62, 11, 12, 14, 15, 3, 8, 9, APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06, CCI-000381, 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii), 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3, SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6, A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2, CM-7(a), CM-7(b), CM-6(a), IA-5(1)(c), PR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4, 2.2.4, 2.2, SRG-OS-000095-GPOS-00049 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure rsh-server is removed
package:
name: rsh-server
state: absent
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- NIST-800-53-IA-5(1)(c)
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- high_severity
- low_complexity
- low_disruption
- no_reboot_needed
- package_rsh-server_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_rsh-server
class remove_rsh-server {
package { 'rsh-server':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove rsh-server
# from the system, and may remove any packages
# that depend on rsh-server. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "rsh-server"
|
Uninstall rsh Package
[ref]rule
The rsh package contains the client commands
for the rsh services Rationale:These legacy clients contain numerous security exposures and have
been replaced with the more secure SSH package. Even if the server is removed,
it is best to ensure the clients are also removed to prevent users from
inadvertently attempting to use these commands and therefore exposing
their credentials. Note that removing the rsh package removes
the clients for rsh ,rcp , and rlogin . References:
R62, 3.1.13, 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii), A.8.2.3, A.13.1.1, A.13.2.1, A.13.2.3, A.14.1.2, A.14.1.3, 2.2.4, 2.2 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure rsh is removed
package:
name: rsh
state: absent
tags:
- NIST-800-171-3.1.13
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- low_complexity
- low_disruption
- no_reboot_needed
- package_rsh_removed
- unknown_severity
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_rsh
class remove_rsh {
package { 'rsh':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove rsh
# from the system, and may remove any packages
# that depend on rsh. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "rsh"
|
Chat/Messaging Services
[ref]groupThe talk software makes it possible for users to send and receive messages
across systems through a terminal session. |
contains 2 rules |
Uninstall talk-server Package
[ref]ruleThe talk-server package can be removed with the following command: $ apt-get remove talk-server Rationale:The talk software presents a security risk as it uses unencrypted protocols
for communications. Removing the talk-server package decreases the
risk of the accidental (or intentional) activation of talk services. Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure talk-server is removed
package:
name: talk-server
state: absent
tags:
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- package_talk-server_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_talk-server
class remove_talk-server {
package { 'talk-server':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove talk-server
# from the system, and may remove any packages
# that depend on talk-server. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "talk-server"
|
Uninstall talk Package
[ref]ruleThe talk package contains the client program for the
Internet talk protocol, which allows the user to chat with other users on
different systems. Talk is a communication program which copies lines from one
terminal to the terminal of another user.
The talk package can be removed with the following command:
$ apt-get remove talk Rationale:The talk software presents a security risk as it uses unencrypted protocols
for communications. Removing the talk package decreases the
risk of the accidental (or intentional) activation of talk client program. Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure talk is removed
package:
name: talk
state: absent
tags:
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- low_complexity
- low_disruption
- medium_severity
- no_reboot_needed
- package_talk_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_talk
class remove_talk {
package { 'talk':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove talk
# from the system, and may remove any packages
# that depend on talk. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "talk"
|
Telnet
[ref]groupThe telnet protocol does not provide confidentiality or integrity
for information transmitted on the network. This includes authentication
information such as passwords. Organizations which use telnet should be
actively working to migrate to a more secure protocol. |
contains 2 rules |
Uninstall telnet-server Package
[ref]ruleThe telnet-server package can be removed with the following command:
$ apt-get remove telnet-server Rationale:It is detrimental for operating systems to provide, or install by default,
functionality exceeding requirements or mission objectives. These
unnecessary capabilities are often overlooked and therefore may remain
unsecure. They increase the risk to the platform by providing additional
attack vectors.
The telnet service provides an unencrypted remote access service which does
not provide for the confidentiality and integrity of user passwords or the
remote session. If a privileged user were to login using this service, the
privileged user password could be compromised.
Removing the telnet-server package decreases the risk of the
telnet service's accidental (or intentional) activation. References:
R62, 11, 12, 14, 15, 3, 8, 9, APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06, CCI-000381, 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii), 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3, SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6, A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2, CM-7(a), CM-7(b), CM-6(a), PR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4, Req-2.2.2, 2.2.4, 2.2, SRG-OS-000095-GPOS-00049 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure telnet-server is removed
package:
name: telnet-server
state: absent
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- PCI-DSS-Req-2.2.2
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- high_severity
- low_complexity
- low_disruption
- no_reboot_needed
- package_telnet-server_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_telnet-server
class remove_telnet-server {
package { 'telnet-server':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove telnet-server
# from the system, and may remove any packages
# that depend on telnet-server. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "telnet-server"
|
Remove telnet Clients
[ref]ruleThe telnet client allows users to start connections to other systems via
the telnet protocol. Rationale:The telnet protocol is insecure and unencrypted. The use
of an unencrypted transmission medium could allow an unauthorized user
to steal credentials. The ssh package provides an
encrypted session and stronger security and is included in Debian 12. References:
R62, 3.1.13, 164.308(a)(4)(i), 164.308(b)(1), 164.308(b)(3), 164.310(b), 164.312(e)(1), 164.312(e)(2)(ii), A.8.2.3, A.13.1.1, A.13.2.1, A.13.2.3, A.14.1.2, A.14.1.3, 2.2.4, 2.2 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure telnet is removed
package:
name: telnet
state: absent
tags:
- NIST-800-171-3.1.13
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- low_complexity
- low_disruption
- low_severity
- no_reboot_needed
- package_telnet_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_telnet
class remove_telnet {
package { 'telnet':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove telnet
# from the system, and may remove any packages
# that depend on telnet. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "telnet"
|
TFTP Server
[ref]groupTFTP is a lightweight version of the FTP protocol which has
traditionally been used to configure networking equipment. However,
TFTP provides little security, and modern versions of networking
operating systems frequently support configuration via SSH or other
more secure protocols. A TFTP server should be run only if no more
secure method of supporting existing equipment can be
found. |
contains 2 rules |
Uninstall tftp-server Package
[ref]ruleThe tftp-server package can be removed with the following command: $ apt-get remove tftp-server Rationale:Removing the tftp-server package decreases the risk of the accidental
(or intentional) activation of tftp services.
If TFTP is required for operational support (such as transmission of router
configurations), its use must be documented with the Information Systems
Securty Manager (ISSM), restricted to only authorized personnel, and have
access control rules established. References:
R62, 11, 12, 14, 15, 3, 8, 9, APO13.01, BAI10.01, BAI10.02, BAI10.03, BAI10.05, DSS01.04, DSS05.02, DSS05.03, DSS05.05, DSS06.06, CCI-000366, 4.3.3.5.1, 4.3.3.5.2, 4.3.3.5.3, 4.3.3.5.4, 4.3.3.5.5, 4.3.3.5.6, 4.3.3.5.7, 4.3.3.5.8, 4.3.3.6.1, 4.3.3.6.2, 4.3.3.6.3, 4.3.3.6.4, 4.3.3.6.5, 4.3.3.6.6, 4.3.3.6.7, 4.3.3.6.8, 4.3.3.6.9, 4.3.3.7.1, 4.3.3.7.2, 4.3.3.7.3, 4.3.3.7.4, 4.3.4.3.2, 4.3.4.3.3, SR 1.1, SR 1.10, SR 1.11, SR 1.12, SR 1.13, SR 1.2, SR 1.3, SR 1.4, SR 1.5, SR 1.6, SR 1.7, SR 1.8, SR 1.9, SR 2.1, SR 2.2, SR 2.3, SR 2.4, SR 2.5, SR 2.6, SR 2.7, SR 3.1, SR 3.5, SR 3.8, SR 4.1, SR 4.3, SR 5.1, SR 5.2, SR 5.3, SR 7.1, SR 7.6, A.11.2.6, A.12.1.2, A.12.5.1, A.12.6.2, A.13.1.1, A.13.2.1, A.14.1.3, A.14.2.2, A.14.2.3, A.14.2.4, A.6.2.1, A.6.2.2, A.9.1.2, CM-7(a), CM-7(b), CM-6(a), PR.AC-3, PR.IP-1, PR.PT-3, PR.PT-4, 2.2.4, 2.2, SRG-OS-000480-GPOS-00227 Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure tftp-server is removed
package:
name: tftp-server
state: absent
tags:
- NIST-800-53-CM-6(a)
- NIST-800-53-CM-7(a)
- NIST-800-53-CM-7(b)
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- high_severity
- low_complexity
- low_disruption
- no_reboot_needed
- package_tftp-server_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_tftp-server
class remove_tftp-server {
package { 'tftp-server':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove tftp-server
# from the system, and may remove any packages
# that depend on tftp-server. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "tftp-server"
|
Remove tftp Daemon
[ref]ruleTrivial File Transfer Protocol (TFTP) is a simple file transfer protocol,
typically used to automatically transfer configuration or boot files between systems.
TFTP does not support authentication and can be easily hacked. The package
tftp is a client program that allows for connections to a tftp server. Rationale:It is recommended that TFTP be removed, unless there is a specific need
for TFTP (such as a boot server). In that case, use extreme caution when configuring
the services. Remediation Ansible snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
- name: Ensure tftp is removed
package:
name: tftp
state: absent
tags:
- PCI-DSSv4-2.2
- PCI-DSSv4-2.2.4
- disable_strategy
- low_complexity
- low_disruption
- low_severity
- no_reboot_needed
- package_tftp_removed
Remediation Puppet snippet: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
include remove_tftp
class remove_tftp {
package { 'tftp':
ensure => 'purged',
}
}
Remediation Shell script: (show)
Complexity: | low |
---|
Disruption: | low |
---|
Reboot: | false |
---|
Strategy: | disable |
---|
# CAUTION: This remediation script will remove tftp
# from the system, and may remove any packages
# that depend on tftp. Execute this
# remediation AFTER testing on a non-production
# system!
DEBIAN_FRONTEND=noninteractive apt-get remove -y "tftp"
|