|
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. |