Hardening Unix computers

This describes some techniques which help harden Unix computers, that is reduce the likelihood that the will be compromised by an attacker.. There is some overlap with another document, forensic analysis. This is because both hardening and forensic analysis require a deep understanding of how Unix works.

Strong access controls

If available, administrators should learn and apply the strong access controls available on their computers. For example, mandatory access control systems such as SELinux or AppArmor go a long way to constrain programs beyond the traditional Unix access controls. Using these controls requires a bit of study, but can provide a large benefit. Another document, SELinux, provides a basic introduction to SELinux.

Passwords and system accounts

Ideally, passwords should be used only for local authentication, where a user must be physically present at the computer performing authentication. The reason for this is that passwords are often compromised using various forms of guessing attacks, and extending password-based authentication beyond physically-present users increases the set of people who can mount these attacks. Other forms of authentication, such as public-key-based systems should authenticate network users.

The passwords that do exist must be strong. In most cases, as review of /etc/passwd will reveal the accounts which will need a password audit.

Another consideration is whether accounts should exist in the first place. A review of /etc/passwd will reveal a number of accounts with a legitimate shell and other accounts whose shell is set to something like /sbin/nologin. You should remove unnecessary accounts of the former case. Accounts of the latter case are pseudo-users. They do not have passwords, and are generally created by the act of installing some package. Pseudo-users exist to run software with the least privileges possible. To remove these latter accounts, remove unnecessary packages.

Pluggable Authentication Modules

The files /etc/passwd, /etc/shadow, and /etc/group define standard UNIX accounts and groups. However, many programs perform authentication using Pluggable Authentication Modules (PAM) which provide many other authentication techniques. Such techniques include Kerberos, NIS, and so on. The PAM modules each PAM-capable program uses to authenticate are defined using configuration files in /etc/pam.d. Thus checking for proper authentication involves:

  • Checking the integrity of each authenticating program
  • Checking the PAM configuration of each authenticating program
  • Checking the accounts themselves (e.g., expected accounts with strong passwords)

Graphical login authentication is generally performed using a display manager such as gdm, and text logins usually use agetty which spawns login.

Service/application-level accounts

Some services, such as databases and web-based applications, often provide their own account databases instead of relying on the system accounts provided by Unix. In such cases, you must audit these accounts too, as they exist separately from the system accounts. Since each account is defined in an application-specific way, you will need to refer to each service’s documentation to find out how to review that service’s accounts.

Minimal privilege

Avoid running programs as root to the maximum extent possible. Network-facing programs should run as pseudo-users, except when root privileges are absolutely needed (see the design of OpenSSH, qmail, Postfix, and Dovecot). X11 applications should never run as root. Indeed, even administrators should minimize running programs as root to avoid accidents. Use sudo to administer your system.

Minimal packages

A hardened computer contains only the software needed to serve its purpose. On Red Hat-like version of Linux, you can enumerate the packages installed with rpm -qa and remove a package with rpm -e *pkg-name*. In general, you should interact with the computer’s package system (i.e., RPM on Red Hat, dpkg on Debian/Ubuntu, or ports on BSD) rather than manually removing things with rm.

Dangerous programs

It is very difficult to audit everything on a modern, general-purpose computer (very small distributions such as OpenWrt can be of help here). Because of this, it is wise to consider those programs which might give an attacker a foothold on the computer. This includes network-facing programs and setuid-bit programs.

Network-facing programs

One way to audit the network-facing programs running on a computer is with a port scan. The nmap utility serves this purpose. There are a few things to remember here:

  • nmap scans only common ports by default, but you can scan all ports using -p1-;
  • nmap scans TCP by default, but you can scan UDP using -sU; and
  • nmap scans IPv4 by default, but you can scan IPv6 using -6.

You should scan the entire port range of IPv4 TCP and UDP and also IPv6 TCP and UDP.

Setuid-bit programs

Setuid-bit programs run with the privileges of the owner of the program's file within the filesystem instead of the parent process. This mechanism is often used to temporarily escalate privileges, and so compromised setuid-bit programs are particularly dangerous. You can list the setuid-bit programs on the compromised system by running the following command:

find /mnt -perm -4000 -type f

It is especially important to remove unnecessary programs which have their setuid bit set.

Memory-bug countermeasures

Attackers sometimes use a memory bug present in a program to a undermine security policy. Such bugs include unchecked buffer accesses. It is generally best to select software which is written using a type-safe language, because type-safe languages remove entire classes of bugs. However, sometimes software written in unsafe languages such as C cannot be avoided. In these cases, certain features of Unix and compilers can help thwart attacks on memory bugs.

The following is a list of memory exploits along with countermeasures.

Stack smash, payload on stack
Non-executable stack, a feature of Unix.
Stack smash, return to existing library
Stack canaries, a compiler feature.
Stack smash, return-oriented programming
Address-space layout randomization, a feature of Unix which relies on code compiled in a position-independent way.

While these techniques can make the act of exploiting a bug more difficult, they often fail when software has more than one bug. For examples, ASLR might be ineffective in the presence of both a buffer-overflow bug and a bug which leaks the address of one of the program’s symbol.

Centralized logging

Computers should log events and send these logs to a centralized log consolidator using an encrypted and authenticated network channel. This allows a network administrator to view the activities on his network in a unified manner, and it stores a record of the activities on each computer separate from the computer being monitored. If a computer is compromised, the attacker might find it difficult to compromise the log server. Of course, the log server itself must also be hardened. Another document, logging strategies, describes one way to build a logging system with these properties.

Update software

Ensure that the software on the computer is up-to-date. You can do this using the computer’s package-management tool.

SSH configuration

Administrators commonly use SSH to administer a set of computers. SSH is a good choice, because it encrypts the connections it provides. Yet SSH can succumb to password-guessing attacks. For this reason, administrators should configure SSH to use public-key-based authentication and forbid password-based authentication.

You can disable OpenSSH’s use of passwords by setting PasswordAuthentication to no in /etc/ssh/sshd_config.

Generating the keys necessary for public-key-based authentication is a matter of running ssh-keygen -b 4096 and copying the resulting ~/.ssh/id_rsa.pub into the ~/.ssh/authorized_keys on the computers you wish to login on.