System hardening is one of the toughest job for any system administrator. I would like to share few steps which can make your server more secure.
1.Physical Server Security
You must protect Linux servers physical console access. Configure the BIOS and disable the booting from external devices such as DVDs / CDs / USB pen. Set BIOS and grub boot loader password to protect these settings.
Next, set a password for the GRUB bootloader. Generate a password hash using the command /sbin/grub-md5-crypt.
Add the hash to the first line of /etc/grub.conf as follows:
password --md5 $1$.bvWQ1$8Cf.vpU5BKQCPlr1u07iQ1
This prevents users from entering single user mode or changing settings at boot time.
Note: The “md5sum” stands for (Compute and Check MD5 Message Digest), md5 checksum (commonly called hash) is used to match or verify integrity of files that may have changed as a result of a faulty file transfer, a disk error or non-malicious interference.
2. Remove unnecessary packages
Install packages according to the functional requirement of your server. It's a good practice that not to run services like Apache or Samba running on mail servers. Same with having development packages or desktop software packages like x-server installed on production servers. It is very crucial to remove unnecessary packages or packages that don't comply with your organization's security policy. Packages like ftp,telnet etc should not be installed unless you have a justified business reason for it. There are many alternatives for it, like scp or sftp, which runs under ssh suite.
To get a list of all installed RPMs you can use the following command:
# rpm -qa
To remove the unwanted RPM's you can use
# rpm -e <package_name> or # yum erase <package_name>
If you don't want to remove the package then you can disable it using chkconfig.
To list the services configured to start at boot, run the following command:
# /sbin/chkconfig --list
# ckhconfig --level 2345 <package_name> off
To remove the startup script:
# /bin/mv /etc/rc.d/rc3.d/S25<script_name> /etc/rc.d/rc3.d/K25<script_name>
To disable services, either you can remove the start up script, or use commands like chkconfig or ntsysv. There are two steps to stopping a service: 1) stop the currently running services, and 2) change the configuration so that the services doesn’t start on the next reboot.
3. Apply Patches release by vendor (Redhat / CentOS etc )
Building an infrastructure for patch management is another very important step to proactively secure Linux production environments. It is recommended to have a written security policy and procedure to handle Linux security updates and issues.
For example, a security policy should detail the time frame for assessment, testing, and roll out of patches. Network related security vulnerabilities should get the highest priority and should be addressed immediately within a short time frame.
All security update should be reviewed and applied as soon as possible. If you don't have a security update policy and you decide to apply automatic update then make sure that you exclude packages from automatic update by excluding them in /etc/yum.conf. This is very important especially when you don't want to update your kernel.
4. Disable unwanted SUID/SGID files
Effective permission could be real security threat, so you need to be very careful with files which has SUID/SGID set.
You can list all the files where SUID/SGID set
# find / -path /proc -prune -o -type f -perm +6000 -ls
5. Secure services like SSH, Postfix, NFS etc
Root login should be disabled also you can create a group that the members only allowed to use ssh.
# vim /etc/ssh/sshd_config
Linux servers that are not dedicated mail or relay servers should not accept external emails. To make sure that Postfix accepts only local emails for delivery. Edit the configuration file and specify mydestination (lists all domains to receive emails) and inet_interfaces (network to listen on)
# vim /etc/postfix/main.cf
mydestination = $myhostname, localhost.$mydomain, localhost
inet_interfaces = localhost
Make all your entries in /etc/exports, you can export all filesystems using: # exportfs –a
6. Impose password policy
a) Enable Password Aging
Password information like Last password change, expiry, inactive etc are stored in /etc/login.def file.
You can get information about a particular user use chage command
# chage -l <user_name>
Last password change : Oct 31, 2019
Password expires : never
Password inactive : never
Account expires : never
b) Enforce stronger passwords
To set complexity of the password edit the system-auth file under the directory /etc/pam.d
# vim /etc/pam.d/system-auth
The pam_cracklib module checks the password against dictionary words and other constraints like whether the password contains the user´s name in some form, a palindrome, too small, just a change of case or even too much similar to the old one. Look for the line containing the pam_cracklib module like below. To enforce the password complexity change the line to:
password requisite pam_cracklib.so try_first_pass retry=3 minlen=8 ucredit=-1 dcredit=-1 ocredit=-1 lcredit=-1
minlen minimum length of password
lcredit minimum number of lower case letters
ucredit minimum number of upper case letters
dcredit minimum number of digits
ocredit minimum number of other characters
retry prompt user at most N times before returning with error.
c) Restricting use of previous passwords
Module pam_unix is used for traditional password authentication, and is obtained from the /etc/passwd and the /etc/shadow file as well if shadow is enabled.
Now, update existing password line and append remember=10 to prevent a user from re-using any of his or her last 10 passwords. Do not append new line, update exiting password line and append remember=10.
password sufficient pam_unix.so use_authtok md5 shadow remember=10
The old password list is located in /etc/security/opasswd file.
d) Lock user accounts after too many login failures
Module pam_tally maintains a count of attempted accesses, can reset count on success, can deny access if too many attempts fail. Add the following entry to the /etc/pam.d/system-auth file.
# vim /etc/pam.d/system-auth
pam_tally.so per_user deny=5 no_magic_root reset
Failure count logging file is stored in /var/log/tallylog, while on the other hand failure logging information is stored in /var/log/secure.
7. Restrict "su" usage
You can list the su users and the command which can be executed by them by using sudo command.
# sudo -l
I have seen many system administrators tend to add users to the wheel group and enable wheel group in the sudoers file, it could be a security risk as these users get the same privilege as root.
7. Set SELINUX
To know your SELINUX policy as well as SELINUXTYPE use the command sestatus. You can also use getenforce command to get the status of SELINUX.
To change open the selinux file
8. Set firewall rules
You should set firewall rules
# vim /etc/sysconfig/iptables
9. Tune your kernel
The sysctl command is used to configure kernel parameters at run time. To list the current values
# sysctl -a
You can optimize the performance of your server by turning the kernel. I'm discussing commonly used few parameters only. For more information you can find here.
Open the sysctl configuration file and you can add these settings. Once done use sysctl -p to load the settings.
# vim /etc/sysctl.conf
# Disable IP packet forwarding
net.ipv4.ip_forward = 0
# Disable IP source routing.
# Sender of a packet can specify the route that a packet should take through the network.
net.ipv4.conf.all.accept_source_route = 0
# Enable IP spoofing protection, turn on source route verification
net.ipv4.conf.all.rp_filter = 1
# Decrease the default value for TCP Keepalive time.
# Checking your connected socket to determine whether the connection is still up and running or if it has broken.
net.ipv4.tcp_keepalive_time = 1800
# Enable TCP SYN Flooding Attack Protection
net.ipv4.tcp_syncookies = 1
# Ignore all broadcast/multicast ICMP ECHO/TIMESTAMP request to prevent common DoS attack
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Enable ExecShield protection to prevent Buffer overflow attack
kernel.exec-shield = 1
# Set limits for system wide open files/file descriptors (FD)
fs.file-max = 65535
# Set allowed PID limit
kernel.pid_max = 65535
# Limit allowed local port range
net.ipv4.ip_local_port_range = 1024 65535
# When kernel panic reboot after 30 second delay
kernel.panic = 30
To verify kernel parameters use sysctl <kernel_parameter_name>
# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
You can also use
# cat /proc/sys/net/ipv4/ip_forward
10. Set limit for resource usage
You can use ulimit -a to see the limits sets on your resources like cpu time, limit the maximum number of processes that a single user may own, priority, open files etc.
Limiting maximum processes an user may own is important especially when users are vulnerable to 'fork bomb' attack.
To make it persistent add corresponding entry to the limits.conf file
# vim /etc/security/limits.conf
You can set user specific limits for open files/file descriptors (FD) by editing /etc/security/limits.conf file and say soft and hard limits.
# vim /etc/security/limits.conf
httpd soft nofile 4096
httpd hard nofile 10240
Note - Please test in NON Production server before considering above hardening tips.