To see a list of all currently installed packages and their version numbers on your RPM-based system, use this command:
rpm -qa
To see if a specific package is installed, pipe this command to grep, specifying part or all of the package’s name. For example:
rpm -qa |grep squid
on my SuSE 7.1 system returns this output: squid23-2.3.STABLE4-75
The equivalent commands for deb-package-based distributions like Debian would be dpkg -l and dpkg -l |grep squid, respectively. Of course, either command can be redirected to a file for later reference (or off-system archival — e.g., for crash or compromise recovery) like this: rpm -qa > packages_07092002.txt
3.1.2.6 SuSE’s online-update feature
In addition to yast and rpm, you can also use yast2 to update SuSE packages. This method is particularly useful for performing a batch update of your entire system after installing SuSE. yast2 uses X by default, but will automatically run in ncurses mode (i.e., with an ASCII interface structured identically to the X
interface) if the environment variable DISPLAY isn't set.
In yast2, start the "Software" applet, and select "Online Update." You have the choice of either an automatic update in which all new patches are identified, downloaded, and installed or a manual update in which you're given the choice of which new patches should be downloaded and installed (Figure 3-3). In either option, you can click the "Expert" button to specify an FTP server other than ftp.suse.com.
Overall, yast2’s Online Update functionality is simple and fast. The only error I’ve encountered running it on my two SuSE servers was the result of invoking yast2 from an xterm as an unprivileged user: yast2 claimed that it couldn’t find the update list on ftp.suse.com, which wasn’t exactly true. The real problem was that yast2 couldn’t write that file locally where it needed to because it was running with my non-root privileges. Invoking yast2 from a window-manager menu (in any window manager that susewm configures) obviates this problem: you will be prompted for the root password if you aren’t running X as root. Running X as root, of course, is another workaround, but not one I recommend due to the overall insecurity of X-Windows. A better approach is to open a terminal window and issue these commands (output omitted):
bash-$ su
bash-# export DISPLAY="" bash-# yast2
Setting the environment variable DISPLAY to null in this way (make sure not to put any whitespace between the quotation marks) will force yast2 to run in your terminal window in ncurses mode; it won’t matter which user started the underlying X session.
3.1.2.7 How to be notified of and obtain security updates: Debian
As is typical of Debian GNU/Linux, updating Debian packages is less flashy yet simpler than with most other distributions. The process consists mainly of two commands (actually, one command, apt-get, invoked twice but with different options):
apt-get update apt-get -u upgrade
The first command, apt-get update, updates your locally cached lists of available packages (which are stored, if you’re curious, in /var/state/apt/lists). This is necessary for apt-get to determine which of your currently installed packages have been updated.
The second command, apt-get -u upgrade, causes apt-get to actually fetch and install the new versions of your local outdated packages. Note that as with most other Linux package formats, the deb format includes pre- and post-installation scripts; therefore, it isn’t necessarily a good idea to run an apt- get upgrade unattended, since one or more scripts may prompt you for configuration information. That’s really all there is to it! Naturally, errors are possible: a common cause is outdated FTP/HTTP links in /etc/apt/sources.list. If apt-get seems to take too long to fetch package lists and/or reports that it can’t find files, try deleting or replacing the sources.list entry corresponding to the server that apt-get was querying before it returned the error. For a current list of Debian download sites worldwide, see http://www.debian.org/distrib/ftplist.
Another common error is new dependencies (ones that didn’t apply when you originally installed a given package), which will cause apt-get to skip the affected package. This is fixed by simply invoking apt- get again, this time telling it to install the package plus any others on which it depends.
For example, suppose that in the course of an upgrade session, apt-get reports that it’s skipping the package blozzo. After apt-get finishes the rest of the upgrade session, you enter the command: apt-get install blozzo
apt-get will then attempt to install the latest version of blozzo and will additionally do a more thorough job of trying to resolve its dependencies. If your old version of blozzo is hopelessly obsolete, however, it may be necessary to upgrade your entire distribution; this is done with the command apt-get -u dist-upgrade.
Detailed instructions on using apt-get can be found in the apt-get(8) manpage, as well as in the APT HOWTO (available at http://www.debian.org/doc/manuals/apt-howto).
To receive prompt, official notification of Debian security fixes, subscribe to the debian-security-announce email list. An online subscription form is available at http://www.debian.org/MailingLists/subscribe.
Unfortunately, the deb package format doesn’t currently support GNUpg signatures, or even md5 hashes, nor are external hashes or GNUpg signatures maintained or checked. Therefore, be careful to stick to official Debian FTP mirror sites when using apt-get.
Reportedly, a future version of the deb package format will support GNUpg signatures.
3.1.3 Deleting Unnecessary User Accounts and Restricting Shell Access
One of the popular distributions’ more annoying quirks is the inclusion of a long list of entries in /etc/passwd for application-specific user accounts, regardless of whether those applications are even installed. (For example, my SuSE 7.1 system created 48 entries during installation!) While few of these are privileged accounts, many can be used for interactive login (i.e., they specify a real shell rather than /bin/false). This is not unique to SuSE: my Red Hat 7.0 system created 33 accounts during installation, and my Debian 2.2 system installed 26.While it’s by no means certain that a given unused account can and will be targeted by attackers, I personally prefer to err on the side of caution, even if that makes me look superstitious in some peoples’ eyes.
Therefore, I recommend that you check /etc/passwd and comment out any unnecessary entries.
If you aren’t sure what a given account is used for but see that account has an actual shell specified, one way to determine whether an account is active is to see whether it owns any files, and if so, when they were last modified. This is easily achieved using the find command.
Suppose I have a recently installed web server whose /etc/passwd file contains, among many others, the following entry:
yard:x:29:29:YARD Database Admin:/usr/lib/YARD:/bin/bash
I have no idea what the YARD database might be used for. Manpage lookups and rpm queries suggest that it isn’t even installed. Still, before I comment out yard’s entry in /etc/passwd, I want to make sure the account isn’t active. It’s time to try find / -user and ls -lu(Example 3-7).
Example 3-7. Using find with the -user flag
root@woofgang:~ # find / -user yard -print /usr/lib/YARD
root@woofgang:~ # ls -lu /usr/lib/YARD/ total 20
drwxr-xr-x 2 yard yard 35 Jan 17 2001 . drwxr-xr-x 59 root root 13878 Dec 13 18:31 .. As we see in Example 3-7, yard owns only one directory, /usr/lib/YARD, and it’s empty. Furthermore, according to ls -lu (which displays and lists files by access times), the directory hasn’t been accessed since January 17. Since the system was installed in October, this date must refer to the directory’s creation on my installation media by SuSE! Clearly, I can safely assume that this account isn’t in use.
Some accounts that are usuallynecessary if present are as follows: • root • bin • daemon • halt • shutdown • man • at
Some accounts that are often unnecessary, at least on bastion hosts, are as follows: • uucp • games • gdm • xfs • rpcuser • rpc
If nothing else, you should change the final field (default shell), in unknown or process-specific accounts’ entries in /etc/passwd, from a real shell to /bin/false — only accounts used by human beings should need shells.
3.1.4 Restricting Access to Known Users
Some FTP daemons allow anonymous login by default. If your FTP server is intended to provide public FTP services, that's fine; but if it isn't, then there's no good reason to leave anonymous FTP enabled.
The same goes for any other service running on a publicly accessible system: if that service supports but doesn't actually require anonymous connections, then the service should be configured to accept connections only from authenticated, valid users. Restricting access to FTP, HTTP, and other services is described in subsequent chapters.
3.1.5 Running Services in chrooted Filesystems
One of our most important threat models is that of the hijacked daemon: if a malicious user manages to take over and effectively "become" a process on our system, he will assume the privileges on our system that that process has. Naturally, developers are always on the alert for vulnerabilities, such as buffer overflows, that compromise their applications, which is why you must keep on top of your distribution's security advisories and package updates.
However, it's equally important to mitigate the risk of potential daemon vulnerabilities, i.e., vulnerabilities that might be unknown to anyone but the "bad guys." There are two primary means of doing so: running the process with as low a set of privileges as possible (see the next section) and running the process in a chroot jail.
Normally, a process can see and interact with as much of a system's filesystem as the user account under which the process runs. Since most of the typical Linux host's filesystem is world-readable, that amounts to a lot of real estate. The chroot system call functionally transposes a process into a subset of the filesystem, effectively redefining the / directory for that process to a small subdirectory under the real root. For example, suppose a system has the following filesystem hierarchy (see Figure 3-4).
Figure 3-4. Example network architecture
For most processes and users, configuration files are found in /etc, commands are found in /usr/bin, and various "volatile" files such as logs are found in /var. However, we don't want our DNS daemon, named, to "see" the entire filesystem, so we run it chrooted to /var/named. Thus, from named's perspective,
/var/named/etc is /etc, /var/named/usr/bin is /usr/bin, and /var/named/var appears as /var. This isn't a foolproof method of containment, but it helps.
Many important network daemons now support command-line flags and other built-in means of being run chrooted. Subsequent chapters on these daemons describe in detail how to use this functionality. (Actually, almost any process can be run chrooted if invoked via the chroot command, but this usually requires a much more involved chroot jail than do commands with built-in chroot functionality. Most applications are compiled to use shared libraries and won't work unless they can find those libraries in the
expected locations. Therefore, copies of those libraries must be placed in particular subdirectories of the chroot jail.)
chroot is not an absolute control: a chroot jail can be subverted via techniques such as using a hard link that points outside of the chroot jail or by using mknod to access the hard disk directly. However, since none of these techniques is very easy to execute without root privileges, chroot is a useful tool for hindering an attacker who has not yet achieved root privileges.
3.1.6 Minimizing Use of SUID=root
Normally, when you execute a command or application, it runs with your user and group privileges. This is how file and directory permissions are enforced: when I, as user mick, issue the command ls /root, the system doesn’t really know that mick is trying to see what’s in root’s home directory. It knows only that the command ls, running with mick’s privileges, is trying to exercise read privileges on the directory /root. /root probably has permissions drwx---; so unless mick’s UID is zero, the command will fail. Sometimes, however, a command’s permissions include a set user-ID (SUID) bit or a set group-ID (SGID) bit, indicated by an "s" where normally there would be an "x" (see Example 3-8).
Example 3-8. A program with its SUID bit set
-rwsr-xr-x 1 root root 22560 Jan 19 2001 crontab This causes that command to run not with the privilege level of the user who executed it, but of the user or group who owns that command. If the owner’s user or group ID is 0 (root), then the command will run with superuser privileges no matter who actually executes it. Needless to say, this is extremely dangerous! The SUID and SGID bits are most often used for commands and daemons that normal users might need to execute, but that also need access to parts of the filesystem not normally accessible to those users. For some utilities like su and passwd, this is inevitable: you can’t change your password unless the command passwd can alter /etc/shadow (or /etc/passwd), but obviously, these files can’t be directly writable by ordinary users. Such utilities are very carefully coded to make them nearly impossible to abuse. Some applications that run SUID or SGID have only limited need of root privileges, while others needn’t really be run by unprivileged users. For example, mount is commonly run SUID=root, but on a server-class system there’s no good reason for anybody but root to be mounting and unmounting volumes, so mount can therefore have its SUID bit unset.
3.1.6.1 Identifying and dealing with SUID=root files
The simplest way to identify files with their SUID and SGID bits set is with the find command. To find all root-owned regular files with SUID and SGID set, we use the following two commands:
find / -perm +4000 -user root -type f -print find / -perm +2000 -group root -type f -print
If you determine that a file thus identified doesn’t need to run SUID/SGID, you can use this command to unset SUID:
chmod u-s /full/path/to/filename and this command to unset GUID:
chmod g-s /full/path/to/filename
Note that doing so will replace the SUID or SGID permission with a normal "x": the file will still be executable, just not with its owner’s/group’s permissions.
Bastille Linux, the hardening utility covered later in this chapter, has an entire module devoted to unsetting SUID and SGID bits. However, Bastille deals only with some SUID files common to many systems; it doesn’t actually identify all SUID/GUID files specific to your system. Therefore, by all means use Bastille to streamline this process, but don’t rely solely on it.