Chapter 4. Maintain Security with sendmail

When the administrator is not careful, the misuse or misconfiguration of sendmail can lead to an insecure and possibly compromised system. Since pre-V8.12 sendmail is often installed to run as a set-user-id root process, it is a prime target for intrusion.[59] The “Internet worm,” for example, used a flaw in old versions of sendmail as one way to gain entry to thousands of machines.[60] If sendmail is not properly installed, improper file permissions can be used to trick the system into giving away root privilege.

In this chapter, we present several ways to protect your site from intrusion via sendmail. Most of these are just good common sense, and the experienced system administrator might be offended that we state the obvious. But not all system administrators are experienced, and not all who administer systems are system administrators. If you fall into the latter category, you might wish to keep a good, general Unix reference by your side to better appreciate our suggestions.

Why root?

One common complaint about sendmail centers on the fact that it is often run, set-user-id root (that is, run as root no matter who actually runs it).[61] Beginning with V8.12, the default is to run sendmail as a user other than root. The listening daemon needs to be root, but sendmail itself no longer needs to be set-user-id root.

For the most part, it is necessary for sendmail to run as root to satisfy legitimate needs. Consider the following:

  • Users want ~/.forward files to work even when their home directory is set to mode 700. The sendmail program requires root privilege so that it can temporarily become the user to read and process the ~/.forward file.

  • Users want :include: mailing-list files readable only by themselves and sendmail. The sendmail program requires root privilege so that it can temporarily become the owner of the list.

  • Users want programs that run on their behalf to run as themselves. This requires root privileges, and running as anything else would be potentially very dangerous.

  • Users want sendmail to listen on TCP/IP ports that are common (ports 25 and 587). The sendmail program requires root privilege so that it can initiate listening connections to privileged ports.

Some folks have been tempted to run sendmail as an untrusted pseudouser (such as nobody). But this doesn’t really work. For example, it causes programs in users’ ~/.forward files to be run as nobody, and it requires the queue to be owned by nobody. Consequently, such a scheme allows any user to break into and modify the queue.[62]

Test seteuid and setreuid

Clearly, many of sendmail’s duties require it to run as root. As a corollary, however, whenever sendmail does not need to be root, it should become the appropriate non-privileged user. It does this by using the following bit of logic:

  • If it was compiled with support for seteuid(3) (USESETEUID on page 151), use that routine to set the effective uid to that of the desired non-root user. This is less preferred than the following.

  • If it was compiled with support for setreuid(3) (HAS... on page 114), use that routine to set the effective and real uids to those of the desired non-root user.

  • Otherwise, use setuid(3) to become the desired non-root user.

Note that setreuid(3) is preferred over seteuid(3)[63] and setuid(3) because it allows sendmail to temporarily give away both its real and effective root privilege, then to get it back again. To illustrate the need for this behavior, consider processing a mailing list that saves mail to two different files:

/u/bill/archive        ← owned by the user bill, mode 4600
/u/alice/archive       ← owned by the user alice, mode 4600

Further consider that these files both have permissions of set-user-id to the individual users[64] and are writable only by the individual users. To perform delivery in this instance, sendmail must[65] first become bill (this requires root privilege). To become another user, sendmail forks. The parent remains root and the child becomes the user, bill in our example. When it is done, the child exits. The parent sendmail remains root so that it can next become alice. By retaining a real uid of root, sendmail is able to change its effective uid to one user after another as needed.

See the description of the test directory in USESETEUID on page 151 for more on this subject.

The Environment

As a general rule, programs should never trust their environment. Such trust can lead to exploitation that has grave security consequences. To illustrate, consider the often misused SunOS LD_LIBRARY_PATH environment variable. Programs that use shared libraries look at this variable to determine which shared library routines they should use and in what order they should load them. One form of attack against non-set-user-id programs (such as some delivery agents) is to modify the LD_LIBRARY_PATH variable (as in a user’s ~/.forward file) to introduce Trojan horse library routines in place of the real system’s library routines. Certainly, sendmail should not pass such variables to its delivery agents.

To improve security, early versions of V8 sendmail began deleting variables from its environment before passing them to its delivery agents. It removed the IFS variable to protect Bourne shell-script agents and all variables beginning with “LD_" to protect all delivery agents from shared library attacks.

Beginning with V8.7, sendmail now takes the opposite approach. Instead of trying to second-guess attackers, it constructs the delivery agent environment from scratch. In this scheme, it defines the AGENT variable as sendmail, and the TZ variable as is appropriate (see the TimeZoneSpec option, TimeZoneSpec on page 1110). Also, in support of operating systems that require them, it passes the ISP and SYSTYPE variables from its own environment to the delivery agent’s environment.

The E Configuration Command

When sendmail executes (runs) a delivery agent (The Child on page 757), it passes to that delivery agent an environment that includes only the items described earlier. Some delivery agents, however, might require additional environment variables to function properly. For those special cases, sendmail offers the E configuration command to set individual environment variables that will be passed to all delivery agents:

Evar=value

The var is the environment variable that will be either defined or redefined. It is immediately followed (with no intervening space) by an equal-sign and then (again with no intervening space) by the value that will be assigned to it.

If the =value is missing, sendmail looks up the variable var in its environment and, if it is found, uses that value. If the = is present but the value is absent, the var is assigned an empty string (a single zero byte). If the var is missing, a variable name that is an empty string is used.

The var is looked up to see whether it is already a part of the delivery agent’s environment. If it is, it is redefined to be the new value. If it is not, it is added to that list of variables. If that addition will cause the list to exceed MAXUSERENVIRON variables (currently defined as 100 in conf.h, MAX... on page 120), the definition is silently ignored.

Whether or not the var was added to, or updated in, the delivery agent’s environment, it is always added or updated to sendmail’s environment with putenv(2). If this call fails, sendmail logs and prints the following message:

setuserenv: putenv(var=value) failed

Only one var can be defined per E command. Additional environment variables require multiple E commands. Each E command affects all delivery agents. There is no way to tune the environment on a per-delivery-agent basis.

SMTP Probes

Although SMTP probes can be legitimate uses of the network, they can also pose potential risks. They are sometimes used to see whether a bug remains unfixed. Sometimes they are used to try to gather user login names or to feed a program unexpected input in such a way that it breaks and gives away root privilege.

SMTP Debug

An “unfixed bug” probe can use the SMTP debug and showq commands. The SMTP debug command allows the local sendmail to be placed into debugging mode (as with the -d command-line switch, The Syntax of -d on page 530) from any other machine anywhere on the network. The SMTP showq command allows outsiders to view the contents of the mail queue.

If SMTPDEBUG (SMTPDEBUG on page 144) is defined when sendmail is compiled, the SMTP debug and showq commands are allowed to work; otherwise, they are disabled. SMTPDEBUG should be defined only when modifying the sendmail code and testing a new version. It should never be defined in an official release of sendmail. To see whether it has been defined at your site, run the following command:

% telnet localhost 25
Trying 123.45.6.7 ...
Connected to localhost.
Escape character is '^]'.
220 localhost sendmail 8.12 ready at Fri, 13 Dec 2002 06:36:12 −0800
debug
500 Command unrecognized
quit
221 localhost.us.edu closing connection
Connection closed by foreign host.
%

