Ensure PAM Enforces Password Requirements - Minimum Special Characters

Classification:

compliance

Framework:

Control:

Description

The 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.

Remediation

Shell script

The following script can be run on the host to remediate the issue.

# 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

Ansible playbook

The following playbook can be run with Ansible to remediate the issue.

- name: Gather the package facts
 package\_facts:
 manager: auto
 tags:
 - DISA-STIG-UBTU-20-010055
 - 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:
 - DISA-STIG-UBTU-20-010055
 - 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