securing oracle linux 9 article 17 securing privilege escalation cis 5-2

In the previous part,

Configuring and Securing the SSH Service (CIS 5.1) was covered.

1. CIS Benchmark Requirements (Section 5.2)

  • 5.2 Configure privilege escalation
  • 5.2.1 Ensure sudo is installed (Automated)
  • 5.2.2 Ensure sudo commands use pty (Automated)
  • 5.2.3 Ensure sudo log file exists (Automated)
  • 5.2.4 Ensure users must provide password for escalation (Automated)
  • 5.2.5 Ensure re-authentication for privilege escalation is not disabled globally (Automated)
  • 5.2.6 Ensure sudo authentication timeout is configured correctly (Automated)
  • 5.2.7 Ensure access to the su command is restricted (Automated)

2. Concept & Rationale

Concept: This section focuses on the secure management of sudo and su. The goal is privilege escalation that is controlled, auditable, and protected against malware.

Security rationale:

  • 5.2.1 (sudo): The preferred way to grant administrative access without exposing the root password.
  • 5.2.2 (pty): The use_pty parameter forces sudo to run in a pseudo-terminal, reducing the risk of background malware sniffing or injecting commands.
  • 5.2.3 (logfile): Logging commands to a dedicated file (for example /var/log/sudo.log) is essential for auditing.
  • 5.2.4 and 5.2.5: Prevents global use of NOPASSWD and !authenticate so users cannot obtain admin access without authentication.
  • 5.2.6 (timeout): Limits how long sudo authentication remains valid (typically 15 minutes) so abandoned sessions are not abused.
  • 5.2.7 (su): With pam_wheel.so, only members of the wheel group can use su to switch users (in this series we use a dedicated sugroup instead—see below).

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

Conflict level: Medium (exceptions needed in automation and access rules)

Oracle notes and requirements:

  • PTY (use_pty / requiretty): Oracle automation (backup cron jobs as oracle, OEM jobs, and similar) that run without a TTY will fail with sorry, you must have a tty to run sudo. Remediation: Add an exception such as !use_pty only for the oracle user in /etc/sudoers.d.
  • Password requirement (NOPASSWD): Oracle provisioning and clustering tools (Oracle FPP, Ansible for Grid/RDBMS, running root.sh, and similar) often need NOPASSWD for specific users or commands. CIS disallows applying that globally; scoped NOPASSWD for Oracle-related users or commands is acceptable and usually required.
  • Restricting su (pam_wheel): DBAs often log in with a personal account and run su - oracle. With this control enabled, they must be in the group allowed to use su. We create a group named sugroup; otherwise they see Permission denied.

4. How to Audit (Audit Script)

The script below audits sudo and su settings:

Script on GitHub: modules/audit_17_Privilege_Escalation.sh

If you are new to Bash scripts, see the tutorial for database administrators on the site: Bash for Oracle DBAs.

#!/bin/bash
# Script: audit17.sh
# Purpose: Audit Script for Sudo and su (CIS 5.3 & 5.6)

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 Sudo & su (CIS 5.3 & 5.6)"
echo " Oracle Context: oracle/grid users need 'su -' access without being sudoers."
echo " Oracle Exception: Using custom 'sugroup' instead of default 'wheel'."
echo "=========================================================================="

echo -e "\n[*] Checking if sudo is installed..."
if rpm -q sudo >/dev/null 2>&1; then
    echo -e "  \e[32m[PASS]\e[0m sudo is installed"
else
    echo -e "  \e[31m[FAIL]\e[0m sudo is not installed"
    ((FAIL_COUNT++))
fi