When connected, enter the command debug. If you get the answer 500 Command unrecognized, you know that SMTPDEBUG is not enabled. If, on the other hand, you get the answer 200 Debug set, SMTPDEBUG is defined on your system, and you should immediately take steps to correct the situation. Either contact your vendor and request a new version of sendmail, or get the sendmail source and compile it with SMTPDEBUG undefined.

When SMTPDEBUG is undefined and an outsider connects to the local machine and attempts to execute the debug or showq command, sendmail will syslog(3) a message such as the following:

Jul 22 07:09:00 here.domain sendmail[192]: "debug" command from there.domain
      (123.45.67.89)

This message shows the name of the machine that attempts the probe, or there.domain, and the IP address of that machine. Note that this message is logged only if the LogLevel option (LogLevel on page 1040) is nonzero.

SMTP VRFY and EXPN

You might be dismayed to learn that the login names of ordinary users can be used to break into a system. It is not, for example, all that unusual for a user to select a password that is simply a copy of his login name, first name, last name, or some combination of initials. A risk of attack can arise from outsiders guessing login names. Any that they find can be used to try to break in, and the SMTP VRFY gives an attacker the means to discover login names.

Login names are also a way to gather addresses for spam email messages. The SMTP VRFY command, too, can be used to collect names for that illicit use.

The SMTP VRFY command causes sendmail to verify that it will accept an address for delivery. If a user’s login name is given, the full name and login name are printed:

vrfy george
250 George Washington <george@wash.dc.gov>

Here, the 250 SMTP reply code (see RFC821) means a successful verification.[66] If the user is unknown, however, sendmail says so:

vrfy foo
550 5.7.1 foo... User unknown

The SMTP EXPN command is similar to the VRFY command, except that in the case of a mailing list, an aliases, or a ~/.forward file entry, it will show all the members. The SMTP EXPN command causes sendmail to expand (show all the recipients) of an address. To illustrate the risk, consider that many sites have aliases that include all or a large segment of users. Such aliases often have easily guessed names, such as all, everyone, or staff. A probe of all, for example, might produce something such as the following:

expn all
250-George Washington <george@wash.dc.gov>
250-Thomas Jefferson <tj@wash.dc.gov>
250-Ben Franklin <ben@here.us.edu>
250-Betsy Ross <msflag@ora.com>
250 John Q. Public <jqp@aol.com>

With well-designed passwords these full and login names can safely be given to the world at large. But if one user (say, jqp) has a poorly designed password (such as jqpublic), your site’s security can easily be compromised.[67] Note that not all uses of VRFY or EXPN represent probes. Some MUAs,[68] for example, routinely VRFY each recipient before sending a message.

SMTP VRFY and EXPN commands are individually logged in a form such as one of the following:

Sep 22 11:40:43 yourhost sendmail[pid]: other.host: vrfy all
Sep 22 11:40:43 yourhost sendmail[pid]: [222.33.44.55]: vrfy all
Sep 22 11:40:43 yourhost sendmail[pid]: other.host: expn all
Sep 22 11:40:43 yourhost sendmail[pid]: [222.33.44.55]: expn all

This shows that someone from the outside (other.host in the first and third examples) attempted to probe for usernames in the mailing list named all. In the second and last examples, the probing hostname could not be found, so the IP address is printed instead (in the square brackets). Note that this form of logging is enabled only if the LogLevel option (LogLevel on page 1040) is greater than 5.

Pre-V8 versions of sendmail do not report SMTP VRFY or EXPN attempts at all. Some versions of sendmail (such as the HP-UX version) appear to verify but really only echo the address stated.

V8 sendmail allows VRFY and EXPN services to be accepted or rejected on the basis of the setting of the PrivacyOptions option (PrivacyOptions on page 1065). For improved security, we recommend this setting for the PrivacyOptions option:

O PrivacyOptions=novrfy,noexpn

V8.10 and above sendmail allow VRFY and EXPN services to be selectively accepted or rejected on the basis of rules in the check_vrfy (check_vrfy and check_expn on page 707) and check_expn (check_vrfy and check_expn on page 707) rule sets. If, for example, you wish to allow VRFY from internal hosts, but wish to deny it for all outside hosts, you can do so by omitting a definition of the PrivacyOptions option as explained earlier, and by designing appropriate rules for the check_vrfy rule set.

The Configuration File

A number of security problems can be created by commands given carelessly in the configuration file. Such problems can be serious because sendmail starts to run as root, provided that it has not been given an unsafe command-line switch (such as -C; see -C on page 238) or an unsafe option (Options That Are Safe on page 951). It can continue as root until it delivers mail, whereupon it generally changes its identity to that of an ordinary user. When sendmail reads its configuration file, it can do so while it is still root. Consequently, as we will illustrate, when sendmail is improperly configured, it might be able to read and overwrite any file.

The F Command—File Form

The file form of the F configuration command (The F Class Command on page 857) can be used to read sensitive information. That command looks like this in the configuration file:

FX/path pat

This form is used to read class macro entries from files. It can cause problems through a misunderstanding of the scanf(3) pattern pat. The /path is the name of the file, and the optional pat is a pattern to be used by scanf(3) (scanf(3) variations on page 858).

To illustrate the risk of the pat, consider the following configuration file entry:

