CIS-Aligned Oracle DB-Compatible Build Runbook for OEL 8,9,10

 

Overview and Scope

This runbook provides a step-by-step procedure for building and hardening Oracle Linux 8, 9, and 10 servers across any virtualization or cloud platform. This runbook applies a CIS Level 1-aligned hardening baseline for Oracle Linux 8/9/10, with documented exceptions where strict CIS controls conflict with Oracle Database, Grid Infrastructure, or middleware operational requirements. Final compliance must be validated with the applicable CIS benchmark version and a scanner such as CIS-CAT or OpenSCAP.

Design Principles

       Every change is logged to /var/log/hardening/changes.log with timestamp, original value, and new value.

       A pre-hardening snapshot of all modified files is taken so any individual change can be rolled back.

       CIS controls that conflict with Oracle Database kernel, network, or security requirements are explicitly skipped with justification.

       Platform-specific guest agent and driver steps are isolated so the same core runbook applies everywhere.

Supported Platforms

Platform

Guest Agent / Drivers

Notes

VMware ESXi

open-vm-tools

Paravirtual SCSI and VMXNET3 recommended

Nutanix AHV

nutanix-guest-tools (NGT)

VirtIO drivers included in OL kernel

KVM / libvirt

qemu-guest-agent

VirtIO disk and network recommended

Hyper-V

hyperv-daemons

Built into OL kernel as LIS modules

OCI

oracle-cloud-agent

OCA installed from OL repos

AWS

amazon-ssm-agent, cloud-init

ENA and NVMe drivers in-kernel

Azure

WALinuxAgent, cloud-init

Accelerated Networking supported

GCP

google-compute-engine, cloud-init

gVNIC recommended


CIS Controls Intentionally Skipped for Oracle DB Compatibility

The following CIS recommendations are intentionally relaxed or skipped because strict enforcement would break Oracle Database installation, ASM, Grid Infrastructure, or runtime behavior. Each entry lists the CIS control ID, the conflict, and the safe alternative applied by this runbook.

CIS Control

Reason for Skip / Relaxation

Alternative Applied

1.1.x – Separate partitions for /tmp, /var, /var/log

Oracle Installer requires flexible /tmp (noexec breaks runInstaller). ASM may need /dev/shm without noexec.

Partitions created but noexec NOT set on /tmp and /dev/shm. nosuid,nodev applied.

1.5.x – core dump restrictions

Oracle DB may require core dumps for diagnostic purposes (incident packaging).

core dumps disabled for non-oracle users. Oracle user allowed via limits.d override.

3.3.x – Disable IPv6

Oracle RAC and Grid Infrastructure require IPv6 for interconnect in some configurations.

IPv6 left enabled. Unused interfaces have privacy extensions disabled. Firewall rules restrict IPv6 traffic.

4.2.x – iptables/nftables strict rules

Oracle Net Listener (1521), EM Express (5500), ONS (6200), VIP, SCAN require open ports.

Firewalld used with a dedicated ‘oracle’ zone. Only required ports opened.

5.2.x – SSH MaxSessions=10

Oracle DBCA, EMCTL, and clusterware may require >10 concurrent SSH sessions from grid/oracle user.

MaxSessions set to 20. MaxStartups tuned for burst.

5.4.x – Restrictive umask (027)

Oracle mandates umask 022 for ORACLE_HOME installations. 027 causes permission errors in shared-home installs.

umask 022 set for oracle/grid users via profile.d. System default remains 027.

6.1.x – AIDE file integrity on all paths

Oracle binary patching (OPatch/datapatch) modifies thousands of files per patch. AIDE baseline changes cause false positives.

AIDE configured with exclusion rules for ORACLE_HOME, GRID_HOME, and Oracle Inventory.


Change Logging and Rollback Framework

Before any hardening step, the framework below must be deployed. It provides atomic logging of every change, automatic backup of original files, and a rollback script that can revert individual changes or the entire hardening run.


Deploy the Hardening Framework Script

Create /usr/local/sbin/hardening-framework.sh and source it from every subsequent step.

#!/usr/bin/env bash

# /usr/local/sbin/hardening-framework.sh

# Oracle Linux CIS Hardening – Logging & Rollback Framework

 

set -euo pipefail

 

export HARDEN_LOG_DIR="/var/log/hardening"

export HARDEN_BACKUP_DIR="/var/log/hardening/backups"

export HARDEN_RUN_ID=$(date +%Y%m%d_%H%M%S)

export HARDEN_CHANGELOG="${HARDEN_LOG_DIR}/changes_${HARDEN_RUN_ID}.log"

export HARDEN_ROLLBACK_SCRIPT="${HARDEN_LOG_DIR}/rollback_${HARDEN_RUN_ID}.sh"

 

mkdir -p "${HARDEN_LOG_DIR}" "${HARDEN_BACKUP_DIR}/${HARDEN_RUN_ID}"

 

echo '#!/usr/bin/env bash' > "${HARDEN_ROLLBACK_SCRIPT}"

