|
|

Practical Linux Security
By Cameron Laird
Contributing Writer Article Date: 01.16.03
Reduce risks and eliminate headaches through sensible
account management
Security 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. |
|