System Hardening

Quick Reference

# Kernel hardening
sysctl -w kernel.kptr_restrict=2
sysctl -w kernel.dmesg_restrict=1
sysctl -w kernel.randomize_va_space=2

# Network hardening
sysctl -w net.ipv4.conf.all.send_redirects=0
sysctl -w net.ipv4.conf.all.accept_redirects=0
sysctl -w net.ipv4.tcp_syncookies=1

# File permissions
chmod 600 /etc/shadow
chmod 644 /etc/passwd
chmod 700 /root

# Find SUID/SGID files
find / -perm /6000 -type f 2>/dev/null

# Check listening services
ss -tulnp
systemctl list-unit-files --state=enabled

# Audit configuration
auditctl -l
aureport --summary

Hardening Methodology

Defense in Depth

┌─────────────────────────────────────────────────────────────────┐
│                        Perimeter                                 │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │                      Network                             │   │
│   │   ┌─────────────────────────────────────────────────┐   │   │
│   │   │                    Host                          │   │   │
│   │   │   ┌─────────────────────────────────────────┐   │   │   │
│   │   │   │               Application                │   │   │   │
│   │   │   │   ┌─────────────────────────────────┐   │   │   │   │
│   │   │   │   │              Data                │   │   │   │   │
│   │   │   │   └─────────────────────────────────┘   │   │   │   │
│   │   │   └─────────────────────────────────────────┘   │   │   │
│   │   └─────────────────────────────────────────────────┘   │   │
│   └─────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

Hardening Priorities

Priority Area Examples

Critical

Access control, authentication

SSH hardening, password policies, sudo

High

Network security

Firewall, service exposure, encryption

Medium

Kernel/OS hardening

sysctl, file permissions, SUID

Standard

Auditing and monitoring

auditd, logging, integrity checking

User and Access Management

Password Policies

/etc/login.defs
# Password aging
PASS_MAX_DAYS   90
PASS_MIN_DAYS   1
PASS_MIN_LEN    12
PASS_WARN_AGE   14

# Encryption method
ENCRYPT_METHOD SHA512
SHA_CRYPT_MIN_ROUNDS 10000
/etc/security/pwquality.conf
# Password quality requirements
minlen = 12
minclass = 3
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
maxrepeat = 3
maxclassrepeat = 4
gecoscheck = 1
dictcheck = 1
usercheck = 1
enforcing = 1
retry = 3

Account Security

# Lock inactive accounts
useradd -D -f 30

# Set account to expire
chage -E 2024-12-31 username

# Lock account
usermod -L username
passwd -l username

# Unlock account
usermod -U username

# Force password change on next login
chage -d 0 username

# Review account expiry
chage -l username

# Find accounts without passwords
awk -F: '($2 == "") {print $1}' /etc/shadow

# Find UID 0 accounts (should only be root)
awk -F: '($3 == 0) {print $1}' /etc/passwd

sudo Configuration

/etc/sudoers (use visudo)
# Require password always
Defaults    timestamp_timeout=0

# Secure PATH
Defaults    secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

# Log all sudo commands
Defaults    logfile="/var/log/sudo.log"

# Require TTY
Defaults    requiretty

# Environment restrictions
Defaults    env_reset
Defaults    env_delete="LD_PRELOAD LD_LIBRARY_PATH"

# Limit specific commands
admin   ALL=(ALL) /usr/bin/systemctl restart httpd
backup  ALL=(ALL) NOPASSWD: /usr/local/bin/backup.sh

SSH Hardening

/etc/ssh/sshd_config.d/hardening.conf
# Authentication
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
PubkeyAuthentication yes
AuthenticationMethods publickey

# Restrict users
AllowUsers admin deploy
# Or: AllowGroups ssh-users

# Protocol settings
Protocol 2
X11Forwarding no
MaxAuthTries 3
MaxSessions 2
ClientAliveInterval 300
ClientAliveCountMax 2
LoginGraceTime 60

# Ciphers and MACs
Ciphers aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org