echo '# Auto-generated rollback script for run ${HARDEN_RUN_ID}' >> "${HARDEN_ROLLBACK_SCRIPT}"

echo 'set -euo pipefail' >> "${HARDEN_ROLLBACK_SCRIPT}"

chmod 700 "${HARDEN_ROLLBACK_SCRIPT}"

 

log_change() {

  local STEP="$1" DESC="$2" BEFORE="$3" AFTER="$4"

  echo "[$(date -Iseconds)] STEP=${STEP} | ${DESC} | BEFORE=${BEFORE} | AFTER=${AFTER}" >> "${HARDEN_CHANGELOG}"

}

 

backup_file() {

  local FILE="$1"

  if [[ -f "${FILE}" ]]; then

    local BKUP="${HARDEN_BACKUP_DIR}/${HARDEN_RUN_ID}$(echo ${FILE} | tr '/' '_')"

    cp -a "${FILE}" "${BKUP}"

    echo "cp -a '${BKUP}' '${FILE}'" >> "${HARDEN_ROLLBACK_SCRIPT}"

    log_change "BACKUP" "Backed up ${FILE}" "original" "${BKUP}"

  fi

}

 

backup_sysctl() {

  local KEY="$1"

  local CURRENT=$(sysctl -n "${KEY}" 2>/dev/null || echo 'NOT_SET')

  echo "sysctl -w ${KEY}=${CURRENT}" >> "${HARDEN_ROLLBACK_SCRIPT}"

  echo "${CURRENT}"

}

 

echo "=== Hardening Run ${HARDEN_RUN_ID} started at $(date -Iseconds) ===" >> "${HARDEN_CHANGELOG}"

How to Use

1.    Source the framework at the start of every hardening session:

source /usr/local/sbin/hardening-framework.sh

2.    Before modifying any file, call backup_file:

backup_file /etc/ssh/sshd_config

3.    After each change, call log_change:

log_change "CIS-5.2.1" "Set SSH Protocol to 2" "not set" "Protocol 2"

4.    To roll back the entire run:

bash /var/log/hardening/rollback_<RUN_ID>.sh

5.    To roll back a single file, find it in the backup directory:

cp -a /var/log/hardening/backups/<RUN_ID>/_etc_ssh_sshd_config /etc/ssh/sshd_config

 

Important: Always test rollback on a non-production system first. After rollback, restart the affected services.

Pre-Hardening Prerequisites

Verify OS Version and Subscription

cat /etc/oracle-release

uname -r

# Ensure UEK (Unbreakable Enterprise Kernel) or RHCK is installed

# For OL8: UEK6 or UEK7

# For OL9: UEK7

# For OL10: UEK8

Register and Enable Repositories

# OL8

dnf install -y oraclelinux-release-el8

dnf config-manager --enable ol8_baseos_latest ol8_appstream ol8_UEKR7

 

# OL9

dnf install -y oraclelinux-release-el9

dnf config-manager --enable ol9_baseos_latest ol9_appstream ol9_UEKR7

 

# OL10

dnf install -y oraclelinux-release-el10

dnf config-manager --enable ol10_baseos_latest ol10_appstream ol10_UEKR8

Apply All Available Patches

dnf update -y

# Reboot into latest kernel if kernel was updated

needs-restarting -r || reboot

Install Platform-Specific Guest Tools

Run ONLY the block that matches your hypervisor or cloud platform:

# ── VMware ──

dnf install -y open-vm-tools

systemctl enable --now vmtoolsd

 

# ── Nutanix AHV ──

# NGT is typically mounted as a CD-ROM ISO from Prism

mount /dev/sr0 /mnt && /mnt/installer/linux/install_ngt.py && umount /mnt

 

# ── KVM / libvirt ──

dnf install -y qemu-guest-agent

systemctl enable --now qemu-guest-agent

 

# ── Hyper-V ──

dnf install -y hyperv-daemons

systemctl enable --now hypervkvpd hypervvssd hypervfcopyd

 

# ── OCI ──

dnf install -y oracle-cloud-agent

systemctl enable --now oracle-cloud-agent oracle-cloud-agent-updater

 

# ── AWS ──

dnf install -y amazon-ssm-agent cloud-init

systemctl enable --now amazon-ssm-agent

 

# ── Azure ──

dnf install -y WALinuxAgent cloud-init

systemctl enable --now waagent

 

# ── GCP ──

dnf install -y google-compute-engine google-osconfig-agent cloud-init

systemctl enable --now google-guest-agent google-osconfig-agent

Install Required Baseline Packages

dnf install -y aide audit chrony rsyslog firewalld policycoreutils-python-utils \

  libselinux-utils selinux-policy-targeted cronie sudo logrotate

Pre-Create Oracle-Required Users and Groups

This step ensures the oracle and grid users exist before hardening, so that hardening rules for password policies, umask, and resource limits can apply correct exceptions from the start.

groupadd -g 54321 oinstall

