In the previous part, Authentication Modules (PAM and Authselect) (CIS 5.3) was completed.
1. CIS Benchmark Requirements (Section 5.3.3)
- 5.3.3 Configure PAM Arguments
- 5.3.3.1 Configure pam_faillock module
- 5.3.3.1.1 Ensure password failed attempts lockout is configured (Automated)
- 5.3.3.1.2 Ensure password unlock time is configured (Automated)
- 5.3.3.1.3 Ensure password failed attempts lockout includes root account (Automated)
- 5.3.3.2 Configure pam_pwquality module
- 5.3.3.2.1 Ensure password number of changed characters is configured (Automated)
- 5.3.3.2.2 Ensure password length is configured (Automated)
- 5.3.3.2.3 Ensure password complexity is configured (Manual)
- 5.3.3.2.4 Ensure password same consecutive characters is configured (Automated)
- 5.3.3.2.5 Ensure password maximum sequential characters is configured (Automated)
- 5.3.3.2.6 Ensure password dictionary check is enabled (Automated)
- 5.3.3.2.7 Ensure password quality is enforced for the root user (Automated)
- 5.3.3.3 Configure pam_pwhistory module
- 5.3.3.3.1 Ensure password history remember is configured (Automated)
- 5.3.3.3.2 Ensure password history is enforced for the root user (Automated)
- 5.3.3.3.3 Ensure pam_pwhistory includes use_authtok (Automated)
- 5.3.3.4 Configure pam_unix module
- 5.3.3.4.1 Ensure pam_unix does not include nullok (Automated)
- 5.3.3.4.2 Ensure pam_unix does not include remember (Automated)
- 5.3.3.4.3 Ensure pam_unix includes a strong password hashing algorithm (Automated)
- 5.3.3.4.4 Ensure pam_unix includes use_authtok (Automated)
- 5.3.3.1 Configure pam_faillock module
2. Concept & Rationale
- Lockout with pam_faillock: After a specified number of failed login attempts (e.g., 5 times), the user account is locked for a defined period (e.g., 900 seconds). This policy is designed to prevent brute-force password guessing attacks and must also apply to the
rootuser (even_deny_root). - Password quality with pam_pwquality: Enforces requirements such as minimum password length (e.g., 14 characters), dictionary word checking (
dictcheck), preventing excessive repetition of consecutive characters (maxrepeat), and ensuring these strict policies are also applied to therootuser. - Password history with pam_pwhistory: Retains previous passwords (e.g., the last 5 passwords) to prevent users from reusing them.
- Base management with pam_unix: Completely blocks the ability to log in with an empty password (
nullok) and requires the system to use strong hashing algorithms (such asyescryptorsha512).
3. Oracle Database Compatibility (RAC, ASM, Grid)
Conflict level: Medium to High
Oracle-specific considerations:
- User lockout crisis (faillock): Applying failed login restrictions to critical users such as
oracle,grid, or automation accounts (like OEM Agents) is highly dangerous. Stale connections, scripts with expired passwords, or failed monitoring attempts can lock these users and cause cluster disruption or a complete database outage. These accounts must be excluded from the lockout process in the/etc/security/faillock.conffile. - Automated installations (pwquality): When running automation scripts (such as Ansible) responsible for creating database or OS users, generated passwords must strictly comply with these complexity rules; otherwise, the provisioning and installation process will halt with an authentication error.
4. How to Audit (Audit Script)
GitHub link for this script: modules/audit_19_PAM_Arguments.sh
If you are not familiar with Bash scripting, you can refer to the training published for database administrators on the site: Bash for Oracle DBAs.
#!/bin/bash
# Script: audit19.sh
# Purpose: Audit Script for Faillock & Password Quality (CIS Section 19)
echo "=========================================================================="
echo " CIS Requirement: Password Policies & Lockout Mechanisms"
echo " - Ensure faillock locks out users after 5 failed attempts for 15 mins."
echo " - Ensure pwquality enforces complexity (length, classes, dictcheck)."
echo " - Ensure password history remembers last 5 passwords."
echo " - Ensure yescrypt is used for password hashing."
echo " Oracle Context:"
echo " - WARNING: Strict faillock policies can lock out 'oracle' and 'grid'"
echo " users during automated deployments (Ansible/Terraform). A PAM bypass"
echo " should be implemented (covered in Sec 18) to avoid database outages."
echo "=========================================================================="
FAIL_COUNT=0
echo -e "\n[*] Checking faillock configuration (/etc/security/faillock.conf)..."
for param in "deny = 5" "unlock_time = 900" "even_deny_root"; do
if grep -q -E "^\s*${param}" /etc/security/faillock.conf; then
echo -e " \e[32m[PASS]\e[0m $param is configured."
else
echo -e " \e[31m[FAIL]\e[0m $param is missing or incorrect."
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
done
echo -e "\n[*] Checking pwquality configuration (/etc/security/pwquality.conf)..."
for param in "difok = 8" "minlen = 14" "minclass = 4" "maxrepeat = 3" "maxsequence = 3" "dictcheck = 1" "enforce_for_root"; do
if grep -q -E "^\s*${param}" /etc/security/pwquality.conf; then
echo -e " \e[32m[PASS]\e[0m $param is configured."
else
echo -e " \e[31m[FAIL]\e[0m $param is missing or incorrect."
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
done
echo -e "\n[*] Checking PAM configurations for pwhistory and yescrypt..."
for pam_file in /etc/authselect/system-auth /etc/authselect/password-auth; do
echo -e " \e[34m[INFO]\e[0m Checking $pam_file..."
if grep -E '^\s*password\s+requisite\s+pam_pwhistory.so' $pam_file | grep -q 'remember=5' && \
grep -E '^\s*password\s+requisite\s+pam_pwhistory.so' $pam_file | grep -q 'enforce_for_root'; then
echo -e " \e[32m[PASS]\e[0m pwhistory is set correctly."
else
echo -e " \e[31m[FAIL]\e[0m Missing correct pwhistory settings."
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
if grep -E '^\s*password\s+(sufficient|required)\s+pam_unix.so' $pam_file | grep -q 'yescrypt'; then
echo -e " \e[32m[PASS]\e[0m pam_unix is using yescrypt."
else
echo -e " \e[31m[FAIL]\e[0m yescrypt is not configured."
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
done
if [ "$FAIL_COUNT" -eq 0 ]; then
echo -e "\n\e[32m[+] AUDIT RESULT: PASS\e[0m"
else
echo -e "\n\e[31m[-] AUDIT RESULT: FAIL ($FAIL_COUNT issues found)\e[0m"
fi
5. How to Remediate with Bash (Remediation Script)
GitHub link for this script: modules/remediate_19_PAM_Arguments.sh
#!/bin/bash
# =====================================================================
# OS Security Standard Remediation Script - Section 19
# Oracle Context: Strict password policies and lockout mechanisms.
# Oracle Exception: High faillock deny counts could lock out 'oracle'
# or 'grid'.
# =====================================================================
# Ensure script is run as root
if [ "$EUID" -ne 0 ]; then
echo -e "\033[31m[ERROR] This script must be run as root.\033[0m"
exit 1
fi
echo -e "\033[36m--- Configuring faillock.conf ---\033[0m"
FAILLOCK_CONF="/etc/security/faillock.conf"
sed -i -E 's/^\s*#?\s*deny\s*=.*/deny = 5/' $FAILLOCK_CONF
sed -i -E 's/^\s*#?\s*unlock_time\s*=.*/unlock_time = 900/' $FAILLOCK_CONF
sed -i -E 's/^\s*#?\s*even_deny_root.*/even_deny_root/' $FAILLOCK_CONF
grep -q "^deny = 5" $FAILLOCK_CONF || echo "deny = 5" >> $FAILLOCK_CONF
grep -q "^unlock_time = 900" $FAILLOCK_CONF || echo "unlock_time = 900" >> $FAILLOCK_CONF
grep -q "^even_deny_root" $FAILLOCK_CONF || echo "even_deny_root" >> $FAILLOCK_CONF
echo -e "\033[36m--- Configuring pwquality.conf ---\033[0m"
PWQUAL_CONF="/etc/security/pwquality.conf"
sed -i -E 's/^\s*#?\s*difok\s*=.*/difok = 8/' $PWQUAL_CONF
sed -i -E 's/^\s*#?\s*minlen\s*=.*/minlen = 14/' $PWQUAL_CONF
sed -i -E 's/^\s*#?\s*minclass\s*=.*/minclass = 4/' $PWQUAL_CONF
sed -i -E 's/^\s*#?\s*maxrepeat\s*=.*/maxrepeat = 3/' $PWQUAL_CONF
sed -i -E 's/^\s*#?\s*maxsequence\s*=.*/maxsequence = 3/' $PWQUAL_CONF
sed -i -E 's/^\s*#?\s*dictcheck\s*=.*/dictcheck = 1/' $PWQUAL_CONF
sed -i -E 's/^\s*#?\s*enforce_for_root.*/enforce_for_root/' $PWQUAL_CONF
grep -q "^maxsequence = 3" $PWQUAL_CONF || echo "maxsequence = 3" >> $PWQUAL_CONF
echo -e "\033[36m--- Configuring Custom Authselect Profile (oracle-sssd) ---\033[0m"
CUSTOM_PROFILE_DIR="/etc/authselect/custom/oracle-sssd"
if [ ! -d "$CUSTOM_PROFILE_DIR" ]; then
echo -e "\033[33m[WARN] Custom profile 'oracle-sssd' not found. Creating it from sssd...\033[0m"
authselect create-profile oracle-sssd -b sssd --symlinks
fi
for pam_file in "$CUSTOM_PROFILE_DIR/system-auth" "$CUSTOM_PROFILE_DIR/password-auth"; do
if [ -f "$pam_file" ]; then
# 1. Update pam_unix.so to use yescrypt instead of sha512
sed -i 's/\bsha512\b/yescrypt/g' "$pam_file"
# 2. Add remember=5 and enforce_for_root to pam_pwhistory.so
# First ensure the line has the required parameters, if not, append them
if grep -q "pam_pwhistory.so" "$pam_file"; then
sed -i -E 's/(pam_pwhistory\.so.*)/\1/' "$pam_file"
# Safely add remember=5 if missing
if ! grep -q "pam_pwhistory.so.*remember=" "$pam_file"; then
sed -i 's/pam_pwhistory.so/pam_pwhistory.so remember=5/g' "$pam_file"
fi
# Safely add enforce_for_root if missing
if ! grep -q "pam_pwhistory.so.*enforce_for_root" "$pam_file"; then
sed -i 's/pam_pwhistory.so/pam_pwhistory.so enforce_for_root/g' "$pam_file"
fi
fi
fi
done
echo -e "\033[36m--- Applying Authselect Changes ---\033[0m"
# Re-apply the custom profile with required features
authselect select custom/oracle-sssd with-faillock without-nullok with-pwhistory --force
authselect apply-changes
echo -e "\033[32m[OK] Section 19 Remediation completed.\033[0m"
In the next part, we will cover Configuring Password Parameters.