|
0
|
1 |
Background: Every few months CERT announces Yet Another Security Hole In
|
|
|
2 |
Sendmail---something that lets local or even remote users take complete
|
|
|
3 |
control of the machine. I'm sure there are many more holes waiting to be
|
|
|
4 |
discovered; sendmail's design means that any minor bug in 46000 lines of
|
|
|
5 |
code is a major security risk. Other popular mailers, such as Smail, and
|
|
|
6 |
even mailing-list managers, such as Majordomo, seem nearly as bad.
|
|
|
7 |
|
|
|
8 |
Note added in 1998: I wrote the above paragraph in December 1995, when
|
|
|
9 |
the latest version of sendmail was 8.6.12 (with 41000 lines of code).
|
|
|
10 |
Fourteen security holes were discovered from sendmail 8.6.12 through
|
|
|
11 |
8.8.5. See http://pobox.com/~djb/docs/maildisasters/sendmail.html.
|
|
|
12 |
|
|
|
13 |
I started working on qmail because I was sick of this cycle of doom.
|
|
|
14 |
Here are some of the things I did to make sure that qmail will never let
|
|
|
15 |
an intruder into your machine.
|
|
|
16 |
|
|
|
17 |
|
|
|
18 |
1. Programs and files are not addresses. Don't treat them as addresses.
|
|
|
19 |
|
|
|
20 |
sendmail treats programs and files as addresses. Obviously random people
|
|
|
21 |
can't be allowed to execute arbitrary programs or write to arbitrary
|
|
|
22 |
files, so sendmail goes through horrendous contortions trying to keep
|
|
|
23 |
track of whether a local user was ``responsible'' for an address. This
|
|
|
24 |
has proven to be an unmitigated disaster.
|
|
|
25 |
|
|
|
26 |
In qmail, programs and files are not addresses. The local delivery
|
|
|
27 |
agent, qmail-local, can run programs or write to files as directed by
|
|
|
28 |
~user/.qmail, but it's always running as that user. (The notion of
|
|
|
29 |
``user'' is configurable, but root is never a user. To prevent silly
|
|
|
30 |
mistakes, qmail-local makes sure that neither ~user nor ~user/.qmail is
|
|
|
31 |
group-writable or world-writable.)
|
|
|
32 |
|
|
|
33 |
Security impact: .qmail, like .cshrc and .exrc and various other files,
|
|
|
34 |
means that anyone who can write arbitrary files as a user can execute
|
|
|
35 |
arbitrary programs as that user. That's it.
|
|
|
36 |
|
|
|
37 |
|
|
|
38 |
2. Do as little as possible in setuid programs.
|
|
|
39 |
|
|
|
40 |
A setuid program must operate in a very dangerous environment: a user is
|
|
|
41 |
under complete control of its fds, args, environ, cwd, tty, rlimits,
|
|
|
42 |
timers, signals, and more. Even worse, the list of controlled items
|
|
|
43 |
varies from one vendor's UNIX to the next, so it is very difficult to
|
|
|
44 |
write portable code that cleans up everything.
|
|
|
45 |
|
|
|
46 |
Of the twenty most recent sendmail security holes, eleven worked only
|
|
|
47 |
because the entire sendmail system is setuid.
|
|
|
48 |
|
|
|
49 |
Only one qmail program is setuid: qmail-queue. Its only purpose is to
|
|
|
50 |
add a new mail message to the outgoing queue.
|
|
|
51 |
|
|
|
52 |
|
|
|
53 |
3. Do as little as possible as root.
|
|
|
54 |
|
|
|
55 |
The entire sendmail system runs as root, so there's no way that its
|
|
|
56 |
mistakes can be caught by the operating system's built-in protections.
|
|
|
57 |
In contrast, only two qmail programs, qmail-start and qmail-lspawn,
|
|
|
58 |
run as root.
|
|
|
59 |
|
|
|
60 |
|
|
|
61 |
4. Move separate functions into mutually untrusting programs.
|
|
|
62 |
|
|
|
63 |
Five of the qmail programs---qmail-smtpd, qmail-send, qmail-rspawn,
|
|
|
64 |
qmail-remote, and tcp-env---are not security-critical. Even if all of
|
|
|
65 |
these programs are completely compromised, so that an intruder has
|
|
|
66 |
control over the qmaild, qmails, and qmailr accounts and the mail queue,
|
|
|
67 |
he still can't take over your system. None of the other programs trust
|
|
|
68 |
the results from these five.
|
|
|
69 |
|
|
|
70 |
In fact, these programs don't even trust each other. They are in three
|
|
|
71 |
groups: tcp-env and qmail-smtpd, which run as qmaild; qmail-rspawn and
|
|
|
72 |
qmail-remote, which run as qmailr; and qmail-send, the queue manager,
|
|
|
73 |
which runs as qmails. Each group is immune from attacks by the others.
|
|
|
74 |
|
|
|
75 |
(From root's point of view, as long as root doesn't send any mail, only
|
|
|
76 |
qmail-start and qmail-lspawn are security-critical. They don't write any
|
|
|
77 |
files or start any other programs as root.)
|
|
|
78 |
|
|
|
79 |
|
|
|
80 |
5. Don't parse.
|
|
|
81 |
|
|
|
82 |
I have discovered that there are two types of command interfaces in the
|
|
|
83 |
world of computing: good interfaces and user interfaces.
|
|
|
84 |
|
|
|
85 |
The essence of user interfaces is _parsing_---converting an unstructured
|
|
|
86 |
sequence of commands, in a format usually determined more by psychology
|
|
|
87 |
than by solid engineering, into structured data.
|
|
|
88 |
|
|
|
89 |
When another programmer wants to talk to a user interface, he has to
|
|
|
90 |
_quote_: convert his structured data into an unstructured sequence of
|
|
|
91 |
commands that the parser will, he hopes, convert back into the original
|
|
|
92 |
structured data.
|
|
|
93 |
|
|
|
94 |
This situation is a recipe for disaster. The parser often has bugs: it
|
|
|
95 |
fails to handle some inputs according to the documented interface. The
|
|
|
96 |
quoter often has bugs: it produces outputs that do not have the right
|
|
|
97 |
meaning. Only on rare joyous occasions does it happen that the parser
|
|
|
98 |
and the quoter both misinterpret the interface in the same way.
|
|
|
99 |
|
|
|
100 |
When the original data is controlled by a malicious user, many of these
|
|
|
101 |
bugs translate into security holes. Some examples: the Linux login
|
|
|
102 |
-froot security hole; the classic find | xargs rm security hole; the
|
|
|
103 |
Majordomo injection security hole. Even a simple parser like getopt is
|
|
|
104 |
complicated enough for people to screw up the quoting.
|
|
|
105 |
|
|
|
106 |
In qmail, all the internal file structures are incredibly simple: text0
|
|
|
107 |
lines beginning with single-character commands. (text0 format means that
|
|
|
108 |
lines are separated by a 0 byte instead of line feed.) The program-level
|
|
|
109 |
interfaces don't take options.
|
|
|
110 |
|
|
|
111 |
All the complexity of parsing RFC 822 address lists and rewriting
|
|
|
112 |
headers is in the qmail-inject program, which runs without privileges
|
|
|
113 |
and is essentially part of the UA.
|
|
|
114 |
|
|
|
115 |
|
|
|
116 |
6. Keep it simple, stupid.
|
|
|
117 |
|
|
|
118 |
See BLURB for some of the reasons that qmail is so much smaller than
|
|
|
119 |
sendmail. There's nothing inherently complicated about writing a mailer.
|
|
|
120 |
(Except RFC 822 support; but that's only in qmail-inject.) Security
|
|
|
121 |
holes can't show up in features that don't exist.
|
|
|
122 |
|
|
|
123 |
|
|
|
124 |
7. Write bug-free code.
|
|
|
125 |
|
|
|
126 |
I've mostly given up on the standard C library. Many of its facilities,
|
|
|
127 |
particularly stdio, seem designed to encourage bugs. A big chunk of
|
|
|
128 |
qmail is stolen from a basic C library that I've been developing for
|
|
|
129 |
several years for a variety of applications. The stralloc concept and
|
|
|
130 |
getln() make it very easy to avoid buffer overruns, memory leaks, and
|
|
|
131 |
artificial line length limits.
|