"Fossies" - the Fresh Open Source Software Archive 
Member "tmpreaper-1.6.17/debian/README.security" (17 Aug 2007, 19957 Bytes) of package /linux/misc/tmpreaper_1.6.17.tar.gz:
As a special service "Fossies" has tried to format the requested text file into HTML format (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
1 Security implications of tmpreaper
2 ----------------------------------
3
4 Below is a message that was forwarded to me, concerning vulnerabilities in
5 tmpwatch, of which tmpreaper is a fork and may thus share vulnerabilities
6 with.
7
8 IMO there are a couple of things wrong about the points in the text, which I
9 could not resolve in discussion with Joey Hess (my direct questions were
10 avoided by responding that I clearly didn't understand the issues -- which is
11 (a) faulty argumentation leading me to believe that they themselves were
12 incapable of explaining, and (b) wrong). For example, the text speaks of
13 "creation time"; I responded that there is no such thing in POSIX, only the
14 inode change time (which is also changed if you link the file, or rename it, or
15 change the permissions, or even when you delete it). I never got an answer on
16 that.
17
18 Here's one thing that was said by Joey:
19
20 Suppose a victim program is setuid, and you want to attack it to
21 get root. So you run it, let it open a temp file, and SIGSTOP it.
22 Now let it sit, suspended, for x days. Tmpreaper then removes the
23 temp file, since mtime, atime, and ctime are all x days. Now replace
24 the tmp file with something crafted to buffer overflow or otherwise
25 exploit the program, and SIGCONT it so it runs, accesses the tmp file
26 it thinks it just made, and is exploited.
27
28 There is no known fix to this hole. You can play with fuser and
29 limit it to a certain smaller class of victim programs, but not
30 entirely close it. It's also pretty easy to exploit on any machine
31 with a large uptime and lots of processes to hide in.
32
33 This calls for the setuid program to close the file, and then open it again
34 without checking the owner, inode number, etc. This also means that fuser
35 won't help a bit (the file must be closed, remember? So why mention it). That
36 in my book is a problem of the setuid program, not of tmpreaper, as this is
37 nothing that won't happen either if the admin does "rm -rf /tmp/*" now and
38 again, despite following claim that that is a preferable alternative to
39 tmpreaper:
40
41 At least admins running rm -rf is something that happens
42 unpredictably ...
43
44
45 Another thing that was said:
46
47 tmp{reaper,watch} use lstat() to look at file creation time. Then they
48 use unlink() to delete it. Two system calls, therefore there is a
49 time period between them in which an attacker may do the very unlikely
50 trick described in the paper of removing its decoy file and letting
51 mkstemp put in a file by the same name, which is then deleted.
52 At this point the attacker can replace the temp file with their own
53 creation, and mess with the program that expects its own temp file there.
54
55 There's that mythical "file creation time" thing again...
56 Besides that, he's right in saying that it's very unlikely to manage to squeeze
57 inbetween those two system calls. Bookies will give you _very_ large odds on
58 that...
59
60 1. you need to be able to predict days in advance what pseudo-random name
61 mkstemp will generate at that precise moment in time. From the message
62 below:
63 ... While mkstemp() names are guaranteed to be unique, they shouldn't be
64 expected to be unpredictable - in most implementations, the name is a
65 function of process ID and time - so it is possible for the attacker to
66 guess it and create a decoy in advance. ...
67 Guessing what process ID a victim process will have a number of days in
68 advance on a multiuser system is a pretty neat trick.
69
70 2. you then need to be able to remove that file at exactly the moment
71 tmpreaper after tmpreaper has used lstat(), but before it does the unlink().
72
73 3. mkstemp (in the daemon/whatever that you're trying to attack) will
74 have to create the file with the correct name, still before tmpreaper's
75 unlink() call.
76
77 4. now tmpreaper has to execute the unlink() call, before the
78 daemon/whatever has gone on and used the tmpfile for its intended purpose.
79
80 5. you now have to create the file again, with the correct name and
81 contents.
82
83 6. the daemon/whatever has to close and reopen the file without checking
84 its owner, permission, inode number, etc. and then use the data therein.
85
86 This would be an incredible feat to accomplish, needing unbelievable amounts
87 of luck in timing (skill is not an issue; timing is), requiring also an app
88 running with sufficient privileges to do harm that uses its tempfiles
89 insecurely in the first place. In such a scenario, is the problem with
90 tmpreaper? I don't think so.
91
92
93 The scenario described is so inprobable that if you're worried about that, you
94 should buy a lottery ticket every week: the chance that *someone* wins the
95 lottery is 100% (well, with a lot of lotteries :-); the chance that this will
96 ever happen is less.
97
98
99 There's also a discussion below about the problems when two tmpwatch processes
100 are running simultaneously (hence would also apply to tmpreaper as well).
101 Tmpreaper avoids this by not allowing itself to run for more than one minute.
102 There's also a random delay before processing (when invoked with --delay as is
103 done in the default cron.daily script) to make it harder to determine when
104 tmpreaper runs exactly.
105 See also the tmpreaper manpage for other precautions taken.
106
107 Of course, if you still are worried, you are of course free to purge tmpreaper
108 from your system, and do a regular "rm -rf /tmp/*" if you think that's
109 safer...
110
111
112 Below is the message that started this discussion, and judge for yourself.
113
114
115
116 Paul Slootman 2003-05-21, updated 2003-06-02
117
118
119 From: Michal Zalewski <lcamtuf@ghettot.org>
120 Date: Fri, 20 Dec 2002 09:30:30 -0800 (PST)
121 To: bugtraq@securityfocus.com, <vulnwatch@vulnwatch.org>,
122 <full-disclosure@netsys.com>
123 Subject: [RAZOR] Problems with mkstemp()
124
125 Common use of 'tmpwatch' utility and its counterparts triggers race
126 conditions in many applications
127
128 Michal Zalewski <lcamtuf@razor.bindview.com>, 12/05/2002
129 Copyright (C) 2002 by Bindview Corporation
130
131
132 1) Scope and exposure info
133 --------------------------
134
135 A common practice of installing 'tmpwatch' utility or similar software
136 configured to sweep the /tmp directory on Linux and unix systems can
137 compromise secure temporary file creation mechanisms in certain applications,
138 creating a potential privilege escalation scenario. This document briefly
139 discusses the exposure, providing some examples, and suggesting possible
140 workarounds.
141
142 It is believed that many unix operating systems using 'tmpwatch' or an
143 equivalent are affected. Numerous Linux systems, such as Red Hat, that ship
144 with cron daemon running and 'tmpwatch' configured to sweep /tmp are
145 susceptible to the attack.
146
147
148 2) Application details
149 ----------------------
150
151 'Tmpwatch' is a handy utility that removes files which haven't been
152 accessed for a period of time. It was developed by Erik Troan and
153 Preston Brown of Red Hat Software, and, with time, has become a
154 component of many Linux distributions, also ported to platforms
155 such as Solaris, *BSD or HP/UX. By default, it is installed with a
156 crontab entry that sweeps /tmp directory on a daily basis, deleting
157 files that have not been accessed for the past few days.
158
159 An alternative program, called 'stmpclean' and authored by Stanislav
160 Shalunov, is shipped with *BSD systems and some Linux distributions
161 to perform the same task, and some administrators deploy other tools or
162 scripts for this purpose.
163
164
165 3) Vulnerability details
166 ------------------------
167
168 Numerous applications rely either on mkstemp() or custom O_EXCL file
169 creation mechanisms to store temporary data in the /tmp directory
170 in a secure manner. Of those, certain programs run with elevated
171 privileges, or simply at a different privilege level than the caller.
172
173 The exposure is a result of a common misconception, promoted by almost
174 all secure programming tutorials and manpages, that /tmp files created
175 with mkstemp(), granted that umask() settings were proper, are
176 safe against hijacking and common races. The file, since it is created
177 in a sticky-bit directory, indeed cannot be removed or replaced by
178 the attacker running with different non-root privileges, but since
179 many operating systems feature 'tmpwatch'-alike solutions, the only
180 thing that can and should be considered safe in /tmp is the descriptor
181 returned by mkstemp() - the filename should not be relied upon. There
182 are two major reasons for this:
183
184 1) unlink() races
185
186 It is very difficult to remove a file without risking a potential
187 race (see section 4). 'Tmpwatch' does not take any extra measures to
188 prevent races, and probes file creation time using lstat(). Based on this
189 data, it calls unlink() as root. Problem is, on a multitasking system,it
190 is possible for the attacker to get some CPU time between those two system
191 calls, remove the old "decoy" file that has been probed with lstat(), and
192 let the application of his choice create its own temporary file under this
193 name. While mkstemp() names are guaranteed to be unique, they shouldn't be
194 expected to be unpredictable - in most implementations, the name is a
195 function of process ID and time - so it is possible for the attacker to
196 guess it and create a decoy in advance. Once the tmpwatch process is
197 resumed, the file is immediately removed, based on the result of
198 earlier lstat() on the old, no longer existing file.
199
200 While this three-component race requires very precise timing, it
201 is possible to try a number of times in a single 'tmpwatch' run if
202 enough decoy files are created by the attacker. Additionally, since
203 each step of the attack would result in a corresponding filesystem
204 change, it is fairly easy to carefully measure timings and
205 coordinate the attack.
206
207 If the attacker cannot make the application run at the same time
208 as 'tmpwatch' - for example, if the application is executed by
209 hand by the administrator, or is running from cron - 'tmpwatch'
210 itself can be artificially delayed for almost an arbitrary amount
211 of time by creating and continuously expending an elaborate directory
212 structure in /tmp using hard links (to preserve access times of
213 files) and running other processes that demand disk access and
214 cache space to slow down the process.
215
216 'Stmpclean' offers additional protection against races by not removing
217 root-owned files and temporarily dropping privileges when removing
218 the file to match the owner of lstat()ed resource. Unfortunately,
219 not removing root files is a considerable drawback, and there is still
220 a potential for a race using carefully crafted hard links to a file
221 owned by the victim and two concurrent 'stmpclean' processes:
222
223 - the attacker links /tmp/foo to ~victim/.bash_profile
224 - tmpwatch #1 does lstat() on /tmp/foo and setuid victim
225 - tmpwatch #2 does lstat() on /tmp/foo and setuid victim
226 - tmpwatch #1 does unlink("/tmp/foo")
227 - victim application creates /tmp/foo at uid==victim
228 - tmpwatch #2 does unlink("/tmp/foo") and succeeds
229 - the attacker creates /tmp/foo
230 - victim application proceeds
231
232 On certain systems such as Owl Linux, the attack will be not possible
233 due to hardlink limits imposed on sticky-bit directories.
234
235 2) suspended processes and 'legitimate' file removal
236
237 Here, all conventional measures that could be exercised by /tmp cleaners
238 fail miserably. A vulnerable application can be often delayed or suspended
239 after mkstemp() / open() - for example, a setuid program can be
240 stopped with SIGSTOP and resumed with SIGCONT. If the application is
241 suspended for long enough, its temporary files are likely to be
242 removed. This method requires much less precision, but is also
243 more time-consuming and has a more limited scope (interactive
244 applications only).
245
246 Note that it is sometimes possible to delay the execution of
247 a daemon - client wait, considerable I/O or CPU loads, and subsequent
248 mkstemp() calls can be all used to achieve the effect. The
249 feasibility and efficiency is low, but the potential issue
250 exists. Some client applications that are often left unattended
251 and create temporary files - such as mail/news clients, web
252 browsers, irc clients, etc - can also be used to compromise
253 other accounts on the machine.
254
255 Not all applications are prone to the problem just because mkstemp()
256 is used to create files in /tmp; if the file name is not used to perform
257 any sensitive operations with some extra privileges afterward (read,
258 write, chown, chmod, link/rename, etc), and only the descriptor is
259 being used, the application is safe. This practice is often exercised by
260 programmers who want to avoid leaving dangling temporary files in case
261 the program is aborted or crashes. Similarly, if the application uses
262 temporary files improperly, but does not rely on their contents and does
263 not attempt to access them with higher privileges, the application is
264 secure in that regard.
265
266 Applications that run with higher privileges and reopen their
267 /tmp temporary files for reading or writing, call chown(), chmod() on
268 them, rename or link the file to replace some sensitive information, and
269 so on, are exposed. It is worth mentioning that a popular 'mktemp'
270 utility coming from OpenBSD passes only the filename to the
271 caller shell script, thus rendering almost all scripts using it
272 fundamentally flawed. If the script is being run as a cron job or
273 other administrative task, and mktemp is used, the system can be likely
274 compromised by replacing the file after mktemp and prior to any write
275 to the file. In the example quoted in the documentation for mktemp(1):
276
277 TMPFILE=`mktemp /tmp/$0.XXXXXX` || exit 1
278 echo "program output" >> $TMPFILE
279
280 ...the attacker would want to replace temporary file right before
281 'echo', causing the text "program output" to be appended to a target
282 file of his choice using symlinks or hardlinks; or, if it is more
283 desirable, he'd spoof file contents to cause the program to misbehave.
284
285 Another example of the problem is a popular logrotate utility,
286 coded - ironically - by Erik Troan, one of co-authors of 'tmpwatch'
287 itself. The program suffered /tmp races in the past, but later
288 switched to mkstemp(). The following sequence is used to handle
289 post-rotation shell commands specified in config files:
290
291 open("/tmp/logrotate.wvpNmP", O_WRONLY|O_CREAT|O_EXCL, 0700) = 6
292 ...
293 write(6, "#!/bin/sh\n\n", 11) = 11
294 write(6, "\n\t/bin/kill -HUP `cat /var/lock/"..., 79) = 79
295 close(6) = 0
296 ... fork, etc ...
297 execve("/bin/sh", ["sh", "-c", "/bin/sh /tmp/logrotate.wvpNmP" ...
298
299 Obviously, if the attacker can have /tmp/logrotate.* replaced in
300 between mkstemp() (represented as open() syscall above) and the
301 point where another process is spawned, a shell interpreter is invoked,
302 then executes another copy of the shell interpreter (apparent
303 programmer's mistake) and finally reads the input file - which is
304 a considerable chunk of time - the shell will be called with
305 attacker-supplied commands to be executed with root privileges.
306
307 On Red Hat, logrotate is executed from crontab on a daily basis, in
308 a sequence before 'tmpwatch', and the easiest option for the attacker
309 is to maintain a still-running tmpwatch process from the previous day
310 to exploit the condition. On systems where those programs are not
311 executed sequentially - for example, when both programs are listed
312 directly in /etc/crontab - the attack requires less precision.
313
314
315 4) Workarounds and fixes:
316 -------------------------
317
318 Recommended immediate workaround is to discontinue the use of 'tmpwatch'
319 or equivalent to sweep /tmp directory if this service is not necessary.
320
321 For applications that rely on TMPDIR or a similar environment
322 variable, setting it to a separate, not publicly writable directory
323 is often a viable solution. Note that not all applications honor
324 this setting.
325
326 In terms of a permanent solution, two different attack vectors have
327 to be addressed, as discussed in section 3:
328
329 1) unlink() race
330
331 The proper way to remove files in sticky-bit directories while
332 minimizing the risk is as follows:
333
334 a) lstat() the file to be removed
335 b) if owned by root, do not remove
336 c) if st_nlink > 1, do not remove
337 d) if owned by user, temporarily change privileges to this user
338 e) attempt unlink()
339 f) if failed, warn about a possible race condition
340 g) switch privileges back to root
341
342 With the exception of step c, this is implemented in 'stmpclean'.
343 Unfortunately, step c is crucial on systems that do not have
344 restricted /tmp kernel patches from Openwall (http://www.openwall.com),
345 otherwise, there is a potential for fooling the algorithm by supplying
346 a hard link to a file owned by the victim, as discussed in section 3.
347 This approach has several drawbacks - such as the fact root-owned files
348 will not be removed. Other solution is to modify applications that
349 generate filenames on their own, and to modify mkstemp(), to generate
350 names that are not only unique, but not feasible to predict.
351
352 Another suggestion is to implement a funlink() capability in the kernel
353 of the operating system in question, to allow race-free file removal,
354 thus removing the non-root ownership requirement for the method described
355 above, and simplifying the approach. A skeleton patch to implement
356 funlink() semantics and make sure the file being removed is the file
357 opened and fstat()ed previously is available at:
358 http://lcamtuf.coredump.cx/soft/linux-2.4-funlink.diff (this and
359 other patches are not endorsed by RAZOR in any way).
360
361 2) suspended process and 'legitimate' file removal
362
363 This issue is fairly difficult to address. The most basic idea is
364 to use a special naming scheme for temporary files to avoid deletion -
365 unfortunately, this seems to defeat the purpose of using tmpwatch-alike
366 solutions in the first place.
367
368 An alternative approach, which is to enforce separate temporary
369 directories for certain applications, either process-, session- or uid-
370 based, is generally fairly controversial, and raises some concerns.
371 Advisory separation is generally acceptable, but there are a number of
372 applications that do not accept TMPDIR setting, and a widespread practice
373 of using /tmp in in-house applications. Mandatory separation (kernel
374 modification) raises compatibility concerns and is generally approached
375 with skepticism - no implementation has become particularly popular.
376
377 Ideally, implementators should carefully audit their sources. It is
378 recommended for privileged applications to use private temporary
379 directories for sensitive files, if possible; if using /tmp is necessary,
380 extra caution has to be exercised to avoid referencing the file by name.
381 Note that comparing the descriptor and a reopened file to verify inode
382 numbers, creation times or file ownership is not sufficient - please refer
383 to "Symlinks and Cryogenic Sleep" by Olaf Kirch, available at
384 http://www.opennet.ru/base/audit/17.txt.html .
385
386 It's worth noticing that 'tmpwatch' offers a -s option, which causes the
387 program to run the 'fuser' command to prevent removal of files that are
388 currently open. At first sight, this could be an effective way to solve the
389 problem. Unfortunately, this is not true, since many applications close the
390 file for a period of time before reopening (including logrotate and
391 mktemp(1)).
392
393
394 5) Credits and thanks
395 ---------------------
396
397 Thanks to Solar Designer for interesting discussions on the subject,
398 to Matt Power for useful feedback, and to RAZOR team in general for making
399 this publication possible.