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.
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 |
Comments
Post a Comment