groupadd -g 54322 dba

groupadd -g 54323 oper

groupadd -g 54324 backupdba

groupadd -g 54325 dgdba

groupadd -g 54326 kmdba

groupadd -g 54327 asmdba

groupadd -g 54328 asmoper

groupadd -g 54329 asmadmin

groupadd -g 54330 racdba

useradd -u 54321 -g oinstall -G dba,oper,backupdba,dgdba,kmdba,racdba oracle

# For Grid Infrastructure / RAC (optional):

useradd -u 54322 -g oinstall -G dba,asmadmin,asmdba,asmoper grid

 

Note: GID/UID values above are Oracle-recommended defaults. Adjust to match your organization standards if needed but keep them consistent across RAC nodes for physical/VMs. Oracle RAC is generally not supported on most IaaS clouds; OCI provides RAC through supported Oracle Database services.

Filesystem and Partition Layout

CIS requires separate partitions for /tmp, /var, /var/log, /var/log/audit, /var/tmp, and /home. The table below shows recommended sizes factoring in Oracle Database requirements.

 

Mount Point

Min Size

Mount Options

CIS Ref

Oracle Notes

/

20 GB

defaults

OS root

/tmp

10 GB

nosuid,nodev

1.1.2–1.1.5

noexec NOT set – Oracle runInstaller uses /tmp for exec

/var

20 GB

nosuid,nodev

1.1.6–1.1.7

Oracle logs and diagnostic data may land here

/var/log

10 GB

nosuid,nodev,noexec

1.1.11–1.1.13

Audit + app logs

/var/log/audit

5 GB

nosuid,nodev,noexec

1.1.14

Auditd dedicated

/var/tmp

10 GB

nosuid,nodev

1.1.8–1.1.10

Bind mount to /tmp or separate; noexec NOT set

/home

20 GB

nosuid,nodev

1.1.15–1.1.17

Oracle user home dirs

/dev/shm

tmpfs

nosuid,nodev

1.1.18–1.1.20

noexec NOT set – Oracle SGA uses shared memory segments

/opt/oracle

100 GB+

defaults

ORACLE_BASE (DB software, homes)

/u01 or ASM

Variable

defaults

Data files – ASM or filesystem

swap

16 GB+

swap

Oracle requires 16 GB+ swap for large SGA configs

These partitions usually not available from default cloud images, but possible with custom images / extra block volumes / manual LVM layouts. For VMWare, Nutanix, Hyper-V, KVM etc or even baremetal installations these can be done.

Apply Mount Options

source /usr/local/sbin/hardening-framework.sh

 

backup_file /etc/fstab

 

# Ensure /tmp has nosuid,nodev but NOT noexec

# Check current fstab entry for /tmp and modify:

sed -i '/\/tmp/ s/defaults/nosuid,nodev/' /etc/fstab

 

# /dev/shm – nosuid,nodev (NO noexec for Oracle SGA)

grep -q '/dev/shm' /etc/fstab || \

  echo 'tmpfs /dev/shm tmpfs nosuid,nodev 0 0' >> /etc/fstab

 

# Remount all affected partitions

mount -o remount /tmp

mount -o remount /dev/shm

log_change "CIS-1.1" "Set mount options for /tmp and /dev/shm" "defaults" "nosuid,nodev"


CIS Hardening Steps (Oracle DB Compatible)

Each step below includes the CIS control reference, the exact commands, change logging calls, and notes on Oracle compatibility where relevant. Source the hardening framework before beginning:

source /usr/local/sbin/hardening-framework.sh

Disable Unused Filesystems (CIS 1.1.1.x)

backup_file /etc/modprobe.d/CIS.conf

 

cat > /etc/modprobe.d/CIS.conf << 'EOF'

install cramfs /bin/true

install squashfs /bin/true

install udf /bin/true

install usb-storage /bin/true

install vfat /bin/true

EOF

 

log_change "CIS-1.1.1" "Disabled cramfs, squashfs, udf, usb-storage, vfat" "modules loadable" "install /bin/true"

Oracle Note: None of these filesystem modules are required by Oracle DB or middleware.

Configure GRUB Bootloader Permissions (CIS 1.4.x)

backup_file /boot/grub2/grub.cfg

backup_file /boot/grub2/user.cfg

 

chown root:root /boot/grub2/grub.cfg

chmod 600 /boot/grub2/grub.cfg

 

# Set GRUB password (interactive – will prompt)

grub2-setpassword

 

log_change "CIS-1.4.1" "Set grub.cfg ownership and permissions" "varied" "root:root 0600"

log_change "CIS-1.4.2" "Set GRUB bootloader password" "none" "password set"

Restrict Core Dumps (CIS 1.5.x)

backup_file /etc/security/limits.conf

 

# System-wide: disable core dumps

echo '* hard core 0' >> /etc/security/limits.conf

 

# Exception: allow Oracle user core dumps for diagnostics

cat > /etc/security/limits.d/99-oracle-coredump.conf << 'EOF'

