...
Temporary files are commonly used for auxiliary storage for data that does not need to, or otherwise cannot, reside in memory and also as a means of communicating with other processes by transferring data through the file system. For example, one process will create a temporary file in a shared directory with a well-known name or a temporary name that is communicated to collaborating processes. The file then can be used to share information among these collaborating processes.
This practice is a dangerous practice because a well-known file in a shared directory can be easily hijacked or manipulated by an attacker. Mitigation strategies include the following:
...
Because the name is hard coded and consequently neither unique nor unpredictable, an attacker need only replace a file with a symbolic link, and the target file referenced by the link is opened and truncated.
The following This noncompliant code example attempts to remedy the problem by generating the file name at runtime using tmpnam()
. The C tmpnam()
function generates a string that is a valid file name and that is not the same as the name of an existing file. Files created using strings generated by the tmpnam()
function are temporary in that their names should not collide with those generated by conventional naming rules for the implementation. The function is potentially capable of generating TMP_MAX
different strings, but any or all of them may already be in use by existing files.
...
The next noncompliant code example attempts to remedy the problem by using the POSIX open()
function and providing a mechanism to indicate whether an existing file has been opened for writing or a new file has been created [Open Group 2004IEEE Std 1003.1:2013]. If the O_CREAT
and O_EXCL
flags are used together, the open()
function fails when the file specified by file_name
already exists. To prevent an existing file from being opened and truncated, include the flags O_CREAT
and O_EXCL
when calling open()
:
...
Nonnormative text in the C Standard, subclause K.3.5.1.2 [ISO/IEC 9899:2011], also recommends the following:
Implementations should take care in choosing the patterns used for names returned by
tmpnam_s
. For example, making a thread id part of the names avoids the race condition and possible conflict when multiple programs run simultaneously by the same user generate the same temporary file names.
If implemented, this reduces the space for unique names is reduced and increases the predictability of the resulting names is increased. In general, Annex K does not establish any criteria for the predictability of names. For example, the name generated by the tmpnam_s
function from Microsoft Visual Studio consists of a program-generated file name and, after the first call to tmpnam_s()
, a file extension of sequential numbers in base 32 (.1-.1vvvvvu).
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> #include <stdlib.h> void func(void) { char file_name[] = "tmp-XXXXXX"; int fd; if (!mktemp(file_name)) { /* Handle error */ } /* A TOCTOU race condition exists here */ fd = open(file_name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0600); if (fd < 0) { /* Handle error */ } } |
The mktemp()
function has been is marked "LEGACY" in the Open Group Base Specifications Issue 6 [Open Group 2004]. The manual page for mktemp()
gives more detail:
...
It should be possible to open at least TMP_MAX
temporary files during the lifetime of the program. (This limit may be shared with tmpnam()
.) Subclause 7.21.4.4 paragraph 6 of , paragraph 6, of the C Standard allows for the value of the macro TMP_MAX
to be as small as 25.
...
It should be possible to open at least TMP_MAX_S
temporary files during the lifetime of the program. (This limit may be shared with tmpnam_s()
.) The value of the macro TMP_MAX_S
is required to be only 25 [ISO/IEC 9899:2011].
The C Standard subclause Standard, subclause K3.5.1.2, paragraph 7 notes 7, notes the following regarding the use of tmpfile_s()
instead of tmpnam_s()
[ISO/IEC 9899:2011]:
...
The tmpfile_s()
function should not be used with implementations that create temporary files in a shared directory, such as /tmp
or C:
, because the function does not allow the user to specify a directory in which the temporary file should be created.
...
In many older implementations, the name is a function of process ID and time, so it is possible for the attacker to predict the name and create a decoy in advance. FreeBSD changed the mk*temp()
family to eliminate the PID process ID component of the file name and replace the entire field with base-62 encoded randomness. This raises the number of possible temporary files for the typical use of six X
's significantly, meaning that even mktemp()
with six X
's is reasonably (probabilistically) secure against guessing except under frequent usage [Kennaway 2000].
Exceptions
FIO43-EX0EX1: The Annex K tmpfile_s()
function can be used if all the targeted implementations create temporary files in secure directories.
...
[Austin Group 2008] | |
[HP 2003] | |
[IEEE Std 1003.1:2013] | System Interfaces: open |
[ISO/IEC 9899:2011] | Subclause K.3.5.1.2, "The tmpnam_s Function"Subclause 7.21.4.4, "The tmpnam Function |
[Kennaway 2000] | |
[Open Group 2004] | mktemp() mkstemp() open() |
[Seacord 2013] | Chapter 3, "Pointer Subterfuge" Chapter 8, "File I/O" |
[Viega 2003] | Section 2.1, "Creating Files for Temporary Use" |
[Wheeler 2003] | Chapter 7, "Structure Program Internals and Approach" |
...