# Disable unused features
AllowAgentForwarding no
AllowTcpForwarding no
GatewayPorts no
PermitTunnel no

# Logging
LogLevel VERBOSE
# Apply changes
sshd -t  # Test configuration
systemctl reload sshd

# Generate strong host keys
rm /etc/ssh/ssh_host_*
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ""

Kernel Hardening

sysctl Security Settings

/etc/sysctl.d/99-security.conf
# === Kernel ===
# Restrict access to kernel pointers
kernel.kptr_restrict = 2

# Restrict dmesg access
kernel.dmesg_restrict = 1

# Enable ASLR
kernel.randomize_va_space = 2

# Restrict ptrace
kernel.yama.ptrace_scope = 1

# Disable SysRq
kernel.sysrq = 0

# Disable unprivileged user namespaces
kernel.unprivileged_userns_clone = 0

# Disable core dumps
kernel.core_pattern = |/bin/false
fs.suid_dumpable = 0

# Restrict BPF JIT
net.core.bpf_jit_harden = 2

# === Filesystem ===
# Restrict symlinks and hardlinks
fs.protected_symlinks = 1
fs.protected_hardlinks = 1
fs.protected_fifos = 2
fs.protected_regular = 2

# === Network: IPv4 ===
# Disable IP forwarding
net.ipv4.ip_forward = 0

# Disable ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0

# Disable source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

# Enable reverse path filtering
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Ignore ICMP broadcast requests
net.ipv4.icmp_echo_ignore_broadcasts = 1

# Ignore bogus ICMP errors
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Log Martian packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1

# Enable SYN cookies (DoS protection)
net.ipv4.tcp_syncookies = 1

# Disable TCP timestamps (privacy)
net.ipv4.tcp_timestamps = 0

# === Network: IPv6 ===
# Disable IPv6 if not needed
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

# Or if IPv6 is needed, harden it:
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
# Apply settings
sysctl -p /etc/sysctl.d/99-security.conf

# Verify settings
sysctl kernel.kptr_restrict
sysctl net.ipv4.tcp_syncookies

Kernel Module Restrictions

/etc/modprobe.d/blacklist-security.conf
# Disable unused filesystems
install cramfs /bin/true
install freevxfs /bin/true
install jffs2 /bin/true
install hfs /bin/true
install hfsplus /bin/true
install squashfs /bin/true
install udf /bin/true

# Disable unused network protocols
install dccp /bin/true
install sctp /bin/true
install rds /bin/true
install tipc /bin/true

# Disable USB storage (if not needed)
install usb-storage /bin/true

# Disable Firewire (if not needed)
install firewire-core /bin/true
install firewire-ohci /bin/true

Boot Security

/etc/default/grub
# Add to GRUB_CMDLINE_LINUX
GRUB_CMDLINE_LINUX="... init_on_alloc=1 init_on_free=1 page_alloc.shuffle=1 slab_nomerge vsyscall=none"

# Regenerate GRUB
grub-mkconfig -o /boot/grub/grub.cfg

File System Security

File Permissions

# Critical system files
chmod 600 /etc/shadow
chmod 600 /etc/gshadow
chmod 644 /etc/passwd
chmod 644 /etc/group