oracle soft core unlimited

oracle hard core unlimited

grid   soft core unlimited

grid   hard core unlimited

EOF

backup_file /etc/sysctl.d/99-hardening.conf

echo 'fs.suid_dumpable = 0' >> /etc/sysctl.d/99-hardening.conf

sysctl -w fs.suid_dumpable=0

log_change "CIS-1.5.1" "Core dumps disabled system-wide, oracle/grid exempted" "not configured" "hard core 0 + oracle exception"

Kernel Sysctl Hardening (CIS 3.x)

This step applies all CIS-recommended kernel parameters for network and system hardening. Oracle-safe values are used where the CIS default would break database networking.

backup_file /etc/sysctl.d/99-hardening.conf

 

cat >> /etc/sysctl.d/99-hardening.conf << 'SYSCTL'

# ── Network Hardening (CIS 3.1.x, 3.2.x, 3.3.x) ──

net.ipv4.ip_forward = 0

net.ipv4.conf.all.send_redirects = 0

net.ipv4.conf.default.send_redirects = 0

net.ipv4.conf.all.accept_source_route = 0

net.ipv4.conf.default.accept_source_route = 0

net.ipv4.conf.all.accept_redirects = 0

net.ipv4.conf.default.accept_redirects = 0

net.ipv4.conf.all.secure_redirects = 0

net.ipv4.conf.default.secure_redirects = 0

net.ipv4.conf.all.log_martians = 1

net.ipv4.conf.default.log_martians = 1

net.ipv4.icmp_echo_ignore_broadcasts = 1

net.ipv4.icmp_ignore_bogus_error_responses = 1

net.ipv4.conf.all.rp_filter = 1

net.ipv4.conf.default.rp_filter = 1

net.ipv4.tcp_syncookies = 1

net.ipv6.conf.all.accept_ra = 0

net.ipv6.conf.default.accept_ra = 0

 

# ── Kernel Hardening ──

kernel.randomize_va_space = 2

kernel.yama.ptrace_scope = 1

 

# ── Oracle DB Specific Sysctl (NOT CIS but required) ──

# These are Oracle-recommended and should not be removed

kernel.shmmax = 4398046511104

kernel.shmall = 1073741824

kernel.shmmni = 4096

kernel.sem = 250 32000 100 128

fs.file-max = 6815744

fs.aio-max-nr = 1048576

net.ipv4.ip_local_port_range = 9000 65500

net.core.rmem_default = 262144

net.core.rmem_max = 4194304

net.core.wmem_default = 262144

net.core.wmem_max = 1048576

SYSCTL

 

sysctl --system

 

log_change "CIS-3.x" "Applied network and kernel hardening sysctls with Oracle DB parameters" "defaults" "CIS + Oracle combined"

 

Oracle Note: The Oracle-specific sysctl values (shmmax, shmall, sem, file-max, aio-max-nr, ip_local_port_range, rmem/wmem) are mandatory Oracle prerequisites. They do not conflict with any CIS controls. Values must be derived based on system memory and SGA sizing.

Firewall Configuration (CIS 3.5.x)

systemctl enable --now firewalld

 

# Create a dedicated Oracle zone

firewall-cmd --permanent --new-zone=oracle 2>/dev/null || true

 

# Add trusted subnets for Oracle connectivity (ADJUST to your network)

firewall-cmd --permanent --zone=oracle --add-source=10.0.0.0/8

 

# Oracle Listener

firewall-cmd --permanent --zone=oracle --add-port=1521/tcp

# EM Express

firewall-cmd --permanent --zone=oracle --add-port=5500/tcp

# ONS (for RAC)

firewall-cmd --permanent --zone=oracle --add-port=6200/tcp

# Oracle Notification Services (FAN)

firewall-cmd --permanent --zone=oracle --add-port=6100/tcp

 

# Restrict default zone

firewall-cmd --permanent --zone=public --remove-service=cockpit 2>/dev/null || true

firewall-cmd --permanent --zone=public --remove-service=dhcpv6-client 2>/dev/null || true

 

# SSH remains in public zone

firewall-cmd --permanent --zone=public --add-service=ssh

 

firewall-cmd --reload

 

log_change "CIS-3.5" "Configured firewalld with oracle zone, opened DB ports" "no firewall" "firewalld active, oracle zone created"

Auditd Configuration (CIS 4.1.x)

backup_file /etc/audit/auditd.conf

backup_file /etc/audit/rules.d/audit.rules

 

# Set audit log retention

sed -i 's/^max_log_file .*/max_log_file = 50/' /etc/audit/auditd.conf

sed -i 's/^max_log_file_action.*/max_log_file_action = keep_logs/' /etc/audit/auditd.conf

sed -i 's/^space_left_action.*/space_left_action = email/' /etc/audit/auditd.conf

sed -i 's/^admin_space_left_action.*/admin_space_left_action = halt/' /etc/audit/auditd.conf

 

# CIS audit rules

