System Hardening checklist¶
- Title:
System Hardening Checklist
- Author:
Douglas O’Leary <dkoleary@olearycomputers.com>
- Description:
Checklist for common and some not so common security hardening practices
- Disclaimer:
Standard: Use the information that follows at your own risk. If you screw up a system, don’t blame it on me…
Overview:¶
A quick google search of unix system hardening checklist resulted in ~15,700 results. So, why one more? Primarily so I’ll know where to go to get my favorite one. It also lists some things that aren’t commonly done. First and foremost, do not put your brand new shiny system on the internet before it’s protected…
This checklist also ties together some of the things raised in Redhat’s SCAP security guide project It’s an excellent checklist although it does go to show that the DOD must really hate their user base (min password length 14, password history 24 - wow)
Principles:¶
The principles listed in the Redhat’s SCAP security guide project are also excellent. This list includes both the ones listed in the guide and my own:
Encrypt data whenever possible both in transit and static.
Minimize installed software - although it is possible to take that too far.
Run different services on different systems - more possible and prevalent in today’s virutalizaton environment.
Least privilege
Separation of duties
Employ multifactor authentication when possible.
Checklist:¶
System installation:¶
Install a minimal system. Easer to do on Linux than other major OS variants. The logic is simple: s/w, daemons and/or apps can’t be cracked if it’s not installed.
Download and install useful utilities:
tcpdump
nmap/wireshark
lsof
tcpwrappers
gpg
rcs/git (version control)
Install the initial patches. Depending on OS, this may require a software support contract.
Mount points: Different mount points and mount options for:
/tmp: nosuid,nodev,(noexec?)*
/var: nosuid,nodev
/var/log: nosuid,nodev
/var/log/audit: nosuid,nodev
The security guide states:
Allowing users to execute binaries from world-writable directories such as /tmp should never be necessary in normal operation and can expose the system to potential compromise.
While it’s an understandable security stance, it doesn’t take into account that /tmp is the generic place to extract files which are then executed for installation.
That’s not to say that /tmp can’t be remounted exec for the installation, then remounted noexec when done. One client had their puppet CM tool handling the remount daily. Please note that not all UNIX variants have the -o remount option.
I whole-heartedly agree with the nosuid on /tmp, though. My favorite example crack is creating a copy of /bin/ksh, suid root, either through a world writable cron file, incorrectly configured sudo, or any other method available:
cp /bin/ksh /tmp/give_me_root chown root:root /tmp/give_me_root chmod 4755 /tmp/give_me_root
A nosuid mounted /tmp filesystem would prevent that attack from working.
Kernel: mostly linux flavored, but other major variants might have something similar:
kernel.dmesg_restrict=1 : prevents unprivileged users from running dmesg.
fs.suid_dumpable=0 : disabled core dumps for suid programs.
kernel.exec-shield=1 : enables kernel protections against memory corruption and buffer overflow attacks.
kernel.randomize_va_space=2 : Enables Address Space Layout Randomization (ASLR) which makes buffer overflow attacks much more entertaining.
Disable core dumps through ulimits. On linux:
echo "* hard core 0" >> /etc/security/limits.conf
Disable kernel unneeded kernel loadable modules, particularly for removable media (data leakage issue)
Protect the system bios, if appropriate:
password protect changes
prevent booting from usb
File/directory permissions:
All world writable dirs have sticky bit and owned by a system account.
No world writable files? Ensure that’s valid before changing willy nilly
Verify all SGID/SUID files.
Standard owner/group perms restrictions on other files/directories, including share libraries. Validate and update
Network and services:¶
Services:¶
Disable unneeded network services. Normally done through /etc/inetd.conf. The list below should be commented out. Echo and chargen, for instance, are used in the fraggle network attacks.
bootps (unless you’re setting up a pxe boot system or something similar)
chargen
daytime
discard
echo
exec (UNIX r-services should be disabled in favor of ssh)
finger
ident (unless needed for sendmail functionality)
login
ntalk
shell
time
uucp
Wrap any inetd based network services left open. Using telnet as an example:
telnet stream tcp nowait root /usr/sbin/tcpd /usr/sbin/telnetd -b /etc/issue
Linux doesn’t install (x)inetd by default so those variants are ahead of the game. There are some services that should be considered:
Disable:
abrtd: automatic bug reporting tool.
acpid: useful on laptops/desktops, but useless and potential DOS for servers and virtuals.
certmonger: if system doesn’t have anything to do w/pki certs.
cgconfig: control groups - allows SA to allocate resources to defined groups of processes.
cgred: Control group rules engine
cpuspeed: conserves heat by reducing clock speed of cpu based on current processing load.
haldaemon: hardware abstraction layer daemon: useful on laptops/ desktops using removable media; but shouldn’t be run on servers or virtuals.
kdump: kernel dump analyzer
mdmonitor: software raid array monitor
netconsole: loads kernel mod which logs kernel printk messages to a syslog server.
oddjobd: basically, sudo for tasks run via the message bus.
qpidd: apache Qpid. listens for advanced message queuing protocol messages on port 5672. Disable if installed and not using AMQP.
quota_nld: Disable if not using quotas.
rdisc: Servers serve, routers, route. Servers shouldn’t be routers disable the routing daemon.
saslauthd: if not using kerberos or ldap.
Enable:
irqbalance: balances h/w interrupts across multiple processes. Enable if server and have more than one processor.
psacct: process accounting.
Disable (better don’t install or uninstall) extraneous system daemons. Items to consider:
sendmail/postfix
samba/cifs
NFS
apache (shouldn’t even be installed if system won’t be a web server)
SNMP
etc
Enable iptables if system is exposed to attack.
If using SNMP, change the community strings
Disable wireless and bluetooth services if not needed.
Harden TCP/IP protocol stack:¶
The commands vary on OS and some may not be possilbe on all OSes.
Decrease the ARP cache cleanup interval
Disable ICMP broadcast echo
Disable ICMP routing redirects
Disable ICMP broadcast probes
Disable IP source routing
Verify/Configure strong initial sequence numbers
Disable IP forwarding (unless you’re setting up a firewall/router)
Disable dead gateway detection (HPUX issue)
Disable ICMP address mask requests
Log martian packets
Implement tcp syn flood defense, if possible.
The following, in /etc/sysctl.conf, will implement those recommendations on rhel based linux systems:
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.ip_forward = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
User accounts:¶
Verify all UIDs in /etc/passwd are unique:
awk -F: '{print $3}' /etc/passwd | sort -n | uniq -d
Verify all non-user accounts are locked:
awk -F: '{printf("%-20s %s\n", $1, $2)}' /etc/shadow
Verify all home directories are owned by appropriate user and have appropriate permissions. While 755 permissions are typical, they really shouldn’t be more open than 750.
awk -F: '{print $1, $6}' /etc/passwd | while read user home do l=$(ls -ld ${home} 2>/dev/null) printf "%-18s %s\n" ${user} "${l:=not_found}" done
Move root’s home directory:
mkdir -p -m 700 /root mv ${profiles} /root usermod -d /root root || edit password file directly. Log in using a different window to verify functionality.
At a minimum, update root’s shell history name - consider adding logic system wide:
vi ${appropriate-profile} [[ ! -d ~/history ]] && mkdir -p -m 700 ~/history Me=$(logname) Dts=$(date +"%y%m%d+%H:%M:%S") HISTFILE=~/history/.sh_history_${Me}_${Dts} HISTSIZE=2048 export HISTFILE HISTSIZE
Verify all directories in root’s path are:
absolute
owned and writable only by root
Doesn’t contain current directory .
Update password aging and complexity rules (OS dependent):
Passwords expire after 90 days (fairly standard and PCI requirement)
Inactivity max of 120 days (follow site security policy)
Min number of days before user can change password again = 7 days (prevents people from changing their password directly back again)
Password history at least 3. Can’t use the last three passwords. Some sites have this at 10. DOD at 24. They must really hate their user base…
Update password complexity. Consider use of password generators for initial passwords.
Min 8 characters
At least 1 capital
At least 1 special character
At least 1 numeric
Lock down pam as appropriate:
Null passwords not allowed (nullok)
Last login notification time present
cracklib used and configured appropriately
Lockout times set reasonably.
ssh configuration:¶
In sshd_config, enable logging of key fingerprints, disable password authentication for root but allow public key authenticaiton, and move where authorized_keys files are kept. See Sudo vs ssh/pka to access root for reasons:
SyslogFacility AUTH LogLevel VERBOSE PermitRootLogin without-password AuthorizedKeysFile /etc/sshkeys/authorized_keys.%u # chgrp /etc/sshkeys/authorized.%u to match the group of the key owner # chcon -t ssh_home_t /etc/sshkeys/authorized_keys.* # selinux
In ssh_config:
ForwardAgent yes ForwardX11 yes
Configure forced commands for ssh keys, particularly those for root. Copy sshroot to /root/bin. If you’re going to use forced commands for all users, put this in /usr/local/bin or other appropriate directory
Update the keys:
command="/root/bin/sshroot" ssh-dss AAAAB3NzaC1kc3MAAA [[ LOTS snipped ]]
Other useful security practices:¶
Logging: forward syslog messages to a central log server. Set one up if you don’t have one.
HIDS: Install, configure, and use host intrusion detection system. Tripwire is the one that everyone knows; however, OSSEC is a good commercial grade open source one as well.
Auditing: If this is a PCI system and it stores PCI data, configure auditing for the directories that hold PCI data and the audit directories. Consider auditing for non-pci related systems as well. Some potential audit configurations for consideration:
/etc/audit/auditd.conf:
num_logs: number of logs to retain
max_log_file: size at which to rotate in megs
space_left_action: what to do when filesystem fills up.
Others as makes sense.
/etc/audit/audit.rules:
Group changes:
# audit_account_changes -w /etc/group -p wa -k audit_account_changes -w /etc/passwd -p wa -k audit_account_changes -w /etc/gshadow -p wa -k audit_account_changes -w /etc/shadow -p wa -k audit_account_changes -w /etc/security/opasswd -p wa -k audit_account_changes
network changes:
# audit_network_modifications -a always,exit -F arch=ARCH -S sethostname -S setdomainname \ -k audit_network_modifications -w /etc/issue -p wa -k audit_network_modifications -w /etc/issue.net -p wa -k audit_network_modifications -w /etc/hosts -p wa -k audit_network_modifications -w /etc/sysconfig/network -p wa \ -k audit_network_modifications
selinux changes:
-w /etc/selinux/ -p wa -k MAC-policy
Attempts to alter login/logout logs:
-w /var/log/faillog -p wa -k logins -w /var/log/lastlog -p wa -k logins
Attempts to alter process/session info:
-w /var/run/utmp -p wa -k session -w /var/log/btmp -p wa -k session -w /var/log/wtmp -p wa -k session
Unuathorized/unsuccessful file access attempts:
-a always,exit -F arch=b64 -S creat -S open -S openat \ -S truncate -S ftruncate -F exit=-EACCES -F auid>=500 \ -F auid!=4294967295 -k access -a always,exit -F arch=b64 -S creat -S open -S openat \ -S truncate -S ftruncate -F exit=-EPERM -F auid>=500 \ -F auid!=4294967295 -k access
Privileged command execution - one line for each suid/sgid program:
-a always,exit -F path=${absolute_path_to_command} \ -F perm=x -F auid>=500 -F auid!=4294967295 -k privileged
Audit data leakage:
-a always,exit -F arch=b64 -S mount -F auid>=500 \ -F auid!=4294967295 -k export
sudo actions:
-w /etc/sudoers -p wa -k actions
Kernel module (un)loading:
-w /sbin/insmod -p x -k modules -w /sbin/rmmod -p x -k modules -w /sbin/modprobe -p x -k modules -a always,exit -F arch=ARCH -S init_module \ -S delete_module -k modules
Add -e 2 to make changes to the rules require a reboot.
Changing DAC:
-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat \ -F auid>=500 -F auid!=4294967295 -k perm_mod -a always,exit -F arch=b64 -S chown -S fchown -S fchownat \ -S lchown -F auid>=500 -F auid!=4294967295 -k perm_mod -a always,exit -F arch=b64 -S setxattr -S lsetxattr \ -S fsetxattr -S removexattr -S lremovexattr \ -S fremovexattr -F auid>=500 -F auid!=4294967295 \ -k perm_mod