# SSH
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_*
chmod 644 ~/.ssh/*.pub

# Cron
chmod 600 /etc/crontab
chmod 700 /etc/cron.d
chmod 700 /etc/cron.daily
chmod 700 /etc/cron.hourly
chmod 700 /etc/cron.monthly
chmod 700 /etc/cron.weekly

# Root directory
chmod 700 /root

# Log files
chmod 640 /var/log/*.log
chmod 600 /var/log/audit/audit.log

# Verify no world-writable files
find /etc -type f -perm -002 -ls
find /var -type f -perm -002 -ls

SUID/SGID Files

# Find SUID files
find / -perm -4000 -type f 2>/dev/null

# Find SGID files
find / -perm -2000 -type f 2>/dev/null

# Find both
find / -perm /6000 -type f 2>/dev/null

# Remove SUID/SGID if not needed
chmod u-s /path/to/file
chmod g-s /path/to/file

# Common SUID files to review:
# /usr/bin/passwd        - Required
# /usr/bin/sudo          - Required
# /usr/bin/su            - Required
# /usr/bin/mount         - Often not needed for users
# /usr/bin/umount        - Often not needed for users
# /usr/bin/chfn          - Often not needed
# /usr/bin/chsh          - Often not needed

Mount Options

/etc/fstab
# /tmp with restrictions
tmpfs   /tmp    tmpfs   defaults,nodev,nosuid,noexec,size=2G    0 0

# /var/tmp with restrictions
/tmp    /var/tmp    none    bind    0 0

# /home with nosuid
/dev/sda3   /home   ext4    defaults,nodev,nosuid    0 2

# /var with nosuid
/dev/sda4   /var    ext4    defaults,nodev,nosuid    0 2

# Separate /var/log
/dev/sda5   /var/log    ext4    defaults,nodev,nosuid,noexec    0 2

# Separate /var/log/audit
/dev/sda6   /var/log/audit  ext4    defaults,nodev,nosuid,noexec    0 2

# /dev/shm restrictions
none    /dev/shm    tmpfs   defaults,nodev,nosuid,noexec    0 0
# Apply without reboot
mount -o remount,nodev,nosuid,noexec /tmp
mount -o remount,nodev,nosuid,noexec /dev/shm

umask Settings

/etc/profile.d/umask.sh
# Set restrictive umask
umask 027
/etc/login.defs
UMASK 027

Service Hardening

Minimize Services

# List enabled services
systemctl list-unit-files --state=enabled

# Disable unnecessary services
systemctl disable --now bluetooth.service
systemctl disable --now cups.service
systemctl disable --now avahi-daemon.service

# Mask services to prevent starting
systemctl mask ctrl-alt-del.target
systemctl mask debug-shell.service

# List listening ports
ss -tulnp

# Remove unused packages
dnf remove telnet rsh xinetd tftp-server
apt purge telnet rsh-server xinetd tftpd

systemd Service Hardening

/etc/systemd/system/myservice.service.d/hardening.conf
[Service]
# Filesystem restrictions
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/lib/myservice

# Network restrictions
PrivateNetwork=false
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX

# Capabilities
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true

# User/Group
User=myservice
Group=myservice
DynamicUser=true

# System call filtering
SystemCallFilter=@system-service
SystemCallArchitectures=native

# Memory
MemoryDenyWriteExecute=true

# Proc/Device restrictions
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true
ProtectClock=true
ProtectHostname=true
ProtectProc=invisible

# Misc
LockPersonality=true
RestrictRealtime=true
RestrictSUIDSGID=true
RemoveIPC=true
PrivateDevices=true
# Analyze service security
systemd-analyze security myservice

Network Hardening

Firewall Configuration

# Enable firewall
systemctl enable --now firewalld
# Or: systemctl enable --now nftables

# Default deny incoming
firewall-cmd --set-default-zone=drop

# Allow only necessary services
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload

# Rate limiting for SSH
firewall-cmd --permanent --add-rich-rule='rule service name="ssh" limit value="10/m" accept'

TCP Wrappers

/etc/hosts.allow
# Allow SSH from specific networks
sshd: 192.168.1.0/24
sshd: 10.0.0.0/8
/etc/hosts.deny
# Deny all by default
ALL: ALL

fail2ban

/etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
banaction = nftables-multiport

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3

[sshd-ddos]
enabled = true
port = ssh
filter = sshd-ddos
logpath = /var/log/auth.log
maxretry = 10
findtime = 60
bantime = 86400
# Enable fail2ban
systemctl enable --now fail2ban

# Check status
fail2ban-client status
fail2ban-client status sshd

# Unban IP
fail2ban-client set sshd unbanip 192.168.1.100

Integrity Checking

AIDE (Advanced Intrusion Detection Environment)

# Install AIDE
dnf install aide
apt install aide

# Initialize database
aide --init
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db

# Check for changes
aide --check

# Update database after legitimate changes
aide --update
mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
/etc/aide.conf (example additions)
# Monitor additional paths
/etc/passwd$ CONTENT_EX
/etc/shadow$ CONTENT_EX
/etc/ssh/sshd_config$ CONTENT_EX
/root/.ssh$ PERMS
/root/.bashrc$ CONTENT_EX

# Exclude frequently changing
!/var/log
!/var/cache
!/proc
!/sys

Package Verification

# Verify installed packages (RPM)
rpm -Va

# Verify specific package
rpm -V openssh-server

# Output meanings:
# S = Size differs
# M = Mode differs
# 5 = MD5 sum differs
# D = Device differs
# L = Link path differs
# U = User differs
# G = Group differs
# T = Time differs

# Verify packages (Debian)
debsums -c

# Verify specific package
debsums openssh-server

Security Auditing

auditd Configuration

/etc/audit/rules.d/security.rules
# Delete all existing rules
-D

# Buffer size
-b 8192

# Failure mode
-f 1

# Monitor authentication
-w /etc/pam.d/ -p wa -k pam
-w /etc/login.defs -p wa -k login
-w /var/log/faillog -p wa -k logins
-w /var/log/lastlog -p wa -k logins

# Monitor sudo
-w /etc/sudoers -p wa -k sudoers
-w /etc/sudoers.d/ -p wa -k sudoers

# Monitor system files
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/group -p wa -k identity
-w /etc/gshadow -p wa -k identity

# Monitor SSH
-w /etc/ssh/sshd_config -p wa -k sshd

# Monitor privilege escalation
-a always,exit -F arch=b64 -S setuid -S setgid -k priv_esc

# Monitor file deletions
-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -k delete

# Module loading
-w /sbin/insmod -p x -k modules
-w /sbin/modprobe -p x -k modules
-a always,exit -F arch=b64 -S init_module -S delete_module -k modules

# Make immutable
-e 2
# Load rules
augenrules --load

# Check for violations
ausearch -k identity -ts today
aureport --summary

Security Scanning

# OpenSCAP security scan
oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_cis \
    --results results.xml \
    --report report.html \
    /usr/share/xml/scap/ssg/content/ssg-rhel8-ds.xml

# Lynis security audit
lynis audit system

# Generate report
lynis audit system --report-file /tmp/lynis-report.log

# Check specific controls
lynis audit --tests CORE-1000,SSH-7408

Quick Hardening Checklist

□ Set strong password policies
□ Configure sudo properly
□ Harden SSH (keys only, no root login)
□ Apply kernel sysctl hardening
□ Disable unnecessary services
□ Configure firewall (default deny)
□ Set restrictive file permissions
□ Remove/restrict SUID/SGID binaries
□ Use restrictive mount options
□ Enable and configure auditd
□ Install and configure AIDE
□ Configure fail2ban
□ Enable SELinux/AppArmor
□ Apply security updates
□ Review and minimize installed packages

Quick Command Reference

# === User Security ===
chage -l username                # Check account expiry
passwd -l username               # Lock account
usermod -s /sbin/nologin user    # Disable login

# === File Permissions ===
find / -perm /6000 -type f       # Find SUID/SGID
find / -perm -002 -type f        # Find world-writable
chmod u-s /path/file             # Remove SUID

# === Service Management ===
systemctl list-unit-files --state=enabled
systemctl disable --now service
systemctl mask service

# === Network ===
ss -tulnp                        # Listening ports
firewall-cmd --list-all          # Firewall rules

# === Auditing ===
auditctl -l                      # List audit rules
ausearch -k key -ts today        # Search audit logs
aureport --summary               # Audit summary

# === Integrity ===
aide --check                     # Check file integrity
rpm -Va                          # Verify packages (RPM)
debsums -c                       # Verify packages (Debian)

# === Security Scanning ===
lynis audit system               # Security audit
oscap xccdf eval ...             # SCAP evaluation

See Also