Practical Linux Security

Reduce risks and eliminate headaches through sensible account managementSecurity is hard. It doesn’t sit still, and it’s difficult to know how far it needs to extend: if you don’t watch yourself, you can end up believing that your boss needs to understand the beauty of elliptic curves when all he really wants is to make sure the custodian doesn’t read his annual budget. However challenging it is to keep up with all facets of computing security, a few areas have matured enough to be worth learning methodically. The first one I recommend to anyone working with Linux servers is account management.Tend to your user Many of the first wave of books devoted to Linux administration and programming included a chapter on “user management” or “account management.” Their meaning was rather specific: how to set up and maintain the computing accounts and group affiliations for the people who use your host. At that time, “use” necessarily meant “log in to.” Account management was all about working with commands such as useradd, chsh, and so on, to configure Linux accounts that would be convenient for a user population dominated by fellow developers. /etc/passwd and its APIs were the focus of Linux experts. Those times are long past, and the first recommendation I make for most servers is to eliminate most of /etc/passwd. What I mean is this: For historical reasons, most e-mail servers, Web servers, file servers, and so on, manage their user access in terms of /etc/passwd. I think this is generally a mistake. It was a sensible practice earlier in our history, when one or two dozen engineers might share a high-end workstation. Conventional /etc/passwd practices are a mistake, though, when one e-mail server might handle mailboxes for tens of thousands of users, for most of whom computing is just another utility like the water fountain or telephone system. It’s certainly possible to rely on /etc/passwd. It’s been patched and tweaked enough to handle surprising workloads. It shouldn’t have to, though. If you move user accounts into a dedicated datastore, such as an LDAP (lightweight directory access protocol) or even an RDBMS (relational database management system) datastore, you gain advantages in scalability, security, and maintenance. Restrict /etc/passwd to the few developers and administrators who truly need logins. This practice gives a big advantage in security, because the duty cycles of service (e-mail, Web, and so on) users are entirely different from those of developers. Once you have burned in a new server, its /etc/passwd shouldn’t change often. It’s an easy job to monitor it for any updates and, particularly, for tampering. If you’re running a large server, though, you might have several new and expired e-mail account changes daily. You need to isolate those from the wider access that /etc/passwd gives. Is construction of an alternate account datastore a serious recommendation? Yes it is, as surprising as that may seem. A lot of effort has gone in over the years to make very large /etc/passwds, filled mostly with login-free users, work properly. If you do decide to code your own account authentication, and you rely on such traditional e-mail programs as sendmail, you might well find yourself writing changes for SMTP, POP3, and IMAP4 servers. Those obstacles generally incline developers toward using off-the-shelf software. My habit is to favor solutions others have written and that I can re-use. One difference with these industrial-use servers, though, is that I often need to customize them anyway — to set up special message directories, logging information, or usage accounting, for example. What decides the issue for me is a preference to modularize security considerations. I like to be able to manage developer and administrator accounts entirely separately from end-user services. By splitting off the latter from /etc/passwd, I can easily lock down either side without affecting the other.Automate policy Almost as important as separating developer accounts from user services is to automate policy. Establish specific, detailed processes for creating and deleting accounts, both developer (/etc/passwd) and end-user (e-mail, Web, database, and so on). While it’s good discipline to capture these into executables, it’s not strictly necessary. What is important is that the processes be understandable and unambiguous. Casual account creation and deletion always leaves security holes. Review your processes with your human resources, customer support, or other pertinent departments. It’s hard to appreciate how crucial this is unless you’ve lived through the alternative. When you don’t have written procedures for adding and removing users, the invariable result is that a new worker shows up on Monday, say, and by Friday still can’t get to his or her company files. Or someone resigns, says goodbye at the holiday party, and is still retrieving occasional corporate assets as February begins. One of the incidental benefits of account automation is that it encourages more thorough validation. If developers don’t have a convenient way to configure accounts with different properties, they’re quite unlikely to exercise applications that are supposed to differentiate those configurations. I recently experienced this first-hand. I was called in on an emergency in which our implementation team had “correctly,” in effect, allowed managers to review employee performance reviews — even for employees they didn’t manage! As ridiculous as that sounds, it’s typical of security issues. It had even been flagged a couple of times during analysis and design reviews. Every time it was brought to a decision-maker, though, it was part of a sufficiently large and muddy collection of problems that it was passed on without crisp resolution. Only when a support specialist finally set up a concrete example of a general instance — one with multiple managers, each of whom had multiple employees reporting in — did the error get the attention it deserved. Save yourself last-minute dramas; make configuration of all sorts of user accounts routine and available for thorough testing.

