Ensure PAM Enforces Password Requirements - Authentication Retry Prompts Permitted Per-Session
Description
To 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.
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\_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