cat > /etc/audit/rules.d/cis-hardening.rules << 'AUDIT'

# Time change events

-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change

-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change

-a always,exit -F arch=b64 -S clock_settime -k time-change

-w /etc/localtime -p wa -k time-change

 

# Identity changes

-w /etc/group -p wa -k identity

-w /etc/passwd -p wa -k identity

-w /etc/gshadow -p wa -k identity

-w /etc/shadow -p wa -k identity

-w /etc/security/opasswd -p wa -k identity

 

# System locale changes

-a always,exit -F arch=b64 -S sethostname -S setdomainname -k system-locale

-w /etc/issue -p wa -k system-locale

-w /etc/issue.net -p wa -k system-locale

-w /etc/hostname -p wa -k system-locale

 

# Login/logout tracking

-w /var/log/lastlog -p wa -k logins

-w /var/run/faillock/ -p wa -k logins

 

# Session initiation

-w /var/run/utmp -p wa -k session

-w /var/log/wtmp -p wa -k session

-w /var/log/btmp -p wa -k session

 

# Permission changes

-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -F auid>=1000 -F auid!=4294967295 -k perm_mod

-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -F auid>=1000 -F auid!=4294967295 -k perm_mod

 

# Privileged commands

-a always,exit -F path=/usr/bin/sudo -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged

-a always,exit -F path=/usr/bin/su -F perm=x -F auid>=1000 -F auid!=4294967295 -k privileged

 

# Make rules immutable (requires reboot to change)
# Apply immutable rule only after full validation. Requires reboot for modification.

-e 2

AUDIT

 

# Load rules

augenrules --load

systemctl restart auditd

 

log_change "CIS-4.1" "Configured auditd rules for CIS compliance" "default rules" "CIS hardening rules applied"

SSH Hardening (CIS 5.2.x)

backup_file /etc/ssh/sshd_config

 

cat > /etc/ssh/sshd_config.d/99-cis-hardening.conf << 'SSHD'

# CIS 5.2 SSH Server Configuration

Protocol 2

LogLevel VERBOSE

MaxAuthTries 4

IgnoreRhosts yes

HostbasedAuthentication no

PermitRootLogin no

PermitEmptyPasswords no

PermitUserEnvironment no

ClientAliveInterval 300

ClientAliveCountMax 3

LoginGraceTime 60

Banner /etc/issue.net

 

# Oracle-compatible: allow 20 sessions (CIS says 10, but DBCA needs more)

MaxSessions 20

MaxStartups 10:30:60

 

# Strong ciphers and MACs

Ciphers aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512,hmac-sha2-256

KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256

SSHD

 

# Set warning banner

echo 'Authorized users only. All activity is monitored and logged.' > /etc/issue.net

 

sshd -t && systemctl reload sshd

 

log_change "CIS-5.2" "Hardened SSH config (MaxSessions=20 for Oracle compat)" "defaults" "CIS hardened"

Password and Authentication Policies (CIS 5.3.x, 5.4.x)

backup_file /etc/login.defs

backup_file /etc/security/pwquality.conf

 

# Password aging (CIS 5.4.1)

sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 365/' /etc/login.defs

sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 1/' /etc/login.defs

sed -i 's/^PASS_WARN_AGE.*/PASS_WARN_AGE 14/' /etc/login.defs

 

# Password quality (CIS 5.3.1)

cat > /etc/security/pwquality.conf << 'PWQUAL'

minlen = 14

minclass = 4

dcredit = -1

ucredit = -1

ocredit = -1

lcredit = -1

maxrepeat = 3

PWQUAL

 

# Account lockout (CIS 5.3.2) – using faillock

# OL8/9 uses authselect with faillock
# Validate existing auth profile before applying.

authselect select sssd with-faillock --force 2>/dev/null || true

cat > /etc/security/faillock.conf << 'FAILLOCK'

deny = 5

unlock_time = 900

fail_interval = 900

even_deny_root

root_unlock_time = 60

FAILLOCK

 

log_change "CIS-5.3/5.4" "Password policies and faillock configured" "defaults" "CIS compliant"

User Environment and umask (CIS 5.4.4)

backup_file /etc/profile

backup_file /etc/bashrc

 

# System-wide umask = 027 (CIS default)

echo 'umask 027' > /etc/profile.d/cis-umask.sh

 

# Oracle user exception: must be 022 per Oracle installation docs

cat > /etc/profile.d/oracle-umask.sh << 'ORACLE_UMASK'

if [[ "$(id -un)" == "oracle" || "$(id -un)" == "grid" ]]; then

  umask 022

fi

ORACLE_UMASK

 

log_change "CIS-5.4.4" "Set system umask 027, oracle/grid umask 022" "default" "027 system, 022 oracle"

Oracle Resource Limits (CIS 5.4.5 + Oracle Prerequisites)

cat > /etc/security/limits.d/99-oracle-db.conf << 'LIMITS'

# Oracle Database required limits