Stay alert The hardest part of security, at least for many of us, is to avoid doing dumb things. Security is one of the “weakest link” affairs, where a single loophole can make all the rest of your investment, however huge and well-planned, laughably pointless. To do security well, you have to stay on the alert for things that you aren’t otherwise thinking about. U.S. government sites frequently exemplify the magnitude of that challenge. One federal agency, frequently in the news for security issues in the “anti-terrorist” sense, maintains a Web site where user passwords are displayed in the open, on the page for changing user preferences. Quite a few organizations address the frequency of lost passwords by assigning passwords based on more-or-less public information (for example, “your password is the first four letters of your birthplace, followed by the final two digits of your birthyear”). How can you avoid such catastrophic mistakes? Unfortunately, there are few systematic ways to succeed at such an abstract goal as “being smart.” Among the useful steps to take, though, are study of the RISKS digest and disciplined engineering review. RISKS is an online newsletter that Peter G. Neumann has been editing since 1985. Reading it is excellent practice in thinking about how things — security on your Linux servers, in particular — can go wrong. Neumann makes the digest quite readable and entertaining, if occasionally macabre. You should also acquire the habit of trying out your ideas on others. You might think of “software inspection” as no more than a way to spot misplaced punctuation in developers’ source code, but it’s actually a far more interesting and productive practice. In particular, inspections are a great way to organize peer reviews of requirements documents, Web sites, and all sorts of other artifacts. Stage inspections. See your work through the eyes of others. You’ll probably learn a lot about the security, or insecurity, of your servers. Cameron Laird is Vice President of Phaseit, Inc., where he specializes in Rapid Enterprise Integration development of high-reliability and high performance applications. He often uses open-source tools, including PostgreSQL, Python, Tcl, Perl, OpenLDAP, and a variety of e-mail servers. Originally published at http://www-106.ibm.com/developerworks/linux/library/l-sc7.html

