autoupdate
[postfix-master.git] / postfix-master / announcements / 20080814.html
blob57bb8ca6a3d5b16e79e344c26fb10bcc5e21cd4c
1 <!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
2 "http://www.w3.org/TR/html4/loose.dtd">
4 <html>
6 <head>
8 <title> Postfix local privilege escalation via hardlinked symlinks </title>
10 <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
12 </head>
14 <body>
16 <h1> Postfix local privilege escalation via hardlinked symlinks </h1>
18 <p>
19 An on-line version of this announcement is available at
20 <a href="http://www.postfix.org/announcements/20080814.html">http://www.postfix.org/announcements/20080814.html</a>
21 </p>
23 <h2> 0. Summary </h2>
25 <p>
26 Solaris and Linux file system behavior has changed over
27 time, breaking one of the assumptions in Postfix. See below for a
28 description of the behavior and how it disagrees with standards.
29 </p>
31 <p>
32 Postfix is not affected on systems with standard (POSIX, X/Open)
33 file system behavior, i.e. *BSD, AIX, MacOS, HP-UX, and very old
34 Sun/Linux systems. The fix and workarounds are simple.
35 </p>
37 <p>
38 There are efforts to get the non-standard behavior approved by
39 standards (a function called llink). Today's fix for Solaris, Linux
40 etc. also makes Postfix future-proof for such changes.
41 </p>
43 <h2> 1. Discussion </h2>
45 <p>
46 Sebastian Krahmer of SuSE has found a privilege escalation problem.
47 On some systems an attacker can hardlink a root-owned symlink to
48 for example /var/mail, and cause Postfix to append mail to existing
49 files that are owned by root or non-root accounts. This can happen
50 on operating systems with specific non-standard behavior.
51 </p>
53 <p>
54 Symlinks (symbolic links) implement aliasing for UNIX pathnames.
55 They were introduced with 4.2BSD UNIX in 1983, and were adopted by
56 other UNIX systems in the course of time. Hardlinks are older and
57 implement the primary mechanism for accessing file system objects.
58 </p>
60 <p>
61 In some UNIX systems, the link(symlink, newpath) operation has
62 changed over time: instead of recursively following the symlink and
63 creating a hardlink to the file thus found, it creates a hardlink
64 to the symlink itself. This behavior disagrees with, for example,
65 the POSIX.1-2001 and X/Open XPG4v2 standards, and is the default
66 on current Solaris, IRIX and Linux systems. On systems with this
67 non-standard behavior, Postfix may be vulnerable depending on how
68 it is configured.
69 </p>
71 <p>
72 Postfix allows a root-owned symlink as a local mail destination,
73 so that mail can be delivered to e.g. /dev/null which is a symlink
74 on Solaris.
75 </p>
77 <h2> 2. What configurations are (not) affected </h2>
79 <p>
80 A configuration is considered affected when an attacker with local
81 access to a system can make Postfix append mail to an existing file
82 of a different user. Appendix A gives a procedure to determine if
83 a system is affected.
84 </p>
86 <p>
87 The following configurations are NOT affected: Postfix on FreeBSD
88 7.0, OpenBSD 4.3, NetBSD 4.0, MacOS X 10.5, AIX 5.3, HP-UX 11.11,
89 Solaris 1.x, Linux kernel 1.2.13, and other systems with standard
90 hardlink behavior. However, these systems may become affected when
91 they share file systems with hosts where users can create hardlinks
92 to symlinks.
93 </p>
95 <p>
96 Also not affected are the following configurations: a) maildir-style
97 delivery with the Postfix built-in local or virtual delivery agents;
98 b) mail delivery with non-Postfix local or virtual delivery agents;
99 c) mailbox-style delivery with the Postfix built-in virtual delivery
100 agent when virtual mailbox parent directories have no "group" or
101 other write permissions.
102 </p>
105 The following configurations are known to be affected on Linux
106 kernel &gt;= 2.0, Solaris &gt;= 2.0, OpenSolaris 11-2008.5, IRIX 6.5, and
107 other systems where users can create hardlinks to symlinks: a)
108 mailbox-style delivery with the Postfix built-in local delivery
109 agent; b) mailbox-style delivery with the Postfix built-in virtual
110 delivery agent when virtual mailbox parent directories have "group"
111 or other write permissions.
112 </p>
114 <h2> 3. Solution </h2>
117 If your system is affected, upgrade Postfix, apply the patch in
118 Appendix C, or apply one of the countermeasures in section 4.
119 </p>
122 Updated versions will be made available via <a href="http://www.postfix.org/">http://www.postfix.org/</a>
123 for Postfix versions 2.3, 2.4, 2.5, and 2.6. Individual vendors
124 will provide updates depending on their support policy.
125 </p>
127 <h2> 4. Countermeasures </h2>
130 Each of the following countermeasures will prevent privilege
131 escalation through Postfix via hardlinked symlinks:
132 </p>
135 1) Protect mailbox files (maildir files are not affected). The
136 script in Appendix B makes sure that the system mail spool directory
137 is owned by root, that the sticky bit is turned on, and that each
138 UNIX account has a mailbox file; it also has suggestions for virtual
139 mailbox file deliveries (again, maildir files are not affected).
140 </p>
143 2) Don't allow non-root users to create hardlinks to objects of
144 other users. This behavior is configurable on some systems.
145 </p>
147 <h2> Appendix A: Procedure to find out if a system is affected </h2>
150 As mentioned in section 2, not affected are maildir-style delivery
151 with the Postfix built-in local or virtual delivery agents, mail
152 delivery with non-Postfix local or virtual delivery agents, and
153 mailbox-style delivery with the built-in Postfix virtual delivery
154 agent when virtual mailbox parent directories have no "group" or
155 other write permissions.
156 </p>
159 To find out if a system may be affected, execute the following
160 commands as non-root user on a local file system:
161 </p>
163 <pre>
164 $ PATH=/bin:/usr/bin:$PATH
165 $ mkdir test
166 $ cd test
167 $ touch src
168 $ ln -s src dst1
169 $ ln dst1 dst2
170 $ ls -l
171 </pre>
174 For the test to be valid, all commands should complete without error.
175 </p>
178 The system is NOT affected when "ls -l" output shows one symlink
179 (dst1 -&gt; src) and two files (dst2, src) as in example A.1.
180 </p>
182 <pre>
183 Example A.1:
184 lrwxr-xr-x 1 user users 3 Mmm dd hh:mm dst1 -&gt; src
185 -rw-r--r-- 2 user users 0 Mmm dd hh:mm dst2
186 -rw-r--r-- 2 user users 0 Mmm dd hh:mm src
187 </pre>
190 However, the system may become affected when it shares file systems
191 with hosts where users can create hardlinks to symlinks as described
192 next.
193 </p>
196 The system is affected when "ls -l" output shows two symlinks and
197 one file as in example A.2, with the following Postfix configurations:
198 a) mailbox-style delivery with the Postfix built-in local delivery
199 agent; b) mailbox-style delivery with the Postfix built-in virtual
200 delivery agent when virtual mailbox parent directories have "group"
201 or other write permission.
202 </p>
204 <pre>
205 Example A.2:
206 lrwxrwxrwx 2 user users 3 Mmm dd hh:mm dst1 -&gt; src
207 lrwxrwxrwx 2 user users 3 Mmm dd hh:mm dst2 -&gt; src
208 -rw-r--r-- 1 user users 0 Mmm dd hh:mm src
209 </pre>
211 <h2> Appendix B: Procedure to protect mailbox files </h2>
214 This section describes one of the countermeasures (see section 4)
215 that eliminate the problem without updating Postfix.
216 </p>
219 The Perl script below hardens systems that use mailbox-style
220 deliveries with the Postfix built-in local delivery agent; it makes
221 sure that the system mailspool directory is root-owned and sticky,
222 and that every UNIX account has a mailbox file. The script assumes
223 that mailbox files are stored under /var/mail.
224 </p>
227 Similar actions would be needed for systems that use mailbox-style
228 delivery with the Postfix built-in virtual delivery agent, but this
229 is needed only when Postfix virtual mailbox parent directories have
230 "group" or other write permissions. Unfortunately, an automated
231 script for this cannot be made available due to the large variation
232 between Postfix configurations.
233 </p>
235 <pre>
236 #!/usr/bin/perl
238 # fix-mailspool - Make sure the mailspool directory is root-owned
239 # and sticky, and that every UNIX account has a mailbox file.
241 use Fcntl;
243 $debug = 0;
245 # Follow compatibility symlink.
246 $mailspool="/var/mail/";
248 chown(0, -1, $mailspool)
249 || die("can't set root ownership for $mailspool: $!\n");
251 chmod((stat($mailspool))[2] | 01000, $mailspool)
252 || die("can't set sticky bit for $mailspool: $!\n");
254 while(($name, $passwd, $uid, $gid, $quota,
255 $comment, $gcos, $dir, $shell) = getpwent()) {
256 print "user $name\n" if $debug;
257 $mailbox = ($mailspool . $name);
258 if (! -e $mailbox) {
259 print "create $mailbox\n" if $debug;
260 if (!sysopen(MAILBOX, $mailbox, (O_CREAT | O_RDWR | O_EXCL), 0600)) {
261 warn("can't create $mailbox: $!\n");
262 } else {
263 # XXX fchown() is not portable.
264 chown($uid, $gid, $mailbox) || warn("chown $mailbox: $!\n");
265 close(MAILBOX);
267 } elsif (! -f $mailbox) {
268 warn("$mailbox is not a regular file\n");
269 } elsif ((stat($mailbox))[4] != $uid) {
270 warn("$mailbox is not owned by $name\n");
272 </pre>
274 <h2> Appendix C: Source code patch </h2>
277 This patch is suitable for Postfix 2.0 and later. It presents the
278 least invasive change that eliminates the problem. Future Postfix
279 releases may adopt a different strategy.
280 </p>
283 The solution introduces the following change: when the target of
284 mail delivery is a symlink, the parent directory of that symlink
285 must now be writable by root only (in addition to the already
286 existing requirement that the symlink itself is owned by root).
287 This change will break legitimate configurations that deliver mail
288 to a symbolic link in a directory with less restrictive permissions.
289 </p>
291 <pre>
292 *** src/util/safe_open.c.orig Sun Jun 4 19:04:49 2006
293 --- src/util/safe_open.c Mon Aug 4 16:47:18 2008
294 ***************
295 *** 83,88 ****
296 --- 83,89 ----
297 #include &lt;msg.h&gt;
298 #include &lt;vstream.h&gt;
299 #include &lt;vstring.h&gt;
300 + #include &lt;stringops.h&gt;
301 #include &lt;safe_open.h&gt;
303 /* safe_open_exist - open existing file */
304 ***************
305 *** 138,150 ****
306 * for symlinks owned by root. NEVER, NEVER, make exceptions for symlinks
307 * owned by a non-root user. This would open a security hole when
308 * delivering mail to a world-writable mailbox directory.
310 else if (lstat(path, &lstat_st) &lt; 0) {
311 vstring_sprintf(why, "file status changed unexpectedly: %m");
312 errno = EPERM;
313 } else if (S_ISLNK(lstat_st.st_mode)) {
314 ! if (lstat_st.st_uid == 0)
315 ! return (fp);
316 vstring_sprintf(why, "file is a symbolic link");
317 errno = EPERM;
318 } else if (fstat_st-&gt;st_dev != lstat_st.st_dev
319 --- 139,167 ----
320 * for symlinks owned by root. NEVER, NEVER, make exceptions for symlinks
321 * owned by a non-root user. This would open a security hole when
322 * delivering mail to a world-writable mailbox directory.
324 + * Sebastian Krahmer of SuSE brought to my attention that some systems have
325 + * changed their semantics of link(symlink, newpath), such that the
326 + * result is a hardlink to the symlink. For this reason, we now also
327 + * require that the symlink's parent directory is writable only by root.
329 else if (lstat(path, &lstat_st) &lt; 0) {
330 vstring_sprintf(why, "file status changed unexpectedly: %m");
331 errno = EPERM;
332 } else if (S_ISLNK(lstat_st.st_mode)) {
333 ! if (lstat_st.st_uid == 0) {
334 ! VSTRING *parent_buf = vstring_alloc(100);
335 ! const char *parent_path = sane_dirname(parent_buf, path);
336 ! struct stat parent_st;
337 ! int parent_ok;
339 ! parent_ok = (stat(parent_path, &parent_st) == 0 /* not lstat */
340 ! && parent_st.st_uid == 0
341 ! && (parent_st.st_mode & (S_IWGRP | S_IWOTH)) == 0);
342 ! vstring_free(parent_buf);
343 ! if (parent_ok)
344 ! return (fp);
346 vstring_sprintf(why, "file is a symbolic link");
347 errno = EPERM;
348 } else if (fstat_st-&gt;st_dev != lstat_st.st_dev
349 </pre>
351 </body>
353 </html>