oracle soft nofile  65536

oracle hard nofile  65536

oracle soft nproc   16384

oracle hard nproc   16384

oracle soft stack   10240

oracle hard stack   32768

oracle soft memlock unlimited

oracle hard memlock unlimited

 

# Grid user (if RAC / ASM)

grid   soft nofile  65536

grid   hard nofile  65536

grid   soft nproc   16384

grid   hard nproc   16384

grid   soft stack   10240

grid   hard stack   32768

grid   soft memlock unlimited

grid   hard memlock unlimited

LIMITS

 

log_change "CIS-5.4.5" "Oracle resource limits configured" "system defaults" "Oracle recommended values"

Chrony / NTP Configuration (CIS 2.2.1)

backup_file /etc/chrony.conf

 

# Use your organization NTP servers (example with public pools)

cat > /etc/chrony.conf << 'CHRONY'

# Adjust pool/server lines for your environment

pool 0.pool.ntp.org iburst

pool 1.pool.ntp.org iburst

pool 2.pool.ntp.org iburst

driftfile /var/lib/chrony/drift

makestep 1.0 3

rtcsync

keyfile /etc/chrony.keys

leapsectz right/UTC

logdir /var/log/chrony

CHRONY

 

systemctl enable --now chronyd

 

log_change "CIS-2.2.1" "Configured chronyd for NTP" "unconfigured" "chrony with pool servers"

Oracle Note: Accurate time synchronization is critical for Oracle RAC (CSS voting), Data Guard, and GoldenGate. Do not use ntpd and chronyd simultaneously.

SELinux Configuration (CIS 1.6.x)

backup_file /etc/selinux/config

 

# Set SELinux to Enforcing (CIS 1.6.1.2)

sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config

sed -i 's/^SELINUXTYPE=.*/SELINUXTYPE=targeted/' /etc/selinux/config

 

# Apply immediately

setenforce 1

 

log_change "CIS-1.6" "Set SELinux to enforcing/targeted" "$(getenforce)" "Enforcing"

Oracle Note: Oracle Database on OL8/9 supports SELinux in enforcing mode. If you encounter AVC denials during DB installation, use audit2allow to create a custom policy module rather than disabling SELinux.

Disable Unused Services (CIS 2.2.x)

# Disable services not needed for a database server

for SVC in avahi-daemon cups rpcbind nfs-server vsftpd dovecot smb named squid snmpd ypserv telnet.socket; do

  if systemctl is-enabled "${SVC}" 2>/dev/null | grep -q enabled; then

    systemctl disable --now "${SVC}"

    log_change "CIS-2.2" "Disabled service ${SVC}" "enabled" "disabled"

  fi

done

 

# Remove unnecessary packages

dnf remove -y xorg-x11-server-Xorg 2>/dev/null || true

Oracle Note: If Oracle Enterprise Manager (OEM) Agent requires SNMP, keep snmpd and harden its community strings instead.

Rsyslog Configuration (CIS 4.2.x)

backup_file /etc/rsyslog.conf

 

# Ensure rsyslog is running

systemctl enable --now rsyslog

 

# Set file permissions for new log files

echo '$FileCreateMode 0640' >> /etc/rsyslog.conf

 

# Remote logging (uncomment and adjust for your syslog server)

# echo '*.* action(type="omfwd" target="syslog.example.com" port="514" protocol="tcp")' >> /etc/rsyslog.conf

 

systemctl restart rsyslog

 

log_change "CIS-4.2" "Configured rsyslog with secure file permissions" "defaults" "FileCreateMode 0640"

 

Configure AIDE File Integrity Monitoring (CIS 1.3.x)

backup_file /etc/aide.conf

 

# Add Oracle exclusions to prevent false positives during patching

cat >> /etc/aide.conf << 'AIDE_EXCL'

 

# Oracle Database exclusions – these paths change during patching
# These exclusions reduce coverage and should be reviewed per environment risk policy.

!/opt/oracle

!/u01/app

!/u01/grid

!/home/oracle

!/home/grid

!/tmp

AIDE_EXCL

 

# Initialize AIDE database

aide --init

mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz

 

# Add daily AIDE check cron

echo '0 5 * * * root /usr/sbin/aide --check' > /etc/cron.d/aide-check

 

log_change "CIS-1.3" "AIDE initialized with Oracle path exclusions" "not configured" "AIDE active, Oracle paths excluded"

Cron and At Restrictions (CIS 5.1.x)

chown root:root /etc/crontab

chmod 600 /etc/crontab

chown root:root /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly

chmod 700 /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly

 

# Restrict cron and at access

echo 'root' > /etc/cron.allow

echo 'oracle' >> /etc/cron.allow

echo 'grid' >> /etc/cron.allow

chown root:root /etc/cron.allow

chmod 600 /etc/cron.allow

rm -f /etc/cron.deny

 

echo 'root' > /etc/at.allow

echo 'oracle' >> /etc/at.allow

chown root:root /etc/at.allow

