securing oracle linux 9 article 18 authentication modules pam and authselect cis 5-3

In the previous part,

Securing Privilege Escalation was completed.

1. CIS Benchmark Requirements (Section 5.3)

The duplicate and disordered numbering has been corrected and aligned with the standard:

  • 5.3 Pluggable Authentication Modules
  • 5.3.1 Configure PAM software packages
  • 5.3.1.1 Ensure latest version of pam is installed (Automated)
  • 5.3.1.2 Ensure latest version of authselect is installed (Automated)
  • 5.3.1.3 Ensure latest version of libpwquality is installed (Automated)
  • 5.3.2 Configure authselect
  • 5.3.2.1 Ensure active authselect profile includes PAM modules (Automated)
  • 5.3.2.2 Ensure pam_faillock module is enabled (Automated)
  • 5.3.2.3 Ensure pam_pwquality module is enabled (Automated)
  • 5.3.2.4 Ensure pam_pwhistory module is enabled (Automated)
  • 5.3.2.5 Ensure pam_unix module is enabled (Automated)

2. Concept & Rationale

Concept: This section focuses on configuring the PAM (Pluggable Authentication Modules) infrastructure and centrally managing authentication policies through the authselect tool.

Security rationale:

  • Base packages (5.3.1): Oracle Linux 9 depends on the pam, authselect, and libpwquality packages for authentication management. Keeping these packages updated is essential for remediating security vulnerabilities.
  • Authselect management (5.3.2.1): In modern Linux releases such as EL9, manually editing files under /etc/pam.d/ is deprecated and unsafe. Integrated authselect profiles should be used instead.
  • Account lockout (5.3.2.2 - faillock): The pam_faillock module helps defend against brute-force attacks by temporarily locking an account after multiple failed login attempts.
  • Password complexity (5.3.2.3 - pwquality): Enforces stricter password rules such as minimum length, mixed case, numbers, and special characters.
  • Password history (5.3.2.4 - pwhistory): Prevents users from reusing previous passwords.
  • Secure hashing (5.3.2.5 - pam_unix): Ensures passwords are hashed and stored using strong modern algorithms such as yescrypt or sha512.

3. Oracle Database Compatibility (RAC, ASM, Grid)

Conflict level: Low to medium (requires careful handling for automation and system accounts)

Oracle-specific considerations:

  • Interaction with faillock: In Oracle RAC environments, monitoring scripts such as Oracle Enterprise Manager (OEM), cluster processes, or automated logins may generate failed attempts because of transient network issues or configuration mistakes. If faillock is active, critical accounts such as oracle or grid may become locked, potentially causing a full database service outage.
  • Recommended solution: Oracle system accounts such as oracle and grid should be excluded from lockout restrictions. This can be implemented through /etc/security/faillock.conf or related management parameters.
  • Interaction with pwquality: During silent Grid Infrastructure or database installations, or when using provisioning tools such as Ansible or Terraform, generated and injected passwords for database or operating system users must comply with the active pam_pwquality policy. Otherwise, installation may fail because the password is rejected.

4. How to Audit (Audit Script)

The following script checks whether the required packages are installed and verifies the active authselect profile:

GitHub link for this script: modules/audit_18_PAM_Authselect.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: audit18.sh
# Purpose: Audit Script for PAM, Authselect & Oracle Faillock Bypass (CIS 5.3)

if [ "$EUID" -ne 0 ]; then
    echo -e "\e[31m[!] Please run as root\e[0m"
    exit 1
fi

FAIL_COUNT=0

echo "=========================================================================="
echo " Audit Script for PAM Packages & Authselect Profile (CIS 5.3)"
echo " Context: EL9 authselect requires 'with-faillock' and 'without-nullok'."
echo " Exception (Oracle): 'oracle' and 'grid' must be bypassed in PAM to avoid DB outage."
echo "=========================================================================="

echo -e "\n[*] Checking required PAM packages..."
check_package() {
    local pkg=$1
    if rpm -q "$pkg" >/dev/null 2>&1; then
        echo -e "  \e[32m[PASS]\e[0m Package '$pkg' is installed"
    else
        echo -e "  \e[31m[FAIL]\e[0m Package '$pkg' is NOT installed"
        ((FAIL_COUNT++))
    fi
}

check_package "pam"
check_package "authselect"
check_package "libpwquality"

echo -e "\n[*] Checking Authselect Profile configuration..."
CURRENT_PROFILE=$(authselect current 2>/dev/null | head -n 1 | awk '{print $3}')

if [ -z "$CURRENT_PROFILE" ] || [[ "$CURRENT_PROFILE" == "No" ]]; then
    echo -e "  \e[31m[FAIL]\e[0m No authselect profile is currently active"
    ((FAIL_COUNT++))
