RHEL 10 (and compatibles) hardening
As an Enterprise operating system, hardening Red Hat Enterprise Linux and compatibles for production use often involves compliance with certain standards rather than ad-hoc hack-and-slash methods.
This is a quick copypasta cheat-sheet for a modern, compliant, and future-proof setup.
First we update the system and to make sure weak dependencies won't be installed, then install OpenSCAP:
dnf groupinstall 'Minimal Install' --setopt=install_weak_deps=False
dnf update -y
dnf install openscap scap-security-guide -y
Once OpenSCAP is installed we can scan the system for configuration compliance; ideally this should be run regularly as a cron job:
oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_stig \
--results scan-results.xml \
--report stig-report.html \
/usr/share/xml/scap/ssg/content/ssg-rhel10-ds.xml
Kernel
Enable validation for Secure Boot in the Shim layer:
mokutil --enable-validation
The following kernel options will be added in /etc/default/grub:
GRUB_CMDLINE_LINUX="slub_debug=FZP page_poison=1 pti=on slab_nomerge vsyscall=none randomize_kstack_offset=on lockdown=confidentiality"
- slub_debug=FZP - Enable SLUB allocator debugging (F=Sanity-check free objects, Z=Zero objects upon allocation and free, P=Poison freed objects and padding)
- page_poison=1 - fill freed memory pages with a poison pattern; detect use-after-free and uninitialised memory bugs.
- pti=on - Enable Page Table isolation; mitigates Meltdown CPU vuln
- vsyscall=none - disable legacy vsyscall interface; force vDSO use
- randomize_kstack_offset=on - enable kernel stack offset randomisation at syscall entry. Entropy in stack locs make exploitation more difficult
- lockdown=confidentiality - kernel lockdown mode; prevent root access to direct memory (/dev/mem, etc)
Rebuild grub2 config:
grub2-mkconfig -o /boot/grub2/grub.cfg
SELinux to enforcing mode:
setenforce 1
sed -i 's/SELINUX=.*/SELINUX=enforcing/g' /etc/selinux/config
Auditing and Logging
Enable the Linux Audit daemon which logs security events to /var/log/audit/audit.log
dnf install audit -y
systemctl enable --now auditd
auditd rules
- log every execve (tagged with 'exec_monitor')
- Watch for /etc/{passwd,shadow,group,sudoers,ssh/sshd_config} changes (writes and attribs)
- Log attempts to change the hostname or domain
Logs can be searched using:
ausearch -k exec_monitor
or summarised with:
aureport
/etc/audit/rules.d/hardening.rules:
-a always,exit -F arch=b64 -S execve -k exec_monitor
-w /etc/passwd -p wa -k passwd_changes
-w /etc/shadow -p wa -k shadow_changes
-w /etc/group -p wa -k group_changes
-w /etc/sudoers -p wa -k sudoers_changes
-w /etc/ssh/sshd_config -p wa -k ssh_changes
-a always,exit -F arch=b64 -S sethostname,setdomainname -k system_identity
-e 2
User and Password Policies
Password quality policy:
- Minimum length of 16
- 4 character classes out of lowercase, uppercase, numbers, special characters
- no more than 2 identical characters consecutively (aaa is invalid, aab is valid)
- no more than 2 sequential characters (abc)
- Check against dictionary words (install dictionary!)
- enforce rules for root
/etc/security/pwquality.conf:
minlen = 16
minclass = 4
maxrepeat = 2
maxsequence = 2
dictcheck = 1
enforce_for_root
SSH Configuration
- Limit host key algorithms to ed25519 to prevent downgrades to RSA/DSA/ECDSA
- Restrict key exchange to Curge25519 with SHA-256
- Use ChaCha20-Poly1305 AEAD cipher only
- Restrict MAC to Encrypt-then-MAC with SHA-512
- No root login, public key auth only (no password auth)
/etc/ssh/sshd_config.d/20-hardened.conf
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKeyAlgorithms ssh-ed25519
KexAlgorithms curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com
MACs hmac-sha2-512-etm@openssh.com
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
Disable weak algorithms entirely
Set our crypto policy to FUTURE. Although some environments require FIPS, it is dated and FUTURE will ensure a modern, secure system. This will enable us to use Quantum-resistant algorithms such as CRYSTALS-Kyber and CRYSTALS-Dilithium when available.
update-crypto-policies --set FUTURE
systemctl restart sshd
- TLS 1.2/1.3 only
- Only strong, modern ciphers
- ECDH or FFDHE key exchange
- Secure signature and hashing algorithms only
- Affects SSH, VPNs, OpenSSL, GnuTLS, etc
Network and Firewall
systemctl enable --now firewalld
firewall-cmd --set-default-zone=drop
firewall-cmd --add-service=ssh --permanent
firewall-cmd --reload
Disable IPv6
sysctl -w net.ipv6.conf.all.disable_ipv6=1
echo "net.ipv6.conf.all.disable_ipv6=1" >> /etc/sysctl.conf
IDS
dnf install aide -y
aide --init
Make sure to run regular checks with a cron job or systemd
Integrity Measurement Architecture (IMA)
WIP. Enable kernel IMA with boot params
ima_policy=tcb ima_appraise=enforce evm=fix ima_hash=sha512
Configure policies in /etc/ima/ima-policy
Container Security
- Always run rootless containers
- Use SELinux/AppArmor
Automatic updates
dnf install dnf-automatic -y
systemctl enable --now dnf-automatic.timer
Written for Cryogenix by int16h