Some Important Files in /etc By Contributing Author Many Linux users will be surprised to learn that their operating system keeps almost all its configuration data in plain text files. In the user’s home directory, for example, there are two important configuration files: .bash_profile and .bashrc. These two files simply regulate some characteristics belonging to that user only. Unlike the configuration files in a user’s home directory, files in /etc affect every user. Files and subdirectories in /etc may not be the same for all distributions. Throughout this article I will use the example of Mandrake 8.0, which, I hope, is a good representation of what one can find in /etc. FILES IN /etc: Linux does not have a standard configuration file format. It is up to the author of the program to choose what format he desires. To see the difference between various formats and degrees of complexity, just compare /etc/shells (a relatively simple file enumerating the possible shells available) and /etc/httpd.conf which you use to configure Apache. (A word of warning here: the example is meant to compare and contrast two configuration files. The file httpd.conf may not be actually in /etc, it may be in /usr/local/httpd/conf or /etc/httpd/conf, depending on your Apache installation). Any attempt to classify the configuration files in /etc according to their importance, will necessarily involve personal judgment and is likely to be a trivial pursuit. (Personally, I believe that /etc/lilo.conf is the single most important file in /etc, but then again, this is my personal opinion). We can, however, classify them according to what they do. The following files are chosen to be included in this short article simply because we hear a lot of questions about them and their uses in dal.net #Linux. System commands are those commands that ensure a proper working environment. Configuration files associated with these commands are of particular importance because they determine whether a system command will actually do what you expect it to do. My personal favorite, /etc/lilo.conf, is such a file. It determines how /sbin/lilo boots your system. It passes a lot of information to /sbin/lilo, telling it what images are available to boot, what the default boot option is, etc. Configure it wrong and you will end up with a non-booting system. In fact, on an average day one can see a lot of complaints in #Linux about not being able to boot using lilo. Here is a short description of the various sections of /etc/lilo.conf and what they do: The first section is what we may call “Global” and, among other things it determines the name of the device that contains the boot sector. My lilo is installed on the MBR of my first hard disk, hence my lilo.conf contains boot=/dev/hda as its first line. Change this to boot=/dev/hdb, save the file and run lilo and you end up with a lilo installed on the MBR of your second disk. The “Global” section is also where you define the default image (default=label) to be booted after a certain period of time (defined by timeout=xyz in the same section) if the user does not press the enter key when the boot prompt comes up. You also define the vga text mode to be used during booting (vga=normal gives you 80 x 25 text mode). You may also need to put “lba32″ here on a line by itself if you are having difficulties when booting an image beyond the infamous cylinder 1024. If you want to pass parameters to the kernel this is usually the place to do it (for example append=” hdc=ide-scsi ” telling the kernel that /dev/hdc uses scsi emulation that makes my Plextor burner available as a scsi device). Next comes the section where you define what you want to boot. The general structure is that you first define where the image you want to boot is (image=/boot/vmlinuz-2.4.17 indicates that the kernel image vmlinuz-2.4.17 in /boot is going to be used), then you give it a name (for example label=newkernel) to type when the lilo boot prompt comes up, and you indicate the partition that contains your / (for example root=/dev/hda8). I multi-boot between Mandrake 8.0, Mandrake 7.1, Windows 2000, and BeOS 5, the default being “newkernel”. Here are the entries in my lilo.conf for the other three booting options: other=/dev/hda2 label=MDK_7.1 So, if I type MDK_7.1 at the lilo boot prompt lilo uses the /boot partition of my Mandrake 7.1 on /dev/hda2 and boots me to it. other=/dev/hda1 label=W2K table=/dev/hda map-drive=1 to=0x80 When I type W2K at the boot prompt, the first line tells lilo to boot the first partition on my first drive (which is actually DOS but contains the ntdetect.com and ntldr files to boot my Windows 2000 which is on /dev/hda6); the third line tells lilo where to find the partition table. The fourth and the fifth lines tell lilo to do some drive swapping to boot Windows 2000. other=/dev/hdb5 label=BeOS Similarly, when I type BeOS, lilo goes to /dev/hdb5 and boots it straight away. (By the way, I’ve found out that the lilo boot prompt is case insensitive, so it does not matter if I type W2K or w2k to boot Windows 2000). /sbin/init is the first program run by your Linux system; it is the “mother” of all processes. Its configuration file, /etc/inittab determines whether you boot into a command line prompt, runlevel 3, or to a window manager, runlevel 5. Among many other things it does, it also determines how many consoles you can have. A problem frequently encountered by new users is that while they would like to boot to a command prompt they automatically enter into a graphical login screen, simply because they have configured their system to boot to X during initial installation. The solution is to edit the /etc/inittab file and change the 5 in “id:5:initdefault:” to 3. At the next boot you will be placed at a command prompt from where you can start your window manager by configuring your .xinitrc file and typing startx. A word of caution here: runlevel numbers may change from one distribution to another. Similarly, /etc/ld.so.conf is the configuration file for /sbin/ldconfig, which actually tells the system where to look for shared libraries. Ever come across the error message “cannot load dynamic shared library such and such”? That is because a shared library needed by a particular program got installed in a directory that is not listed in /etc/ld.so.conf. Make sure that /etc/ld.so.conf lists all the possible paths to your shared libraries and make a habit of running /sbin/ldconfig every time you install a library. /etc/fstab is an important file in the sense that it lists all the devices that are “mountable” by your system. During your boot up sequence the system performs a “mount ­-a” command which takes its input from /etc/fstab. In /etc/fstab you can have a myriad of configuration options. You can have devices mounted read only, restrict the mounting of devices to a certain group, specify where to mount a specific device, etc. The fifth and the sixth fields in /etc/fstab are a source of constant confusion. The fifth field is either 0 or 1. These values are used to determine if the /sbin/dump command needs to check that filesystem for archiving. The sixth field is a number between 0 and 2 (if it does not exist a value of zero is assumed) and it indicates the order in which filesystems are checked during boot. The root partition and only the root partition is assigned a value of 1 so that it gets checked first. All other partitions are assigned a value of 2 and get checked sequentially after the root partition. If the value is 0 or non-existent then that particular filesystem will not be checked. (Please do not confuse this with the maximal mounts count between two filesystem checks which is determined with the /sbin/tune2fs command using the -c option). The file /etc/mtab shows what devices and filesystems are mounted at any given moment. In other words, it is a dynamic file, reflecting the changes in /proc/mount instantaneously. Actually, what /etc/mtab does is that it reads /proc/mount and outputs the information in human readable form, just as /sbin/lsmod reads and reflects the changes in /proc/modules. /etc/group maintains a list of current groups for the system and the names of users that belong to each group. The reason for this is that users with similar needs or characteristics are usually put in groups and given special permissions. Every user is a member of at least one group. By editing this file (as root) you can add or delete groups, change a user’s group membership, etc. When you first boot to your newly installed Linux chances are that your host and domain names are localhost.localdomain, if you have not configured them during installation. You can easily verify this by typing hostname at the command prompt. If you are not satisfied with this name you can always change it with the command hostname followed by the new hostname. However, in order to make the change permanent you need to edit the /etc/sysconfig/network file and put the new hostname there. Security considerations dictate that every user has a valid password. Traditionally, the passwords are kept in /etc/passwd in an encrypted form. But, and this is a big but, this particular file is world readable by its very nature because many of the programs and commands an ordinary user uses must access that file to have some necessary information. Although the passwords are encrypted a determined and malicious cracker may ultimately figure out what a particular user’s password is. The solution to this is to put the encrypted passwords in /etc/shadow that can only be read by root. The fields in /etc/passwd are separated by colons, the first field being your username and the second an indication of the nature of your password. If the second field is empty, then you can login by simply typing your username at the login prompt. This works even if you have an encrypted password in /etc/shadow. If there is an x in the second field you have to supply the correct password. A value of * blocks login access to that account even if you supply the correct password.