chmod 600 /etc/at.allow

rm -f /etc/at.deny

 

log_change "CIS-5.1" "Restricted cron/at to root, oracle, grid" "open" "allow-list only"

Oracle Note: Oracle Database uses cron for automatic diagnostic collection (ADRCI), TFA, and custom backup scripts. The oracle and grid users must be allowed.

Sudo Configuration (CIS 5.3.x)

backup_file /etc/sudoers

 

# Use visudo or drop file in sudoers.d

cat > /etc/sudoers.d/99-cis-hardening << 'SUDO'

# Log all sudo commands

Defaults logfile="/var/log/sudo.log"

Defaults use_pty

Defaults timestamp_timeout=15

 

# Restrict su to wheel group

# Handled by PAM below

SUDO

 

chmod 440 /etc/sudoers.d/99-cis-hardening

 

# Restrict su access to wheel group (CIS 5.6)

backup_file /etc/pam.d/su

sed -i '/pam_wheel.so/s/^#//' /etc/pam.d/su

 

log_change "CIS-5.3/5.6" "Sudo hardened, su restricted to wheel group" "defaults" "CIS compliant"

File Permissions Hardening (CIS 6.1.x, 6.2.x)

System File Permissions

# Critical system files

chmod 644 /etc/passwd

chmod 000 /etc/shadow

chmod 644 /etc/group

chmod 000 /etc/gshadow

chmod 600 /etc/passwd-

chmod 600 /etc/shadow-

chmod 600 /etc/group-

chmod 600 /etc/gshadow-

 

chown root:root /etc/passwd /etc/shadow /etc/group /etc/gshadow

 

log_change "CIS-6.1" "System file permissions hardened" "varied" "CIS recommended"

Find and Report Unowned Files

# Audit – log files without valid owner or group

find / -xdev \( -nouser -o -nogroup \) -print >> ${HARDEN_CHANGELOG} 2>/dev/null

 

# Find world-writable files

find / -xdev -type f -perm -0002 -print >> ${HARDEN_CHANGELOG} 2>/dev/null

 

# Find SUID/SGID binaries for review

find / -xdev \( -perm -4000 -o -perm -2000 \) -type f -print >> ${HARDEN_CHANGELOG} 2>/dev/null

 

log_change "CIS-6.1/6.2" "Unowned, world-writable, and SUID/SGID files audited" "not audited" "logged to changelog"

Ensure No Legacy + Entries

# Check for legacy '+' entries in passwd, shadow, group

for f in /etc/passwd /etc/shadow /etc/group; do

  grep '^+:' "$f" && echo "WARNING: Legacy + entry found in $f" >> ${HARDEN_CHANGELOG}

done || true

Additional Security Controls

Disable USB Storage at Kernel Level (CIS 1.1.1.7)

Already handled in Section 5.1 via /etc/modprobe.d/CIS.conf

Banner Configuration (CIS 1.7.x)

backup_file /etc/motd

backup_file /etc/issue

 

cat > /etc/motd << 'MOTD'

*******************************************************************************

*  WARNING: This system is for authorized use only. All access and activity   *

*  are monitored, recorded, and subject to audit. Unauthorized use is         *

*  prohibited and may result in administrative, civil, or criminal action.    *

*******************************************************************************

MOTD

 

cp /etc/motd /etc/issue

cp /etc/motd /etc/issue.net

 

log_change "CIS-1.7" "Login banners configured" "default" "warning banner applied"

Disable Automatic Error Reporting

systemctl disable --now abrtd 2>/dev/null || true

dnf remove -y abrt 2>/dev/null || true

 

log_change "CIS-EXTRA" "Disabled abrtd automatic error reporting" "enabled" "removed"

Secure /etc/security/access.conf

backup_file /etc/security/access.conf

# Optionally restrict console login to specific groups

# echo '-:ALL EXCEPT root wheel oracle grid:ALL' >> /etc/security/access.conf

 

log_change "CIS-EXTRA" "access.conf reviewed" "default" "reviewed (manual enforcement optional)"

Post-Hardening Validation

Validation Checklist Script

Run the following script after hardening to confirm all controls are applied:

#!/usr/bin/env bash

# /usr/local/sbin/validate-hardening.sh

 

echo '=== Oracle Linux CIS Hardening Validation ==='

echo

 

# SELinux

echo -n '[CIS 1.6] SELinux: '

getenforce

 

# Firewalld

echo -n '[CIS 3.5] Firewalld: '

systemctl is-active firewalld

 

# Auditd

echo -n '[CIS 4.1] Auditd: '

systemctl is-active auditd

 

# SSH Config

echo '[CIS 5.2] SSH Settings:'

sshd -T 2>/dev/null | grep -E '(permitrootlogin|maxsessions|maxauthtries|protocol|loglevel)'

 

# Chrony

echo -n '[CIS 2.2.1] Chrony: '

chronyc tracking | head -3

 

# Sysctl spot checks