echo -e "\n[*] Checking sudo configuration (Defaults)..."
check_sudo_default() {
    local param=$1
    if grep -rEi "^\s*Defaults\s+([^#]+,\s*)?${param}" /etc/sudoers /etc/sudoers.d/* >/dev/null 2>&1; then
        echo -e "  \e[32m[PASS]\e[0m sudo is configured with $param"
    else
        echo -e "  \e[31m[FAIL]\e[0m sudo is missing configuration for $param"
        ((FAIL_COUNT++))
    fi
}

check_sudo_default "use_pty"
check_sudo_default "logfile"
check_sudo_default "timestamp_timeout"

echo -e "\n[*] Checking for '!authenticate' in sudoers..."
if grep -rEi "^\s*[^#].*!authenticate" /etc/sudoers /etc/sudoers.d/* >/dev/null 2>&1; then
    echo -e "  \e[31m[FAIL]\e[0m Found '!authenticate' in sudo configuration"
    ((FAIL_COUNT++))
else
    echo -e "  \e[32m[PASS]\e[0m No '!authenticate' found in sudo configuration"
fi

echo -e "\n[*] Checking 'su' restrictions (pam_wheel.so) and groups..."
if grep -Eq "^\s*auth\s+(required|requisite)\s+pam_wheel\.so\s+.*group=sugroup" /etc/pam.d/su; then
    echo -e "  \e[32m[PASS]\e[0m pam_wheel.so is configured with group=sugroup in /etc/pam.d/su"
else
    echo -e "  \e[31m[FAIL]\e[0m pam_wheel.so with group=sugroup is not properly configured in /etc/pam.d/su"
    ((FAIL_COUNT++))
fi

# Check if sugroup exists and users are members
if getent group sugroup >/dev/null 2>&1; then
    echo -e "  \e[32m[PASS]\e[0m Group 'sugroup' exists"
    for u in oracle grid; do
        if id "$u" >/dev/null 2>&1; then # Check if user exists on system
            if id -nG "$u" | grep -qw "sugroup"; then
                echo -e "  \e[32m[PASS]\e[0m User $u is a member of 'sugroup'"
            else
                echo -e "  \e[31m[FAIL]\e[0m User $u is NOT a member of 'sugroup'"
                ((FAIL_COUNT++))
            fi
        fi
    done
else
    echo -e "  \e[31m[FAIL]\e[0m Group 'sugroup' does not exist"
    ((FAIL_COUNT++))
fi

# Ensure Oracle users are NOT in wheel group
for u in oracle grid; do
    if id "$u" >/dev/null 2>&1; then
        if id -nG "$u" | grep -qw "wheel"; then
            echo -e "  \e[31m[FAIL]\e[0m User $u is in 'wheel' (Should be removed to prevent sudo access)"
            ((FAIL_COUNT++))
        else
            echo -e "  \e[32m[PASS]\e[0m User $u is safely NOT in 'wheel'"
        fi
    fi
done

echo "=========================================================================="
if [ $FAIL_COUNT -eq 0 ]; then
    echo -e "\e[32m[+] AUDIT PASSED: All Sudo & su settings meet CIS/Oracle requirements.\e[0m"
else
    echo -e "\e[31m[-] AUDIT FAILED: $FAIL_COUNT issue(s) found. Run remediation17.sh.\e[0m"
fi

5. How to Remediate with Bash (Remediation Script)

This script applies sudo settings in a safe drop-in file and removes unsafe global directives:

Script on GitHub: modules/remediate_17_Privilege_Escalation.sh

#!/bin/bash
# Remediation Script for CIS 5.3 & 5.6 - Sudo and su Configuration
# Direct configuration of sudoers and pam (Oracle RAC Compatible)

# 1. Check if running as root
if [ "$EUID" -ne 0 ]; then
  echo -e "\033[31m[-] Please run as root.\033[0m"
  exit 1
fi

SUDOERS_FILE="/etc/sudoers"
PAM_SU_FILE="/etc/pam.d/su"
BACKUP_SUFFIX=".bak.$(date +%F_%T)"

# 2. Backup the original files
echo -e "\033[34m[*] Backing up configuration files...\033[0m"
cp -p "$SUDOERS_FILE" "${SUDOERS_FILE}${BACKUP_SUFFIX}"
cp -p "$PAM_SU_FILE" "${PAM_SU_FILE}${BACKUP_SUFFIX}"

# 3. Ensure sudo is installed
echo -e "\033[34m[*] Ensuring sudo is installed...\033[0m"
dnf install -y sudo > /dev/null 2>&1

# 4. Configure Sudo Defaults
echo -e "\033[34m[*] Applying CIS Sudo Defaults (use_pty, logfile, timestamp_timeout)...\033[0m"
cat << 'EOF' > /etc/sudoers.d/99-cis-sudo-defaults
Defaults use_pty
Defaults logfile="/var/log/sudo.log"
Defaults timestamp_timeout=15
EOF
chmod 0440 /etc/sudoers.d/99-cis-sudo-defaults

# 5. Remove !authenticate
echo -e "\033[34m[*] Removing '!authenticate' from sudoers files...\033[0m"
sed -i 's/!authenticate//g' /etc/sudoers
for f in /etc/sudoers.d/*; do
  if [ -f "$f" ]; then
    sed -i 's/!authenticate//g' "$f"
  fi
done


# 6. Restrict 'su' to a specific group (e.g., 'sugroup') to prevent granting sudo access
echo -e "\033[34m[*] Restricting 'su' command to 'sugroup' in pam...\033[0m"

# Create the group if it does not exist
groupadd -f sugroup

# Add Oracle users to this group
usermod -aG sugroup oracle 2>/dev/null
usermod -aG sugroup grid 2>/dev/null

# Configure pam_wheel to use this specific group (preventing interference with wheel and sudo)
if grep -q "pam_wheel.so" "$PAM_SU_FILE"; then
    sed -i 's/^#\s*auth\s*required\s*pam_wheel.so.*/auth            required        pam_wheel.so use_uid group=sugroup/' "$PAM_SU_FILE"
    sed -i 's/^auth\s*required\s*pam_wheel.so.*/auth            required        pam_wheel.so use_uid group=sugroup/' "$PAM_SU_FILE"
else
    sed -i '/pam_rootok.so/a auth            required        pam_wheel.so use_uid group=sugroup' "$PAM_SU_FILE"
fi

# 7. Add Oracle/Grid to wheel group (Oracle Exception)
echo -e "\033[34m[*] Adding Oracle and Grid users to 'wheel' group...\033[0m"
for user in oracle grid; do
    if id "$user" &>/dev/null; then
        usermod -aG wheel "$user"
    fi
done

# 8. Check syntax
echo -e "\033[34m[*] Checking sudoers configuration syntax...\033[0m"
if visudo -c >/dev/null 2>&1; then
    echo -e "\033[32m[+] Syntax OK. Remediation completed successfully.\033[0m"
else
    echo -e "\033[31m[-] Syntax error detected in sudoers. Restoring backup...\033[0m"
    cp -p "${SUDOERS_FILE}${BACKUP_SUFFIX}" "$SUDOERS_FILE"
    rm -f /etc/sudoers.d/99-cis-sudo-defaults
    exit 1
fi

In the next part we cover:

Authentication Modules (PAM and authselect) (CIS 5.3).


Previous article: Article 16 — SSH (CIS 5.1)

Next article: Article 18 — PAM and authselect (CIS 5.3)