Linux Server Hardening Checklist
Checklist :
- 1. Encrypt Data Communication for Linux Server
- All data transmitted over a network is open to monitoring. Encrypt transmitted data whenever possible with password or using keys / certificates.
- GnuPG allows to encrypt and sign your data and communication, features a versatile key management system as well as access modules for all kind of public key directories.
- SSH / RSYNC / SFTP for file transfer
- SSL whenever it's possible
- 2. Avoid Using FTP, Telnet, and Rlogin / Rsh Services
- Commands and transferred files can be captured by anyone on the same network using a packet sniffer.
- Use instead OpenSSH , SFTP, or FTPS (FTP over SSL)
- 3. Minimize Software to Minimize Vulnerability
yum list installed
yum list packageName
or
dpkg --list
dpkg --info packageName
- 4. One Network Service Per System, VM or Container
Run each exposed service isolated via VM, Docker, LXC..
- 5. Keep Linux Kernel and Software Up to Date
yum update
or
apt update && apt upgrade
- 6. Use Linux Security Extensions
Use SELinux, Apparmor, Grsecurity when possible.
Feature | SELinux | AppArmor | grsecurity |
---|---|---|---|
Automated | No (audit2allow and system-config-selinux) | Yes (Yast wizard) | Yes (auto training / gradm) |
Powerful policy setup | Yes (very complex) | Yes | Yes |
Default and recommended integration | CentOS / RedHat / Debian | Suse / OpenSuse / Ubuntu based | Any Linux distribution |
Training and vendor support | Yes (Redhat) | Yes (Novell) | No (community forum and lists) |
Recommend for | Advanced user | New / advanced user | New users |
Feature | Attaches labels to all files, processes and objects | Pathname based system does not require labeling or relabeling filesystem | ACLs |
7. Linux User Accounts must respect a strong password policy
-
Lockout/Error after X retry
passwd -l username
- Minimum length
- Force to change similar characters
- Force no null passwords
- Setup password aging For ex, you can directly edit the /etc/shadow file :
{userName}:{password}:{lastpasswdchanged}:{Minimum_days}:{Maximum_days}:{Warn}:{Inactive}:{Expire}:
Where,
- Minimum_days: The minimum number of days required between password changes.
- Maximum_days: The maximum number of days the password is valid (after that user is forced to change his/her password).
- Warn : The number of days before password is to expire that user is warned that his/her password must be changed.
- Expire : Absolute date specifying when the login may no longer be used.
- 8. Ensure No Non-Root Accounts Have UID Set to 0 Only root account have UID 0 with full permissions to access the system. Check with :
awk -F: '($3 == "0") {print}' /etc/passwd
- 9. Disable Root Login Never ever login as root user. You should use sudo to execute root level commands as and when required.
- 10. Physical Server Security
- BIOS & Grub password w or w/o MFA
- 11. Disable Unwanted Linux Services
Check with :
systemctl list-unit-files
This command will list all services installed/deployed.
Print a list of services that lists which runlevels each is configured on or off
systemctl list-unit-files --type=service
systemctl list-dependencies graphical.target
- 12. Find Listening Network Ports
ss -tulpn
netstat -plntu
- 13. Delete X Window Systems (X11) X Window systems on server is not required.
yum groupremove "X Window System"
yum group remove "$DE_NAME Desktop"
- 14. Configure Iptable Firewall
- 15. Harden Linux Kernel with /etc/sysctl.conf
/etc/sysctl.conf file is used to configure kernel parameters at runtime. Linux reads and applies settings from /etc/sysctl.conf at boot time.
- 16. Separate Disk Partitions for Linux System
Partition | Purpose |
---|---|
/usr | This is where most executable binaries, the kernel source tree and much documentation go. |
/var | This is where spool directories such as those for mail and printing go. It also contains the error log directory. |
/tmp | This is where most temporary data files are stored by apps. |
/boot | This is where your kernel images and boot loader configuration go. |
/home | This is where users' home directories go. |
If the partitions are in one, a script like this one :
#!/bin/sh
man bash > $(mktemp)
$0
runned with cron or nohup can crash your entire system.
A good way of hardening could be , depending on your IS, to add the following option to /etc/fstab file:
- nosuid – Do not set SUID/SGID access on this partition
- nodev – Do not character or special devices on this partition
- noexec – Do not set execution of any binaries on this partition
- ro – Mount file system as readonly
- quota – Enable disk quota
Above options can be set only, if you have a separate partition.
Make sure you create a partition as above with special option set on each partition:
- /home – Set option nosuid, and nodev with diskquota option
- /usr – Set option nodev
- /tmp – Set option nodev, nosuid, noexec option must be enabled
- 17. Disable IPv6 if Not Using It
- 18. Disable Unwanted SUID and SGID Binaries
All SUID/SGID bits enabled file can be misused : https://gtfobins.github.io/
- 19. Check for World-Writable Files
If you find a script that is owned by root but is writable by anyone you can add your own malicious code in that script that will escalate your privileges when the script is run as root
# World writable files directories
find / -writable -type d 2>/dev/null
find / -perm -222 -type d 2>/dev/null
find / -perm -o w -type d 2>/dev/null
# World executable folder
find / -perm -o x -type d 2>/dev/null
# World writable and executable folders
find / \( -perm -o w -perm -o x \) -type d 2>/dev/null
- 20. Remove Noowner Files
Files not owned by any user or group can pose a security problem. Just find them with the following command :
find /dir -xdev \( -nouser -o -nogroup \) -print
- 21. Use Centralized Authentication Service
IAM / LDAP / SSO ....
- 22. Implement Kerberos for Authentication
Use Kerberos if available : https://docs.redhat.com/en/documentation/red_hat_ansible_automation_platform/2.4/html/automation_controller_administration_guide/assembly-controller-kerberos-authentication
- 22. Configure Logging and Auditing
- 23. Monitor Suspicious Logs with Logwatch / Logcheck
Read your logs using logwatch command (logcheck). You get detailed reporting on unusual items in syslog via email.
- 24. Use System Accounting with auditd
- 25. Secure OpenSSH Server
26. Install and Use Intrusion Detection Systems (IDS)
-
Install a NIDS
-
Use AIDE, a HIDS
-
rkhunter to detect rootkit
- 27. Disable USB/Firewire/Thunderbolt Devices
Type the following command to disable USB devices on Linux system:
echo 'install usb-storage /bin/true' >> /etc/modprobe.d/disable-usb-storage.conf
You can use same method to disable firewire and thunderbolt modules:
echo "blacklist firewire-core" >> /etc/modprobe.d/firewire.conf
echo "blacklist thunderbolt" >> /etc/modprobe.d/thunderbolt.conf
Once done, users can not quickly copy sensitive data to USB devices or install malware/viruses or backdoor on your Linux based system.
- 28. Use fail2ban/denyhost/portsentry for IDS
Fedora Hardening Script :
- Add you ssh keys BEFORE running the script
- Update and upgrade BEFORE
#!/bin/bash
# Fedora Server Hardening Script
echo "Starting system hardening..."
# -------------------------------------
### Step 1 of 24: Update system and install required packages
sudo dnf update -y && sudo dnf install -y dnf-automatic sysstat clamav clamav-update clamd audit aide fail2ban arpwatch policycoreutils-python-utils
# -------------------------------------
### Step 2 of 24: Configure firewall and SSH port 69
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --permanent --add-port=69/tcp
sudo firewall-cmd --reload
sudo semanage port -a -t ssh_port_t -p tcp 69
echo "blacklist dccp\nblacklist sctp\nblacklist rds\nblacklist tipc" | sudo tee -a /etc/modprobe.d/blacklist.conf && sudo modprobe -r dccp sctp rds tipc
# -------------------------------------
### Step 3 of 24: Harden SSH configuration
sudo sed -i '/Port/d' /etc/ssh/sshd_config
sudo sed -i '/AllowTcpForwarding/d' /etc/ssh/sshd_config
sudo sed -i '/ClientAliveCountMax/d' /etc/ssh/sshd_config
sudo sed -i '/LogLevel/d' /etc/ssh/sshd_config
sudo sed -i '/MaxAuthTries/d' /etc/ssh/sshd_config
sudo sed -i '/MaxSessions/d' /etc/ssh/sshd_config
sudo sed -i '/TCPKeepAlive/d' /etc/ssh/sshd_config
sudo sed -i '/X11Forwarding/d' /etc/ssh/sshd_config
sudo sed -i '/AllowAgentForwarding/d' /etc/ssh/sshd_config
echo "Port 69
AllowTcpForwarding no
ClientAliveCountMax 2
LogLevel VERBOSE
MaxAuthTries 3
MaxSessions 2
TCPKeepAlive no
X11Forwarding no
AllowAgentForwarding no
PermitRootLogin no
PasswordAuthentication no
UsePAM yes
AuthenticationMethods publickey" | sudo tee -a /etc/ssh/sshd_config
sudo systemctl restart sshd
# -------------------------------------
### Step 4 of 24: Kernel hardening
echo "kernel.core_uses_pid=1
kernel.sysrq=0
kernel.kptr_restrict=2
net.ipv4.conf.all.rp_filter=1
net.ipv4.conf.all.accept_redirects=0
net.ipv4.conf.default.accept_redirects=0
net.ipv4.conf.all.log_martians=1
net.ipv4.conf.default.log_martians=1
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.default.accept_source_route=0
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_timestamps=0
net.ipv6.conf.all.accept_redirects=0
net.ipv6.conf.default.accept_redirects=0
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
dev.tty.ldisc_autoload=0
fs.protected_fifos=2
fs.protected_regular=2
fs.suid_dumpable=0
kernel.unprivileged_bpf_disabled=1
net.core.bpf_jit_harden=2
kernel.yama.ptrace_scope=3
kernel.perf_event_paranoid=3
kernel.dmesg_restrict=1
kernel.kexec_load_disabled=1
kernel.randomize_va_space=2
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv6.conf.default.router_solicitations=0
net.ipv6.conf.default.accept_ra_rtr_pref=0
net.ipv6.conf.default.accept_ra_pinfo=0
net.ipv6.conf.default.accept_ra_defrtr=0
net.ipv6.conf.default.autoconf=0" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# -------------------------------------
### Step 5 of 24: Disable core dumps
echo "* hard core 0" | sudo tee -a /etc/security/limits.conf
# -------------------------------------
### Step 6 of 24: Fix cron directory permissions
sudo chmod 755 /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.monthly /etc/cron.weekly
# -------------------------------------
### Step 7 of 24: Configure password age
sudo sed -i 's/PASS_MAX_DAYS.*/PASS_MAX_DAYS 30/' /etc/login.defs
sudo sed -i 's/PASS_MIN_DAYS.*/PASS_MIN_DAYS 7/' /etc/login.defs
sudo sed -i '/FAIL_DELAY/d' /etc/login.defs
echo "FAIL_DELAY 3" | sudo tee -a /etc/login.defs
# -------------------------------------
### Step 8 of 24: Set default UMASK
sudo sed -i '/UMASK/d' /etc/login.defs
echo "UMASK 027" | sudo tee -a /etc/login.defs
# -------------------------------------
### Step 9 of 24: Modify password hashing policies
sudo sed -i '/SHA_CRYPT/d' /etc/login.defs
echo "SHA_CRYPT_MIN_ROUNDS 5000" | sudo tee -a /etc/login.defs
echo "SHA_CRYPT_MAX_ROUNDS 5000" | sudo tee -a /etc/login.defs
# -------------------------------------
### Step 10 of 24: Build locate database
sudo updatedb
# -------------------------------------
### Step 11 of 24: Disable USB and Firewire
echo "blacklist usb-storage" | sudo tee -a /etc/modprobe.d/blacklist.conf
echo "blacklist firewire-core" | sudo tee -a /etc/modprobe.d/blacklist.conf
# -------------------------------------
### Step 12 of 24: Resolve localhost and hostname in DNS
sudo sed -i '/127.0.0.1/d' /etc/hosts
echo "127.0.0.1 $(hostname)" | sudo tee -a /etc/hosts
# -------------------------------------
### Step 13 of 24: Enable automatic updates
sudo systemctl enable --now dnf-automatic.timer
# -------------------------------------
### Step 14 of 24: Install and configure ClamAV
sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam -now
sudo sed -i '/^Example/d' /etc/clamd.d/scan.conf
sudo sed -i '/^Example/d' /etc/freshclam.conf
sudo sed -i 's/^#LocalSocket/LocalSocket/' /etc/clamd.d/scan.conf
# -------------------------------------
### Step 15 of 24: Restrict execution of compilers
sudo chmod o-x /usr/bin/python3
sudo chmod g-x /usr/bin/python3
# -------------------------------------
### Step 16 of 24: Install and enable ARP monitoring tool
sudo systemctl enable --now arpwatch
# -------------------------------------
### Step 17 of 24: Increase auditing and logging
sudo systemctl enable --now auditd
echo "-w /etc/passwd -p wa -k passwd_changes
-w /etc/shadow -p wa -k shadow_changes
-w /var/log/ -p wa -k log_monitoring
-w /etc/ssh/sshd_config -p wa -k ssh_changes" | sudo tee -a /etc/audit/audit.rules
# -------------------------------------
### Step 18 of 24: Install and configure AIDE for file integrity checking
sudo aide --init
sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
# -------------------------------------
### Step 19 of 24: Configure fail2ban for SSH protection
echo "[sshd]
enabled = true
port = 69
filter = sshd
logpath = /var/log/secure
maxretry = 3
bantime = 600" | sudo tee /etc/fail2ban/jail.local
sudo systemctl enable --now fail2ban
# -------------------------------------
### Step 20 of 24: Lock down cron and at
echo "root" | sudo tee /etc/cron.allow /etc/at.allow
sudo chmod 600 /etc/cron.allow /etc/at.allow
# -------------------------------------
### Step 21 of 24: Set idle user logout
echo "TMOUT=600
readonly TMOUT
export TMOUT" | sudo tee /etc/profile.d/autologout.sh
# -------------------------------------
### Step 22 of 24: Add legal banner
echo "Unauthorized access to this server, please stop all activity !" | sudo tee /etc/issue
echo "Unauthorized access to this server, please stop all activity !" | sudo tee /etc/issue.net
# -------------------------------------
### Step 23 of 24: Enable sysstat for stats
sudo systemctl enable --now sysstat
# -------------------------------------
### Step 24 of 24: Enable SELinux enforcement
sudo setenforce 1
sudo sed -i 's/SELINUX=permissive/SELINUX=enforcing/' /etc/selinux/config