else
    echo -e "  \e[32m[PASS]\e[0m Active authselect profile: $CURRENT_PROFILE"

    check_authselect_feature() {
        local feature=$1
        if authselect current 2>/dev/null | grep -qw "$feature"; then
            echo -e "  \e[32m[PASS]\e[0m Feature '$feature' is enabled"
        else
            echo -e "  \e[31m[FAIL]\e[0m Feature '$feature' is missing"
            ((FAIL_COUNT++))
        fi
    }

    check_authselect_feature "with-faillock"
    check_authselect_feature "without-nullok"
fi

echo -e "\n[*] Checking Oracle/Grid Faillock Bypass..."
if grep -q "pam_succeed_if.so user in oracle:grid" /etc/pam.d/system-auth 2>/dev/null; then
    echo -e "  \e[32m[PASS]\e[0m Oracle/Grid accounts are successfully excluded from faillock rules"
else
    echo -e "  \e[31m[FAIL]\e[0m Oracle/Grid accounts are NOT excluded from faillock (High Risk for DB!)"
    ((FAIL_COUNT++))
fi

echo "=========================================================================="
if [ $FAIL_COUNT -eq 0 ]; then
    echo -e "\e[32m[+] AUDIT PASSED: PAM, Authselect, and Oracle Exceptions are perfectly configured.\e[0m"
else
    echo -e "\e[31m[-] AUDIT FAILED: $FAIL_COUNT issue(s) found. Run remediation18.sh.\e[0m"
fi

5. How to Remediate with Bash (Remediation Script)

This script installs the required packages and configures the authselect profile with the necessary security modules enabled:

GitHub link for this script: modules/remediate_18_PAM_Authselect.sh

#!/bin/bash
# Script: remediation18.sh
# Purpose: Remediation Script for PAM & Authselect with Oracle Exclusions (CIS 5.3)

if [ "$EUID" -ne 0 ]; then
    echo -e "\e[31m[!] Please run as root\e[0m"
    exit 1
fi

echo "=========================================================================="
echo " Remediation Script for PAM Packages & Authselect Profile (CIS 5.3)"
echo " Action: Creating custom authselect profile to implement 'with-faillock'"
echo "         while explicitly excluding 'oracle' and 'grid' accounts."
echo "=========================================================================="

# Variables for custom profile
CUSTOM_PROFILE_NAME="oracle-sssd"
BASE_PROFILE="sssd"
CUSTOM_DIR="/etc/authselect/custom/$CUSTOM_PROFILE_NAME"

echo -e "\n[*] 1. Creating Custom Authselect Profile for Oracle..."
# Ensure any broken previous attempts are cleaned up
rm -rf "$CUSTOM_DIR"

echo "Creating custom profile '$CUSTOM_PROFILE_NAME' based on '$BASE_PROFILE'..."
# Without --symlinks to ensure physical files are copied and modifiable
authselect create-profile "$CUSTOM_PROFILE_NAME" -b "$BASE_PROFILE"

if [ ! -d "$CUSTOM_DIR" ]; then
    echo -e "\e[31m[!] Error: Failed to create custom authselect profile!\e[0m"
    exit 1
fi

echo -e "\n[*] 2. Injecting Faillock Bypass logic for 'oracle' and 'grid' users..."
BYPASS_RULE="auth        [success=1 default=ignore]                   pam_succeed_if.so user in oracle:grid"

for pam_file in system-auth password-auth; do
    FILE_PATH="$CUSTOM_DIR/$pam_file"
    if [ -f "$FILE_PATH" ]; then
        # Insert bypass rule right above the first occurrence of pam_faillock preauth
        sed -i "/pam_faillock.so preauth/i $BYPASS_RULE" "$FILE_PATH"

        # Insert bypass rule right above pam_faillock authfail
        sed -i "/pam_faillock.so authfail/i $BYPASS_RULE" "$FILE_PATH"

        # Insert bypass rule right above pam_faillock authsucc
        sed -i "/pam_faillock.so authsucc/i $BYPASS_RULE" "$FILE_PATH"

        echo " -> Injected successfully into $pam_file"
    else
        echo " -> Warning: File $pam_file not found in custom directory!"
    fi
done

echo -e "\n[*] 3. Applying the new Custom Oracle Profile..."
# Select the profile. In EL9 the path prefix 'custom/' is required.
authselect select "custom/$CUSTOM_PROFILE_NAME" with-faillock without-nullok --force

echo -e "\n[*] 4. Forcing Authselect changes to PAM stack..."
authselect apply-changes

echo -e "\n[*] Current Authselect Configuration:"
authselect current

echo "=========================================================================="
echo -e "\e[32m[+] Remediation completed.\e[0m"
echo -e "Please run audit18.sh to verify."

In the next part, we will cover:

Configuring Authentication Module Arguments.