Fw/etc/myhostnames %[^#]

Normally, the F command reads only the first whitespace-delimited word from each line of the file. But if the optional pattern pat is specified, the F command instead reads one or more words from each line based on the nature of the pattern. The pattern is used by scanf(3) to extract words, and the specific pattern used here, [^#], causes scanf(3) to read everything up to the first comment character (the #) from each line. This pat allows multiple hostnames to be conveniently listed on each line of the file. Now assume that a new administrator, who is not very familiar with sendmail, decides to add an F command to gather a list of UUCP hosts from the /etc/uucp/Systems file. Being a novice, the new administrator copies the existing entry for use with the new file:

FU/etc/uucp/Systems %[^#]

This is the same pattern that was correctly used for /etc/myhostnames. Unfortunately, the Systems file contains more than just host entries on each line:

linda Any ACU 2400 5551212  "" \d\n in:-\r-in: Uourhost word: MublyPeg
hoby Any ACU 2400 5551213  "" \d\n in:-\r-in: Uourhost word: FuMzz3.x

A part of each line (the last item in each) contains nonencrypted passwords. Prior to V8.12, an unscrupulous user, noticing the mistaken [^#] in the configuration file, could run sendmail with a -d36.5 debugging switch and watch each password being processed. For example:

% /usr/lib/sendmail -d36.5 -bt < /dev/null...some output deleted
STAB: hoby 1 entered
STAB: Any 1 entered
STAB: ACU 1 entered
STAB: 2400 1 entered
STAB: 5551213 1 entered
STAB: "" 1 type 1 val 0 0 200000 0
STAB: \d\n 1 entered
STAB: in:-\r-in: 1 entered
STAB: Uourhost 1 entered
STAB: word: 1 entered
STAB: FuMzz3.x 1 enterednote
STAB: local 3 type 3 val 34d00 0 0 0
STAB: prog 3 type 3 val 34d80 0 0 0

Note the third line from the bottom, where the password for the UUCP login into the host hoby is printed. Also note that this is no longer possible with V8.12 and above if sendmail is installed as non-set-user-id as recommended.

This example illustrates two rules about handling the configuration file:

  • Avoid using the F command to read a file that is not already publicly readable. To do so can reveal sensitive information. Even if the scanf(3) option is correct, a core dump[69] can be examined for sensitive information from otherwise secured files.

  • Avoid adding a new command to the configuration file by blindly copying and modifying another. Try to learn the rules governing the command first.

The F Command—Program Form

Another form of the F (File) configuration command is the program form, which looks like this:

FX|/path

Here, the | prefix to the /path tells sendmail that /path is the name of a program to run. The output produced by the program is appended to the class, here X.

To illustrate another potential security risk, consider a configuration file that is group-writable, perhaps by a few administrators who share the job of postmaster. To break into root, the attacker needs to assume the identity of only one of those users and, under that identity, edit the configuration file. Consider the following bogus entry added by an attacker to that configuration file:

FX|/tmp/.sh

Consider further a change to the DefaultUser option (DefaultUser on page 1000) that causes the default uid and gid to become those of root:

O DefaultUser=0:0

With these changes in place, the program (actually a shell script) called /tmp/.sh is run by sendmail to fill the class X with new values. All this seems harmless enough, but suppose /tmp/.sh does the unexpected:

#!/bin/sh
cp /bin/sh /tmp/.shell
chmod u+s /tmp/.shell

Here, the Bourne shell is copied to /tmp/.shell, and the set-user-id root bit is set. Now, any user at all can run sendmail and become root:

% ls -l /tmp/.shell
/tmp/.shell not found
% /usr/lib/sendmail -bt < /dev/null
% ls -l /tmp/.shell
-rwsr-xr-x  1 root       122880 Sep 24 13:20 /tmp/.shell

The program form of the F configuration command can clearly be dangerous. The sendmail configuration file must never be writable by anyone other than root. It should also live in a directory, every path component of which is owned by and writable only by root. (We’ll discuss this latter point in greater detail soon.) If the configuration file is created with the m4 technique, care must be taken to ensure that only root can write to the mc file, and that only root can use that mc file to install the configuration file.

The P= of Delivery Agents

Just as the program form of the F command can pose a security risk if the configuration file is poorly protected, so can the M delivery agent definition. Specifically, the P= equate for a delivery agent (P= on page 748) can be modified to run a bogus program that gives away root privilege. Consider the following modification to the local delivery agent:

Mlocal, P=/bin/mail, F=rlsDFMmnP, S=10, R=20, A=mail -d $u
            ↓
becomes
            ↓
Mlocal, P=/tmp/mail, U=0,F=SrlsDFMmnP,  S=10, R=20, A=mail -d $u
                ↑       ↑
note           note

Here, local mail should be delivered with the /bin/mail program, but instead it is delivered with a bogus frontend, /tmp/mail. If /tmp/mail is carefully crafted, users will never notice that the mail has been diverted. The S flag in the F= equate (F=S on page 780) causes sendmail to retain its default identity when executing the bogus /tmp/mail. The U=0 equate (U= on page 755) causes that default to become the identity of root.

Delivery agent P= equates must be protected by protecting the configuration file. As an additional precaution, never use relative pathnames in the P= equate.

The F=S and U=0 are especially dangerous. They should never appear in your configuration file unless you have deliberately placed them there and are 100% certain of their effect. For example, the local_lmtp feature (FEATURE(local_lmtp) on page 625) correctly sets them for the local delivery agent because the mail.local program is no longer set-user-id root.

StatusFile Option and the Statistics File

When sendmail attempts to record its delivery agent statistics (The statistics File on page 365), it checks for the existence and write permissions of the file specified by the StatusFile option (StatusFile on page 1095). Prior to V8.9, sendmail did not care where that file lived or what permissions it had—only that it existed.

A security problem could arise if one is tempted to locate the statistics file in a spool or temporary area. Consider the following location, for example:

define(`STATUS_FILE',`/usr/tmp/statistics')

Here, the administrator sets the StatusFile option to locate the statistics file in the /usr/tmp directory. The intention is that the file can be easily created by anyone who wishes to gather statistics, then removed. Unfortunately, the /usr/tmp directory is usually world-writable.

Thus, prior to V8.9, any unhappy or malicious user could bring the system to its knees:

% cd /usr/tmp
% ln -s /vmunix statistics

Here, sendmail clobbers the disk copy of the kernel. Nothing bad might happen at first,[70] but the machine will require manual intervention to boot in the future.[71] Clearly, precautions must be taken. For example, any file that sendmail writes to (such as the StatusFile option statistics file or the aliases database files) must be writable only by root and live in a directory, every path component of which is writable only by root.

Permissions

One technique that attackers use to gain root privilege is to first become a semiprivileged user such as bin or sys. Such semiprivileged users often own the directories in which root-owned files live. For example, consider the following:

drwxr-sr-x 11 bin      2560 Sep 22 18:18 /etc/mail
-rw-r--r--  1 root     8199 Aug 25 07:54 /etc/mail/sendmail.cf

Here, the /etc/sendmail.cf configuration file is correctly writable only by root. But the directory in which that file lives is owned by bin and writable by bin. Having write permission on that directory means that bin can rename and create files. An individual who gains bin permission on this machine can create a bogus sendmail.cf file by issuing only two simple commands:

% mv /etc/mail/sendmail.cf /etc/mail/...
% mv /tmp/sendmail.cf /etc/mail/sendmail.cf

The original sendmail.cf is renamed ... (a name that is not likely to be randomly noticed by the real system administrator). The bogus /tmp/sendmail.cf then replaces the original:

drwxr-sr-x 11 bin      2560 Sep 22 18:18 /etc/mail
-rw-r--r--  1 bin      4032 Nov 16 00:32 /etc/mail/sendmail.cf

Unix pays less attention to semiprivileged users than it does root. The user root, for example, is mapped to nobody over NFS, whereas the user bin remains bin. Consequently, the following rules must be observed to prevent malicious access to root-owned files:

  • All directories in the path leading to a root-owned file must be owned by root and writable only by root. This is true for all files, not just sendmail files.

  • Files owned by root must be writable only by root. Group write permission, although at times desirable, should consistently be avoided.

  • Because sendmail is running as root when processing the configuration file, care should be taken to ensure the safety of system files as well. All system directories and files must live in directories whose path component parts are owned by and writable only by root. All system files (except possibly set-user-id or set-group-id files) must be owned by root and be writable only by root. If any program “breaks” after securing permissions, complain to your vendor at once!

Dangerous Write Permissions

The sendmail program, of necessity, needs to trust its configuration file. To aid in the detection of risks, it checks the permissions of its configuration file when first reading that file. If the file is writable by group or world, sendmail logs the following message:[72]

configfile: WARNING: dangerous write permissions

If sendmail is being started as a daemon or is being used to initialize the aliases database, it will print the same message to its standard error output.

Permissions for :include:

The sendmail program doesn’t always run as root. When delivering mail, it often changes its identity into that of a nonprivileged user. When delivering to an :include: mailing list, for example, it can change its identity to that of the owner of the list. This, too, can pose security risks if permissions are not appropriate.[73] Consider the following aliases file entry:

newprogs: :include:/usr/local/lists/proglist

Here, notification of new programs is mailed to the alias newprogs. The list of recipients is taken from the following file:

-rw-rw-r—  2 bin  prog   704 Sep 21 14:46 /usr/local/lists/proglist

Because this file is owned by bin, sendmail changes its identity to bin when delivering to the list of recipients. Unfortunately, the file is also writable by the group prog. Anyone in the group prog can add a recipient to that list, including one of the form:

|/tmp/x.sh

This tells sendmail to deliver a copy of the message by running the program (a shell script) /tmp/x.sh. The sendmail program (which is still running as bin) executes that program as bin. Further, suppose the program /tmp/x.sh contains the following:

#!/bin/sh
cp /bin/sh /tmp/sh
chmod u+s /tmp/sh
cat - > /dev/null
exit 0

This causes bin first to make a copy of the Bourne shell in /tmp (a copy that will be owned by bin), and then to set the set-user-id bit on that copy (the u+s):

-rwsr-xr-x  1 bin    64668 Sep 22 07:38 /tmp/sh

The script then throws away the incoming mail message and exits with a zero value to keep sendmail unsuspecting. Through this process, an ordinary user in the group prog has created a set-user-id shell that allows anyone to become the semiprivileged user bin. From the earlier discussion (Permissions on page 164), you can see the trouble that can cause!

Mailing lists (:include:) must live in a directory, all the components of which are writable only by root. The lists themselves should be writable only by the owner.

Mailing list (:include:) files can safely be owned by root. When sendmail processes a root-owned mailing list, it changes itself to run as the user and group specified by the DefaultUser option (DefaultUser on page 1000). That option defaults to daemon[74] but should be set to the mailnull user and mailnull group. The DefaultUser option should never be set to root.

Permissions for ~/.forward Files

The ~/.forward file can pose a security risk to individual users. There is a higher degree of risk if the user is root or one of the semiprivileged users (such as bin). Because the ~/.forward file is like an individual mailing list (:include:) for the user, risk can be encountered if that file is writable by anyone but the user.[75] Consider the following, for example:

drwxr-xr-x 50 george guest        3072 Sep 27 09:19 /home/george/
-rw-rw-r—  1 george guest          62 Sep 17 09:49 /home/george/.forward

Here, the user george’s ~/.forward file is writable by the group guest. Anyone in group guest can edit george’s ~/.forward file, possibly placing something such as this into it:

\george
|"cp /bin/sh /home/george/.x; chmod u+s /home/george/.x"

Now all the attacker has to do is send george mail to create a set-user-id george shell. Then, by executing /home/george/.x, the attacker becomes george.

The semiprivileged users such as bin, and root in particular, should never have ~/.forward files. Instead, they should forward their mail by means of the aliases file directly.

User ~/.forward files must be writable only by the owning user. Similarly, user home directories must live in a directory that is owned and writable only by root, and must themselves be owned and writable only by the user.

Some users, such as the pseudouser uucp, have home directories that must be world-writable for software to work properly. If that software is not needed (if a machine, for example, doesn’t run UUCP software), that home directory should be removed. If the directory must exist and must be world-writable, to ensure that the ~/.forward file is never processed you can create an alias in the aliases database for uucp that points to root. For example:

uucp:   root

Thereafter, although the ~uucp directory is world-writable (so that anyone can remove anything from it), that file will be ignored by sendmail, even if someone places a ~/.forward file in it.

Note that all critical dot files in a world-writable home directory must be protected from creation by others. Each of .rhosts, .login, .cshrc, .profile, and .logout, for example, should be made a nonempty, root-owned directory with mode 000. World-writable home directories must be owned by root instead of by the user, and they must have the +t (sticky bit) set.

When processing a user’s ~/.forward file, sendmail requires that the file be owned by the user or by root. If ownership is correct, it then examines the ~/.forward file’s permissions. If that file is world- or group-writable, sendmail ignores (and logs) attempts to run programs and to write directly to files.

Table 4-1 shows the recommended ownerships and permissions for all the files and directories in the sendmail system. The path components will vary depending on the vendor version of sendmail you are running. For example, where we show the /usr/sbin/sendmail directory, your site might use /usr/lib/sendmail, or even /usr/lib/mail/sendmail.

In Table 4-1, we show the owner as root, or as a T (which means the owner can be the user listed with the TrustedUser option; TrustedUser on page 1112), or as an R (which means the owner must be the one specified by the RunAsUser option; RunAsUser on page 1083) if that option was specified. Under the “Owner” column, we show a colon and the group when the group is important.

Table 4-1. Recommended permissions for V8.12 and above

Path

Type

Owner

Mode

 

/

Directory

root

0755

drwxr-xr-x

/usr

Directory

root

0755

drwxr-xr-x

/usr/sbin[a]

Directory

root

0755

drwxr-xr-x

/usr/sbin/sendmail

File

root:smmsp

02555

-r-xr-sr-x[b]

/etc

Directory

root

0755

drwxr-xr-x

/etc/mail

Directory

root,T

0755

drwxr-xr-x

/etc/mail/sendmail.cf

File

root,T

0644 or 0640

 

/etc/mail/statistics

File

root,T,R

0600

-rw-------

/etc/mail/helpfile

File

root,T

0444

-r--r--r--

/etc/mail/aliases

File

root,T

0644

-rw-r--r--

/etc/mail/aliases.pag

File

root,T,R

0640

-rw-r-----

/etc/mail/aliases.dir

File

root,T,R

0640

-rw-r-----

/etc/mail/aliases.db

File

root,T,R

0640

-rw-r-----

F/path

Directory

root,T

0755

drwxr -xr-x

/path/file

File

T

0444 or 0644

 

/var

Directory

root

0755

drwxr-xr-x

/var/spool

Directory

root

0755

drwxr-xr-x

/var/spool/mqueue

Directory

root,R

0700[c]

drwx------

/var/spool/clientmqueue

Directory

smmsp:smmsp

0770

drwxrwx---

:include:/path

Directories

root

0755

drwxr -xr-x

:include:/path/list

File

n/a

0644

-rw-r--r--

[a] a The sendmail program sometimes lives in /usr/lib or in some other directory. If so, adjust this path accordingly.

[b] b As of V8.12, sendmail is no longer set-user-id root, but is instead set-group-id smmsp or the like, and sendmail is root only when it is run by root. The older versions of sendmail might need to be set-group-id kmem for the load average to be checked on some systems.

[c] c CERT (the Computing Emergency Response Team) and the sendmail document doc/op/op.me recommend that the queue directories be mode 0700 to prevent potential security breaches.

Don’t Blame sendmail

In DontBlameSendmail on page 1009, we describe the DontBlameSendmail option, which can be used to allow looser permissions. We mention this option here because its misuse can lead to a weakening of security.

Consider a site where you use group permissions to allow system administrators to edit :include: files, rather than allowing them to do so by becoming root. Note that these mailing lists include archive files—that is, entries that append messages to archive files.

Unless you tell sendmail otherwise, it will refuse to run programs listed in such group-writable :include: files, and also refuse to append to any files listed in such :include: files (append to archive files). Every time mail is sent to such a mailing list, sendmail will log the following warning:

/path: group writable :include: file, marked unsafe

You can prevent this warning and allow running of disallowed programs and appending to disallowed files by declaring the DontBlameSendmail option in your mc configuration file:

define(`confDONT_BLAME_SENDMAIL', `GroupWritableIncludeFileSafe')

This declaration tells sendmail that you consider it safe to append to archive files from inside :include: files, even when the :include: file is group-writable. The result is that you have streamlined your department’s operation, but you have done so at the price of security.

The sendmail program is paranoid about group-writable permissions because such permissions open the door to intrusion by insiders. Group permissions are managed via the passwd and group files, and :include: files can be silently edited with no record made about what was done to them. Contrast this approach to one that uses sudo(8) or a similar program, to manage access to root and other privileges. The sudo(8) program executes programs (such as an editor to edit an :include: file) with special permissions (such as root) and logs a record of each command executed.

It is vastly better to keep sendmail’s file permissions narrow and to use other security tools to manage those files. We recommend you never use the DontBlameSendmail option to loosen permissions. If you think you need to do so, you should review your overall approach. Try to find a safe way to satisfy your needs, rather than loosening sendmail’s security behavior.

The aliases File

The aliases file can easily be used to gain privileged (but not root) status if it is wrongly or carelessly administered. In addition to proper permissions and ownership, you should be aware of potentially harmful entries that you might have inherited from the vendor or previous administrators. For example, many vendors used to ship systems with a decode alias in the aliases file (this practice is becoming less common):

# you might wish to comment this out for security
decode:    |/usr/bin/uudecode

The intention is to provide an easy way for users to transfer binary files using mail. At the sending site, the user converts the binary to ASCII with uuencode(1), and then mails the result to the decode alias at the receiving site. That alias pipes the mail message through the /usr/bin/uudecode program, which converts the ASCII back into the original binary file.

The uudecode(1) program takes the name of the file to create from the file it is decoding. That information is in the begin line, used by uudecode. For example, here’s an attempt to use uudecode(1) to place a bogus queue file directly into the sendmail queue:

begin 777 /var/spool/mqueue/qfl0NFMs3g016812

Here, the begin tells uudecode to begin conversion. The 777 is the permissions to give to the file that will be created. That is followed by the full pathname of the file. If the queue directory were wrongly owned by daemon, any outsider could create a bogus queued message at your site.

Some versions of uudecode (such as the one with SunOS) will create set-user-id files. That is, a begin line such as the following can be used to create a set-user-id daemon shell in /tmp:

begin 4777 /tmp/sh

The decode alias should be removed from all aliases files. Similarly, every alias that executes a program—that you did not place there yourself and check completely—should be questioned and probably removed.

The Alias Database Files

The aliases(5) file is often stored in dbm(3) or db(3) database format for faster lookups. The database files live in the same directory as the aliases file. For all versions of sendmail they are called aliases.dir and aliases.pag for dbm(3), but for V8 sendmail, only a single database file might exist and be called aliases.db for db(3).

It is useless to protect the aliases(5) file if you do not protect its corresponding database files. If the database files are not protected, the attacker can create a private aliases file and then run:

% /usr/lib/sendmail -oA./aliases -bi

This causes sendmail to build ./aliases database files in the current directory. The attacker then copies those bogus database files over the unprotected system originals. The sendmail program never detects the change because the database files appear to be newer than the aliases file.

Note, for best security, that the aliases file and its database files must be owned by root, and be writable only by root. They must live in a directory, every path component of which is owned by and writable only by root.

Forged Mail

Although most users are aware that paper mail can be forged, many are blissfully unaware that email can also be forged. Forged mail can lead to a serious breach of security. Two points of vulnerability that require particular attention are the queue file and the SMTP interface of sendmail.

Forging with the Queue Directory

All versions of sendmail trust the files in the mail queue. They assume that only sendmail has placed files there. As a consequence, a poorly protected queue directory can allow the attacker to create mail that looks 100% authentic. This can be used to send forged mail, to append to system-critical files, or to run arbitrary programs as root or other users. Consider the following bogus qfl0NFMs3g016812 file for sending forged mail (qf files are described in The qf File Internals on page 445):

V8
T829313834
N0
P943442
Fs
$_root@yourhost
S<root@yourhost>
RPFD:george@yourhost
H?P?return-path: <root@yourhost>
Hmessage-id: <200712141257.l0NFSKNK016837@yourhost>
HFrom: root@yourhost
HDate: Thu, 14 Dec 2007 05:47:46 −0800
HTo: george@yourhost
HSubject: Change your Password Now!!

This qf file causes mail to be sent to george that appears in all ways to come from root. There is nothing in this qf file to indicate to the recipient (or to sendmail) that the message is not authentic. Now further suppose that the df file (the message body) contains the following text:

The system has been compromised. Change your password NOW!
Your new password must be:

                           Fuzz7bal
Thank you,
        —System Administration

Unfortunately, in any large organization there will be more than a few users who will obey a message such as this. They will gladly change their password to one assigned to them, thereby providing the attacker with easy access to their accounts.

The queue directory must be owned by and writable only by root or the user defined by the RunAsUser option (RunAsUser on page 1083). CERT recommends that the queue directory always be mode 0700.

The MSP queue of V8.12 and above (typically /var/spool/clientmqueue) must be owned by smmsp, with group smmsp, and should be mode 0770.

The queue files placed into the queue by sendmail must be well protected by defining narrow default permissions with the TempFileMode option (TempFileMode on page 1097) prior to V8.12, or the QueueFileMode option (QueueFileMode on page 1071) beginning with V8.12. A default of 0600 is best for the main queue, and a default of 0660 is recommended for the MSP queue.

Forging with SMTP

We won’t illustrate the SMTP interaction here. But note that anyone can connect to your local sendmail via telnet(1) at port 25 or run sendmail with the -bs command-line switch. Once connected, sendmail must, of necessity, believe everything it receives. The only exception is the hostname sent in the HELO or EHLO message.[76] In that case, the sendmail program looks up the real hostname based on the connection. If the stated hostname and the real hostname differ, the false name is used as the name of the sending host with the real name added in parentheses:

250 your.host Hello false.host (real.host), pleased to meet you

The real hostname is then used as the sending hostname in the construction of all headers. The result (the header and body received by the user) might look something like this:

From root@false.host Dec 14 14:36:40 2007
Received: from false.host (real.host [real.IP.address]) by your.host (8.14.1/8.14.1)
        id AA00998; Thu, 14 Dec 2007 14:36:38 −0700
Message-Id: <200712141257.l0NFSKNK016837@yourhost>
From: root@false.host (System Administration)
To: you@your.host
Subject: Change your password now!
Date: Thu, 14 Dec 2007 05:47:46 −0800

To improve security at our location you are requested to immediately
change your password. The password you have been assigned is:

        7Fuzzy1's

Thank you,
        --root

Fortunately, this Received: header contains the name of the real host (which is not always the case). An attentive user can tell that this is a forged message because the host in that header line differs from the false hostname used in the other header lines.

However, most mail-reading programs allow users to filter out (prevent your seeing) uninteresting header lines.[77] Typically, users choose to ignore headers such as Received: and Message-ID:. For such users, the task of detecting forged mail is much more difficult. Instead of seeing the earlier message with real hostnames, they might see the following with only false names:

From root@false.host Dec 14 14:36:40 2007
From: root@false.host (System Administration)
To: you@your.host
Subject: Change your password now!
Date:  Thu, 14 Dec 2007 14:36:38 −0800
To improve security at our location you are requested to immediately
change your password. The password you have been assigned is:

        7Fuzzy1's

Thank you,
        —root

Clearly, a user who sees only this much of the mail message will be more likely to believe that it is real. There are several ways you can educate your users that mail can be forged:

  • Teach users what to look for when they receive a message of questionable authenticity.

  • Rarely, if ever, send mail as root. Always communicate as yourself and always use a distinctive style of writing. If users never see mail from root, they will be more likely to question such mail when it arrives. Even if the forger pretends to be you, that forger will likely not be in a position to imitate your distinctive writing style.

  • Train users to never send (or ask to receive) clear-text passwords or other security-related information by email.

  • Train users to use digital signatures, such as PGP or S/MIME, to authenticate email contents.

Security Features

We now turn our attention from security problems to security features. Many security features are discussed in the various README files supplied with the sendmail source distribution. In this section, we discuss the most common security features:

  • The T configuration command (class t) defines which users are allowed to use the -f command-line switch to override the sender address with one of their own, and which users are allowed to rebuild the aliases database.

  • The smrsh program replaces /bin/sh as the program run by the prog delivery agent to execute programs. The smrsh program is simple yet immensely valuable. We recommend that it be routinely installed on all your machines. The smrsh program is described in detail in The smrsh Program on page 379.

  • Several options can be used to tighten security and to provide reports of security violations.

  • The /etc/shells file prevents ordinary users from running programs on your mail server.

Trusted Users

Under pre-V8 sendmail, trusted users are those who are allowed to use the -f command-line switch (-f on page 241) to override the sender address with one of their own. V8.1 sendmail eliminated this configuration command. V8.7 restored it, but as a class, and uses that class only to suppress warning headers. V8.11 and above allow only users in that class to rebuild the aliases database.

Trusted users are necessary for certain kinds of mail to flow properly. For example, the rmail(8) program of the UUCP suite of programs runs set-user-id to uucp. If rmail were not to use the -f command-line switch, all mail from UUCP would wrongly appear to come from the uucp user. To circumvent this problem, rmail runs sendmail as:

/usr/lib/sendmail -f reallyfrom

This tells sendmail to show, in both the header and envelope, the message as being from reallyfrom, rather than from uucp.

The concept of a trusted user is intended to prevent ordinary users from changing the sender address and thereby forging mail. Although that intention is laudable and good for UUCP, it can cause problems with mailing lists. Consider the following:

list: "|/usr/lib/sendmail -oi -flist-request -odi list-real"
list-real:    :include:/export/share/mail-lists/list.list

The intention here is for all mail sent to the mailing list named list to be dispatched as though it were sent from the address list-request (the -f). This causes errors to be returned to the maintainer of the list (the list-request), but replies still go to the real sender.

Unfortunately, this scheme fails when mail is posted to list from the local machine. Recall that only trusted users can change the identity of the sender with -f. This is why V8.1 sendmail eliminated the concept of the trusted user (anyone could use the -f switch).

Declare trusted users (ignored V8.1 through V8.6)

Trusted users are defined by those lines in the sendmail.cf file that begin with the uppercase letter T. Only trusted users can use the sendmail program’s -f command-line switch to specify who sent the message. Beginning with V8.7 sendmail, the class t can also be used.

The T sendmail.cf command must begin a line. One or more space-delimited usernames then follow on that same line. There can be multiple T commands in a sendmail.cf file, each adding names to the list of trusted users. Prior to V8 there could be, at most, MAXTRUST trusted users, where MAXTRUST was defined in conf.h when you compiled sendmail. Beginning with V8.7, there is no limit:

T uucp                                       ← legal in V8.1 through V8.6 but
ignored
Troot daemon                                 ← legal in V8.1 through V8.6 but
ignored
Ct uucp                                      ← ignored pre-V8.7
Ctroot daemon                                ← ignored pre-V8.7
define(`confTRUSTED_USERS',`root daemon')    ← V8.7 and above in mc file

The two T commands show that there might optionally be whitespace between the T and the first name in any list of names. They indicate that uucp, root, and daemon are trusted and have been added to the list of trusted users in that order. The two class declarations show a similar declaration for use beginning with V8.7 sendmail (but note that V8.7 and above can still use the old syntax).

Prior to V8 sendmail, if you listed more than MAXTRUST trusted users, sendmail printed and syslog(3)'ed a message such as this:

sendmail: too many T lines, 32 max

This message was not fatal. The sendmail program issued it for each excess T line (ignored those trusted users) and continued to run. V8 sendmail has implemented trusted users as a class, and there is no longer any limit imposed.

Prior to V8 sendmail, if a user who was not trusted attempted to use the -f switch, that attempt was silently ignored (silently disallowed). Beginning with V8.7 sendmail, if a user who is not trusted attempts to use the -f switch, that attempt can produce an X-Authentication-Warning: header (X-Authentication-Warning: on page 1167) if the PrivacyOptions option (PrivacyOptions on page 1065) has authwarnings listed.

Even though some users find them annoying, we recommend that you always enable X-Authentication-Warning: headers. They warn of suspicious behavior. If the behavior is legitimate, modify that behavior to eliminate the header instead of eliminating the more valuable warning headers.

Security Options

The sendmail program offers several options that can help you to improve the security at your site. Some we have discussed already. We touch on a few more in this section, and provide a recommended setting where appropriate. For a full description of each, see the sections referenced.

The DefaultUser option

The DefaultUser option (DefaultUser on page 1000) can be used to ensure that the default identity (when it is not running as root) is a safe one. CERT recommends that you create a pseudouser whose uid and gid are used nowhere on your system, and then define the DefaultUser option to be that pseudouser. As an additional precaution, make sure that pseudouser lacks a valid shell and has no valid home directory:

mailnull:*:32765:32765:Sendmail Default User:/no/such/directory:/bin/false

At the same time, set up a group entry for this user’s group:

mailnull:*:32765:

This is necessary if you want to refer to this group symbolically at some later time. This is also recommended to avoid the risk of someone else reusing that group ID for another purpose in the future.

Avoid using the name nobody, because root is mapped to nobody over NFS. If root were to create a file over NFS that it thought was safe because root owned it and because it was readable only by root, that root user would be surprised to find that file owned by nobody. Consequently, we recommend that in an NFS environment, you set the default user to one less than nobody.[78] For example, if nobody has the uid 65534, you could set up:

mailnull:*:65533:65533:Sendmail Default User:/no/such/directory:/bin/false

The RunAsUser option (V8.8 and above)

The RunAsUser option (RunAsUser on page 1083) is just like the DefaultUser option (DefaultUser on page 1000) described earlier. But instead of setting the identity to be used when sendmail is not running as root, this option sets the identity to replace root. Because a non-root program cannot assume the identity of other users, this option cannot be used in conjunction with the DefaultUser option. Instead, this option sets the only identity that sendmail will use.

Although it is tricky to get sendmail to run as a non-root process in all circumstances, V8.12 offers a way to get part of sendmail to do this. The idea is that initial mail submission (by local users) can be sent safely with a non-root sendmail, whereas handling inbound mail and local delivery can require a root process. V8.12 handles this division by creating two separate sendmail processes, handling the two separate roles. See Install sendmail on page 60 for a complete explanation of this process.

The TrustedUser option (V8.10 and above)

The TrustedUser option (TrustedUser on page 1112) defines the user that can administer sendmail. If set, this user will own database map files (such as aliases), and will also own the control socket (ControlSocketName on page 990). Even though only root can start sendmail, this user can stop and restart the sendmail daemon.

By setting this option, you can employ a user other than root to administer sendmail. But if you have been administering sendmail as root, you cannot simply set this option and be done. Instead, you need to shut down sendmail, make a few changes and then restart.

  • The first change is needed to ensure that this trusted user can edit the source files for database files created by sendmail (the aliases database).

  • The second change is needed to remove the control socket (if you use one) so that sendmail can create it with the proper ownerships.

With these simple changes in place, you can add the following line to your mc configuration file, and build and install a new configuration file from it:

define(`confTRUSTED_USER',`user')

Here, user is a user login name, or a user ID number.

When you restart sendmail with this new trusted user in place, you can thereafter routinely employ that user to administer sendmail.

The ForwardPath option

The ForwardPath option (ForwardPath on page 1034) lists a series of directories that sendmail will search for user ~/.forward files. At most sites, there are users who are savvy and able to correctly administer their own ~/.forward files, but there are others who are untrained or careless. You can allow experienced users to use the ~/.forward facility, while denying this ability to the others with the ForwardPath option:

O ForwardPath=/usr/local/etc/forwards/$u.forward:$z/.forward

Here, sendmail will first search the /usr/local/etc/forwards directory to find a file that begins with the user’s login name (the $u, $u on page 848) followed by a .forward. If you set up such a file for the untrained user—say, bob:

-rw-r—r—  1 root  system   0 Dec 13  2002  /usr/local/etc/forwards/bob.forward

and if that file is empty, bob’s mail will always be delivered locally, regardless of what bob puts in his ~/.forward file. For experienced users, you can omit their files from the /usr/local/etc/forwards directory, thus enabling them to use their own ~/.forward files.

The LogLevel option

The sendmail program normally logs a great deal of useful information via syslog (syslog(3) on page 514). There will be times, however, when the normal amount of information is insufficient. Consider, for example, that some outsider is using your site to forge mail. Because this is done over an SMTP connection, it would be handy to have both sides of all SMTP conversations logged. You can do this with the LogLevel option (LogLevel on page 1040):

O LogLevel=12      ← V8.8 and above configuration file
define(`confLOG_LEVEL', 12)   ← V8.8 and above mc configuration

Beginning with V8.8 sendmail, a level of 12 causes both sides of every SMTP conversation to be logged. That logging looks very similar to the logging produced by verbose mode (Verbose Mode (-v) on page 24).

Note that after changing the log level in your configuration file, you will need to restart the daemon. With V8.7 and above sendmail you restart the daemon like this:

# kill -HUP `head −1 /etc/sendmail.pid'

Be aware that a log level of 12 produces a huge amount of output. Be prepared to prune your logfiles more often than usual while running at this higher logging level.

The PostmasterCopy option

The PostmasterCopy option (PostmasterCopy on page 1064) causes a copy of every bounced message to be delivered to a named user. Usually, that user is the person who handles email problems. But because clumsy intrusion attempts can result in bounced mail, there will be times when bounced mail should also be delivered to the security administrator. Consider the following:

——- Transcript of session follows ——-
 >>> RCPT To:<root@your.site.domain>
 <<< 550 cannot open /tmp/.../getshell: No such file or directory
 550 5.7.1 cannot open /tmp/.../getshell: No such file or directory

This bounced mail message indicates that someone tried to become root by breaking through your aliases database.

Users are added to the list of those who get copies of bounced messages with the PostmasterCopy option:

O PostmasterCopy=postmaster,securitymasteradded

Here, securitymaster (probably an alias to a real user) was added.

The PrivacyOptions option

The PrivacyOptions option (PrivacyOptions on page 1065) is used to limit the amount of information offered to the outside world and to limit other kinds of access. The most restrictive setting for the PrivacyOptions option is probably best:

define(`confPRIVACY_FLAGS', ``goaway,restrictmailq,restrictqrun'')

This setting disables the EXPN and VRFY SMTP commands, requires other sites to identify themselves before sending mail, and limits access to the mail queue directory. As a side effect, it also disables DSN parameters because goaway includes noreceipts. If that is a problem for you, you can manually set up everything that goaway does, but exclude noreceipts.[79] Note that the following line is split to fit the page:

define(`confPRIVACY_FLAGS', ``needmailhelo,noexpn,novrfy,noverb,authwarnings,
restrictmailq,restrictqrun'')

As a general rule, it is best to begin with tight security. This minimizes your risk from the beginning and allows you to cautiously ease restrictions at a comfortable rate. Beginning with loose restrictions can force you to tighten restrictions in a panic when it is least convenient to do so.

The SafeFileEnvironment option

Beginning with V8.7 sendmail, the SafeFileEnvironment option (SafeFileEnvironment on page 1084) determines how delivery will be made to files. Ordinarily, sendmail will deliver to anything, provided that it has permission to do so (Delivery to Files on page 466). It can, for example, deliver by appending to ordinary files or by writing to a device such as /dev/log.

If the SafeFileEnvironment option is declared, sendmail will deliver only to ordinary files. This improves security by preventing anyone from scribbling over sensitive things, such as directories and devices. (Beginning with V8.8 sendmail, it is still OK to write to /dev/null even though this option is set.)

The SafeFileEnvironment option can also be used to define a directory under which all files that will be appended to must exist. This might inconvenience some users but will generally improve the security of your site. We recommend:

O SafeFileEnvironment=/pathconfiguration file
define(`confSAFE_FILE_ENV',`/path')mc configuration

This takes care of both security enhancements. Of course, you will need to create the directory specified in /path and populate it with the appropriate files.

Note that, just before appending to a file, sendmail does a chroot(2) into /path. As a consequence, an entry such as the following requires that the full path exist, such as /path/admin/mail:

bob:     \bob, /admin/mail/bob.archive

But sendmail is also clever, and if an aliases path begins with the same path as the SafeFileEnvironment path, and that latter path is removed before the write:

bob:     \bob, /path/admin/mail/bob.archive

Here, because the SafeFileEnvironment option specifies /path, sendmail will perform the chroot(2) into /path, then will strip /path from the aliases file entry to form /admin/mail.

If all you want to do is prevent writing to directories and devices, and if you do not want to place all files in a special path, you can accomplish this by defining /path as the root directory:

O SafeFileEnvironment=/

The TempFileMode and QueueFileMode options

The TempFileMode option (TempFileMode on page 1097) specifies the mode (file permissions) to give all temporary files and queue files. Beginning with V8.12, the QueueFileMode option (QueueFileMode on page 1071) specifies the permissions given to queue files. In general, all files that are created by sendmail should be considered proprietary for safety’s sake. We recommend a setting of:

O TempFileMode=0600       ← pre-V8.12, for all temp files and queue files
O QueueFileMode=0600      ← V8.12 and above, for queue files only, in sendmail.cf
O QueueFileMode=0660      ← V8.12 and above, for MSP queue files only, in submit.cf

With this narrow setting, the risk of accidental or malicious easing of permissions of your mail archive directories or queue becomes less of a risk.

The /etc/shells File

To prevent certain users from running programs or writing to files by way of the aliases or ~/.forward files, V8 sendmail introduced the concept of a “valid shell.” Just before allowing delivery via an alias so:

|"/some/program"
/save/to/a/file

the user’s password entry is looked up. If the shell entry from that password entry is a valid one, delivery is allowed. A shell is valid if it is listed in the /etc/shells file.[80] If that file does not exist, sendmail looks up the shell in its internal list, which looks (more or less) like this:[81]

/bin/bsh
/bin/csh
/bin/ksh
/bin/pam
/bin/posix/sh
/bin/rksh
/bin/rsh
/bin/sh
/bin/tcsh
/usr/bin/bsh
/usr/bin/csh
/usr/bin/keysh
/usr/bin/ksh
/usr/bin/pam
/usr/bin/posix/sh
/usr/bin/rksh
/usr/bin/rsh
/usr/bin/sh
/usr/bin/tcsh

With this technique it is possible to prevent certain users from having sendmail running programs or delivering to files on their behalf. To illustrate, consider the need to prevent the ftp pseudouser from misusing sendmail:

ftp:*:1092:255:File Transfer Protocol Program:/u/ftp:/no/shell

Here, any attempt by ftp to send mail through a program or into a file will fail because the shell /no/shell is not a valid shell. Such mail will bounce with one of these two errors:

User ftp@here.us.edu doesn't have a valid shell for mailing to programs
User ftp@here.us.edu doesn't have a valid shell for mailing to files

Note that unusual circumstances might require you to allow users with invalid shells to run programs or deliver to files. To enable this for all such users (as on a mail server with restricted logins), place the following line directly in the /etc/shells file:

/SENDMAIL/ANY/SHELL/

To enable this for selected users, just replace their shell with a bogus one that is listed in /etc/shells:

ftp:*:1092:255:File Transfer Protocol Program:/u/ftp:/bogus/shell

We recommend that all pseudousers (such as bin and ftp) be given invalid shells in the password file and that /SENDMAIL/ANY/SHELL/ never be used.

Be warned, however, that if a user can get into your machine as ftp, it can be possible for that user to run another shell, such as csh(1). Thus, in addition to listing a bogus shell, you might need to take further steps to prevent such access.

Other Security Information

No single chapter on security can be fully complete. The subject is so complex and far-ranging that an entire book might not be enough. To augment the information we have given here, we recommend these other important sources:

http://www.sendmail.org/~gshapiro/

Gregory Shapiro has authored a number of fine papers on sendmail. Of special interest, as of this writing, is Sendmail Security (based on V8.12), a brief document that outlines much of what we have talked about in this chapter, and provides tips we have not covered.

sendmail/SECURITY

The file sendmail/SECURITY is supplied with the sendmail source distribution and mainly deals with a non-root setup. You should read this file each time you download a new sendmail release.

http://www.cert.org/

This is the official site for the CERT Coordination Center, which studies Internet security vulnerabilities, handles computer security incidents, and publishes security alerts. This is an excellent site for security information, and it allows you to sign up for a mailing list that can warn you about security incidents.

http://www.sans.org/

The official site for the SANS Institute, an organization that provides security training and information. This site allows you to subscribe to a mailing list that provides routine digests of security matters.

Practical Unix & Internet Security, Third Edition

By Simson Garfinkel and Gene Spafford (O’Reilly), this comprehensive book on security that includes information about many versions of Unix. It contains information about network security that is germane to sendmail administration.

Other web sources

Any of your favorite search engines can be used to find additional material about computer security in general, email security, and sendmail security in specific.

Pitfalls

  • The sendmail program is only as secure as the system on which it is running. Correcting permissions and the like is useful only if such corrections are systemwide and apply to all critical system files and programs.

  • Time spent tightening security at your site is best spent before a break-in occurs. Never suppose that your site is too small or of too little consequence to be attacked. Start out by being wary, and you will be more prepared when the inevitable happens.

  • Newer versions of perl(1) object to PATH environment variables that begin with a dot (such as .:/bin:/usr/bin). V8 clears the PATH variable before executing programs in a user’s ~/.forward file. Some shells put it back with the dot first. Under such versions of the Bourne shell, execute perl(1) scripts like this:

    |"PATH=/bin:/usr/bin /home/usr/bin/script.pl"
  • There is no check in the T command to determine that the names listed are the names of real users. That is, if you mistakenly entered Tuupc when you really meant Tuucp, pre-V8 sendmail remained silent and UUCP mail mysteriously failed. V8.7 and above sendmail log warning messages.



[59] * The default beginning with V8.12 is to install sendmail as a non-set-user-id program that operates as root only if it is run by root.

[60] That flaw has been eliminated—wrongly by some vendors who turned all debugging completely off, correctly by most who simply disabled SMTP debugging.

[61] Contrary to popular belief, sendmail does not run as root to handle local delivery (except that sendmail can deliver directly to files when necessary, but that is not directly germane to this discussion). Local delivery is handled by delivery agents (such as /bin/mail), which may run set-user-id root themselves (or set-group-id mail as in SysV).

[62] * But note that V8.8 sendmail has loosened the latter for use on firewall machines, where it won’t complain about non-root qf files if it is not running as root.

[63] Except when seteuid(3) is POSIX-compliant. Old implementations of seteuid(3) didn’t properly save the uid, hence the preference, in that case, for setreuid(3).

[64] * When delivering to files, sendmail will become the owner of the file if that file’s set-user-id bit is set and if no execute bits are set.

[65] We say “must” because in an NFS environment, root is mapped to nobody, so in that instance, even root won’t be able to write to bill’s files unless sendmail becomes bill.

[66] * See the F=q flag (F=q on page 778) for a way and reason to change this SMTP reply code to 252.

[67] The fingerd(8) daemon can also reveal login IDs.

[68] The GNU fingerd(8) daemon also uses VRFY to provide mailbox information.

[69] * Most versions of Unix disallow core dumps of set-user-id root programs.

[70] * Programs that need kernel symbols, such as ps(1), will cease to work or will produce garbage output.

[71] The savvy administrator can still boot off the network or from a CD-ROM and quickly install a new kernel.

[72] * This is done only when not in rule-testing mode to prevent spurious warnings when you already know you are using a weak configuration file with -C.

[73] We refer here to both file permissions and permissions granted by the DontBlameSendmail option (Don’t Blame sendmail on page 168). Beginning with V8.9, for example, the behavior we describe requires the DontBlameSendmail option to be set to GroupWritableIncludeFileSafe.

[74] * Actually, beginning with V8.10, it defaults to whichever of the following is found first to exist in the passwd file: mailnull, sendmail, or daemon. If none of those exists, the default becomes 1:1.

[75] Beginning with V8.9, the problem we describe is not possible with the default settings of the configuration file. However, if you enable the DontBlameSendmail option (Don’t Blame sendmail on page 168) with a setting of GroupWritableForwardFileSafe, you override the default safety features and allow this dangerous behavior.

[76] * V8 sendmail also tries to verify the connection itself with identd, if possible.

[77] In fact, old versions of the GNU emacs(1) mail reader delete those lines irrevocably.

[78] * If that user ID is already in use, find an available number that is below nobody’s number, and use it instead.

[79] * Actually, goaway also includes needexpnhelo and needvrfyhelo, but these are superseded by noexpn and novrfy, respectively.

[80] * The /etc/shells file is also used by the ftpd daemon, and by other daemons, to screen users.

[81] This is an amalgamation of many vendor lists. See conf.c in the source distribution for details.