echo '[CIS 3.x] Sysctl spot checks:'

sysctl net.ipv4.ip_forward net.ipv4.conf.all.accept_redirects kernel.randomize_va_space

 

# Oracle sysctls

echo '[Oracle] DB sysctls:'

sysctl kernel.shmmax kernel.shmall fs.file-max fs.aio-max-nr

 

# AIDE

echo -n '[CIS 1.3] AIDE DB: '

[[ -f /var/lib/aide/aide.db.gz ]] && echo 'Present' || echo 'MISSING'

 

# Password policy

echo '[CIS 5.4] Password aging:'

grep -E '^PASS_MAX_DAYS|^PASS_MIN_DAYS|^PASS_WARN_AGE' /etc/login.defs

 

# Oracle user limits

echo '[Oracle] oracle user limits:'

su - oracle -c 'ulimit -a' 2>/dev/null | grep -E '(open files|max user|stack size|locked memory)'

 

# Mount options

echo '[CIS 1.1] Mount options:'

mount | grep -E '(/tmp|/dev/shm)' | awk '{print $1, $3, $6}'

 

echo

echo '=== Validation Complete ==='

 

Oracle Database Pre-Installation Check

After hardening, run Oracle’s prerequisite checker to confirm no conflicts:

# For OL8/9 – Oracle preinstall RPM validates kernel params, user limits, packages

dnf install -y oracle-database-preinstall-19c   # for 19c

# or

dnf install -y oracle-database-preinstall-23ai  # for 23ai

 

# Review what it set (should already match our hardening)

rpm -ql oracle-database-preinstall-19c | xargs grep -l sysctl 2>/dev/null

Note: If the preinstall RPM modifies files that we have already hardened, compare the changes. Our hardening values should be equal to or more restrictive than the preinstall values, except for the Oracle-specific items.


Rollback Procedures

Full Rollback

To revert ALL changes from a specific hardening run:

# List available rollback scripts

ls -lt /var/log/hardening/rollback_*.sh

 

# Execute the rollback (review first!)

cat /var/log/hardening/rollback_<RUN_ID>.sh  # review

bash /var/log/hardening/rollback_<RUN_ID>.sh  # execute

 

# Restart affected services after rollback

systemctl restart sshd auditd firewalld chronyd rsyslog

 

# If sysctl values were changed, reload

sysctl --system

Selective Rollback (Single File)

# List backed-up files for a specific run

ls /var/log/hardening/backups/<RUN_ID>/

 

# Restore a specific file

cp -a /var/log/hardening/backups/<RUN_ID>/_etc_ssh_sshd_config /etc/ssh/sshd_config

systemctl restart sshd

Rollback Sysctl Only

# The rollback script includes sysctl -w commands for each parameter

# Extract and run only sysctl lines

grep 'sysctl -w' /var/log/hardening/rollback_<RUN_ID>.sh | bash

 

# Verify

sysctl --system

Emergency: SELinux Permissive Mode

If SELinux enforcement causes application failures that cannot be immediately diagnosed:

# Temporary (runtime only, reverts on reboot)

setenforce 0

 

# Then investigate AVC denials

ausearch -m AVC -ts recent

audit2why -i /var/log/audit/audit.log

 

# Create a targeted policy module instead of disabling SELinux

audit2allow -a -M oracle_custom

semodule -i oracle_custom.pp

setenforce 1

Important: Never leave SELinux in permissive mode in production. Always create a targeted policy module to resolve AVC denials. Some kernel/network changes may require reboot and may not fully revert runtime state.

Quick Reference: Key File Paths

Purpose

File Path

Hardening change log

/var/log/hardening/changes_<RUN_ID>.log

Rollback script

/var/log/hardening/rollback_<RUN_ID>.sh

File backups

/var/log/hardening/backups/<RUN_ID>/

Hardening framework

/usr/local/sbin/hardening-framework.sh

Validation script

/usr/local/sbin/validate-hardening.sh

CIS sysctl config

/etc/sysctl.d/99-hardening.conf

SSH hardening

/etc/ssh/sshd_config.d/99-cis-hardening.conf

Oracle resource limits

/etc/security/limits.d/99-oracle-db.conf

Oracle umask override

/etc/profile.d/oracle-umask.sh

Oracle core dump exception

/etc/security/limits.d/99-oracle-coredump.conf

AIDE config

/etc/aide.conf

Audit rules

/etc/audit/rules.d/cis-hardening.rules

Firewalld oracle zone

firewall-cmd --zone=oracle --list-all

Disabled kernel modules

/etc/modprobe.d/CIS.conf

Faillock config

/etc/security/faillock.conf

Password quality

/etc/security/pwquality.conf


Important: This document should be useed as example / rough guide only. Do not blindly copy/paste or implement the steps without understanding them.

Comments

Popular posts from this blog

Access Oracle OCI Object Storage through GUI Client

Instance OS Baseline Configuration Runbook

Accessing OCI Compute Instances Using VNC Console (Instance Console Connection)