I've heard the claim that anyone can get rooted. (By "rooted", I mean an unauthorized person gets access to the root account.) While this is strictly true, there are degrees of protection that can be put in place that make your system more secure, even against unknown attacks.
There are a small number of ways that an attacker can become root. By careful analysis, one can dramatically reduce one's exposure, so it's important to understand some fundamental Unix security.
A few attacks on root are based on exploiting bugs in the implementation of the kernel's security mechanisms. These are very hard to defend against, especially if users have shell accounts on the machines.
Most attacks are based on exploiting bugs in programs that are directly or indirectly trusted by root. By following the web of trust, one can see where to put the effort into hardening a system.
A program is trusted by root if it run as root. This could be because it is automatically started by another program running as root, for example, by init or inetd (eg. smartd, inetd, rpc.mountd, gpm, syslogd and fam), or because it is manually started by somebody logged in as root (eg. ls).
A program may run as root, and hence be trusted by root, if it is setuid root. Examples include su, mount, crontab, ping and suexec.
Suppose that an account, A, runs a program. That account trusts that program. If 'su' is then used to switch to the root account, then the root account trusts A. Suppose that the program isn't trustworthy and has installed a program called su in ~/bin, which happens to be first on the PATH. The fake su records the password then runs the real su. This would lead to the root account being compromised. In other words root trusts the program run by A.
To get to root, one has to employ two attacks - one to get to account, A, and another to get from A to root. What makes A special is the use of su; that makes second attack so trivial that compromising A is the effectively same as compromising root.
This means that all programs run by computer administrators are trusted by root, which is why computer administrators should have two accounts: one for administration and one for normal use.
In order to subvert the root account, it is necessary to find part of the system that is:
All useful programs interact with their environment in some way; a few programs only produce an output (eg. /usr/bin/yes), but the vast majority of programs take actions based on their environment. One can influence the behaviour of a program by manipulating the environment.
Manipulatable parts of the environment include:
All of the above, if not correctly handled, can give opportunities to subvert trusted programs.
Network servers have a very obvious interaction with their environment - they receive data from the network. The obvious attack method is to try and exploit incorrect handling of the network data.
We are only interested in programs are that are trusted by root, so we can mitigate the risk by posed by eliminating the trust:
Alternatively, one can prevent the exploit:
By eliminating the trust of network servers by the root account, one gets protection against unknown attacks. If you unlucky and are attacked before the security hole is fixed, the damage will be contained to the compromised subsystem.
Network clients also receive data from the network, so the possiblity of exploits exists by causing the client to receive carefully constructed data. Network clients include programs like mail user agents, web browsers etc.
Some setuid and/or setgid programs are trusted by root. These programs are especially difficult to implement correctly since they inherit the environment from the calling program. There are many opportunities for quite subtle bugs to lead to a root compromise, and many local user-to-root exploits use setuid programs.
A serious deficiency specific to setuid programs is that the program can write to itself. This leads to an attack where:
Note that this deficiency exists for any setuid program, not just setuid root programs. On Linux ext2, one can make a setuid program immutable, so that only root may change it.
One can mitigate the risks:
Many trusted programs do files I/O for configuration, data files, etc. Unless the data is handled correctly, it may be possible to subvert a program by manipulating its files. It is therefore important that any file that is shared is either handled with the utmost care or is not modifiable by untrustworthy accounts.
A simple case is that of a program executed by root being writable by others. A more complex case is that of a configuration file being writable which is used to exploit a buffer overflow in the program.
Directories that are writable by untrustworthy accounts consitute at least a big a risk as writable files, since a file can simply be replaced it the containing directory is writable.
In addition, it opens up the possibility of symbolic link attacks. One replaces a file with a symbolic link another user's file. When the victim runs the program, one of the victims files is overwritten. This may just cause damage, or it may expose the victim's account to other types of attack. (Consider .rhosts being overwritten.)
A particularly poor design decision in Unix is /tmp. This directory is shared, and therefore writable by everyone, which means that without care one is susceptible to symlink attacks and other races.
Peter Benie <email@example.com>